aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:07:47 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:07:47 -0500
commit558b1e35fd0777ac97763c1b28056ac984e583e7 (patch)
tree1eb2557119a117ea76535c89cd14a49e510b96bf /SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp
parentc22eb635c11fd45f9c30f911d70e1d79111a49ce (diff)
parent1fdc150116cad39aae5c5da407c3312b47a59e3a (diff)
Update upstream source from tag 'upstream/3.3.3+dfsg1'
Update to upstream version '3.3.3+dfsg1' with Debian dir 9a301fff4922aed2fec0c04c7d011947168c42f1
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp')
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp b/SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp
new file mode 100644
index 0000000..308b868
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/constraints/columngeneratedpanel.cpp
@@ -0,0 +1,227 @@
+#include "columngeneratedpanel.h"
+#include "ui_columngeneratedpanel.h"
+#include "parser/parser.h"
+#include "parser/keywords.h"
+#include "parser/lexer.h"
+#include "uiutils.h"
+#include "schemaresolver.h"
+#include <QDebug>
+
+ColumnGeneratedPanel::ColumnGeneratedPanel(QWidget *parent) :
+ ConstraintPanel(parent),
+ ui(new Ui::ColumnGeneratedPanel)
+{
+ ui->setupUi(this);
+ init();
+}
+
+ColumnGeneratedPanel::~ColumnGeneratedPanel()
+{
+ delete ui;
+}
+
+void ColumnGeneratedPanel::changeEvent(QEvent *e)
+{
+ QWidget::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool ColumnGeneratedPanel::validate()
+{
+ if (!ui->exprEdit->isSyntaxChecked())
+ {
+ setValidState(ui->exprEdit, false, tr("Enter the column value generating expression."));
+ return false;
+ }
+
+ // First check if we already validated this text.
+ // This method is called twice, by both errors checking and syntax highlighting,
+ // because signal for textChange() is connected with call to updateValidation().
+ QString text = ui->exprEdit->toPlainText();
+ if (!lastValidatedText.isNull() && lastValidatedText == text)
+ return lastValidationResult;
+
+ lastValidatedText = text;
+
+ bool nameOk = true;
+ if (ui->namedCheck->isChecked() && ui->namedEdit->text().isEmpty())
+ nameOk = false;
+
+ bool exprOk = !ui->exprEdit->toPlainText().trimmed().isEmpty() &&
+ !ui->exprEdit->haveErrors();
+
+ QString exprError;
+ if (exprOk)
+ {
+ // Everything looks fine, so lets do the final check - if the value is correct for use as generated column expression in SQLite.
+ static QString tempDdlExprTpl = QStringLiteral("CREATE TEMP TABLE %1 (aaa, %2 GENERATED ALWAYS AS (%3));");
+ static QString dropTempDdl = QStringLiteral("DROP TABLE %1;");
+
+ SqliteCreateTable::Column* columnStmt = dynamic_cast<SqliteCreateTable::Column*>(constraint->parentStatement());
+ SqliteCreateTable* createTableStmt = dynamic_cast<SqliteCreateTable*>(columnStmt->parentStatement());
+
+ QStringList preparedColNames;
+ QString thisColumnName = columnStmt->name;
+ for (SqliteCreateTable::Column* column : createTableStmt->columns)
+ {
+ if (column->name == thisColumnName)
+ continue;
+
+ preparedColNames << wrapObjIfNeeded(column->name);
+ }
+ preparedColNames << wrapObjIfNeeded(thisColumnName);
+
+ QString tableName = getTempTable();
+ QString tempDdl = tempDdlExprTpl.arg(tableName, preparedColNames.join(", "), ui->exprEdit->toPlainText());
+ SqlQueryPtr res = db->exec(tempDdl);
+ if (res->isError())
+ {
+ exprOk = false;
+ exprError = tr("Invalid value generating expression: %1.")
+ .arg(res->getErrorText());
+ }
+
+ db->exec(dropTempDdl.arg(tableName));
+ } else
+ exprError = tr("Invalid value generating expression.");
+
+ setValidState(ui->exprEdit, exprOk, exprError);
+ setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint."));
+
+ lastValidationResult = (exprOk && nameOk);
+ return lastValidationResult;
+}
+
+bool ColumnGeneratedPanel::validateOnly()
+{
+ ui->exprEdit->checkSyntaxNow();
+ return validate();
+}
+
+void ColumnGeneratedPanel::constraintAvailable()
+{
+ if (constraint.isNull())
+ return;
+
+ readConstraint();
+ updateVirtualSql();
+ validateOnly();
+}
+
+void ColumnGeneratedPanel::storeConfiguration()
+{
+ if (constraint.isNull())
+ return;
+
+ SqliteCreateTable::Column::Constraint* constr = dynamic_cast<SqliteCreateTable::Column::Constraint*>(constraint.data());
+ constr->type = SqliteCreateTable::Column::Constraint::GENERATED;
+ storeExpr(constr);
+
+ if (ui->typeCheck->isChecked())
+ constr->generatedType = SqliteCreateTable::Column::Constraint::generatedTypeFrom(ui->typeCombo->currentText());
+ else
+ constr->generatedType = SqliteCreateTable::Column::Constraint::GeneratedType::null;
+
+ constr->generatedKw = ui->generatedKwCheck->isChecked();
+
+ if (ui->namedCheck->isChecked())
+ constr->name = ui->namedEdit->text();
+}
+
+void ColumnGeneratedPanel::storeExpr(SqliteCreateTable::Column::Constraint* constr)
+{
+ QString text = ui->exprEdit->toPlainText();
+ clear(constr);
+
+ Parser parser;
+ SqliteExpr* newExpr = parser.parseExpr(text);
+ newExpr->setParent(constraint.data());
+ constr->expr = newExpr;
+}
+
+void ColumnGeneratedPanel::clear(SqliteCreateTable::Column::Constraint* constr)
+{
+ if (constr->expr)
+ {
+ delete constr->expr;
+ constr->expr = nullptr;
+ }
+ constr->generatedKw = false;
+ constr->generatedType = SqliteCreateTable::Column::Constraint::GeneratedType::null;
+}
+
+void ColumnGeneratedPanel::init()
+{
+ setFocusProxy(ui->exprEdit);
+ ui->exprEdit->setShowLineNumbers(false);
+
+ connect(ui->namedCheck, SIGNAL(toggled(bool)), this, SIGNAL(updateValidation()));
+ connect(ui->namedEdit, SIGNAL(textChanged(QString)), this, SIGNAL(updateValidation()));
+ connect(ui->exprEdit, SIGNAL(textChanged()), this, SIGNAL(updateValidation()));
+ connect(ui->exprEdit, SIGNAL(errorsChecked(bool)), this, SIGNAL(updateValidation()));
+
+ connect(ui->namedCheck, SIGNAL(toggled(bool)), this, SLOT(updateState()));
+ connect(ui->typeCheck, SIGNAL(toggled(bool)), this, SLOT(updateState()));
+
+ ui->typeCombo->addItems(getGeneratedColumnTypes());
+
+ updateState();
+}
+
+void ColumnGeneratedPanel::readConstraint()
+{
+ SqliteCreateTable::Column::Constraint* constr = dynamic_cast<SqliteCreateTable::Column::Constraint*>(constraint.data());
+
+ constr->rebuildTokens();
+ if (constr->expr)
+ ui->exprEdit->setPlainText(constr->expr->detokenize());
+
+ QString typeValue = SqliteCreateTable::Column::Constraint::toString(constr->generatedType);
+ switch (constr->generatedType) {
+ case SqliteCreateTable::Column::Constraint::GeneratedType::STORED:
+ ui->typeCheck->setChecked(true);
+ break;
+ case SqliteCreateTable::Column::Constraint::GeneratedType::VIRTUAL:
+ ui->typeCheck->setChecked(true);
+ break;
+ case SqliteCreateTable::Column::Constraint::GeneratedType::null:
+ ui->typeCheck->setChecked(false);
+ typeValue = SqliteCreateTable::Column::Constraint::toString(SqliteCreateTable::Column::Constraint::GeneratedType::VIRTUAL);
+ break;
+ }
+ ui->typeCombo->setCurrentText(typeValue);
+
+ ui->generatedKwCheck->setChecked(constr->generatedKw);
+
+ if (!constr->name.isNull())
+ {
+ ui->namedCheck->setChecked(true);
+ ui->namedEdit->setText(constr->name);
+ }
+}
+
+void ColumnGeneratedPanel::updateVirtualSql()
+{
+ static QString sql = QStringLiteral("CREATE TABLE tab (col GENERATED ALWAYS AS (%1))");
+ ui->exprEdit->setDb(db);
+ ui->exprEdit->setVirtualSqlExpression(sql);
+}
+
+QString ColumnGeneratedPanel::getTempTable()
+{
+ SchemaResolver resolver(db);
+ return resolver.getUniqueName("sqlitestudio_temp_table");
+}
+
+void ColumnGeneratedPanel::updateState()
+{
+ ui->namedEdit->setEnabled(ui->namedCheck->isChecked());
+ ui->typeCombo->setEnabled(ui->typeCheck->isChecked());
+}