Sqlite: Improve constraint support

Now you can add more than one constraint. And we added some
new constraints too.

Change-Id: I849d2d2ef6e44c897a65ff2bdfe8d172a345c991
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2020-05-13 20:29:49 +02:00
committed by Tim Jenssen
parent a86fd58e40
commit c4bbc74e37
12 changed files with 497 additions and 242 deletions

View File

@@ -41,16 +41,11 @@ void CreateTableSqlStatementBuilder::setTableName(Utils::SmallString &&tableName
void CreateTableSqlStatementBuilder::addColumn(Utils::SmallStringView columnName,
ColumnType columnType,
Contraint constraint,
ForeignKey &&foreignKey)
Constraints &&constraints)
{
m_sqlStatementBuilder.clear();
m_columns.emplace_back(Utils::SmallStringView{},
columnName,
columnType,
constraint,
std::move(foreignKey));
m_columns.emplace_back(Utils::SmallStringView{}, columnName, columnType, std::move(constraints));
}
void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns)
@@ -121,30 +116,90 @@ Utils::SmallStringView actionToText(ForeignKeyAction action)
return "";
}
void appendForeignKey(Utils::SmallString &columnDefinitionString, const ForeignKey &foreignKey)
class ContraintsVisiter
{
columnDefinitionString.append(" REFERENCES ");
columnDefinitionString.append(foreignKey.table);
public:
ContraintsVisiter(Utils::SmallString &columnDefinitionString)
: columnDefinitionString(columnDefinitionString)
{}
if (foreignKey.column.hasContent()) {
columnDefinitionString.append("(");
columnDefinitionString.append(foreignKey.column);
void operator()(const Unique &) { columnDefinitionString.append(" UNIQUE"); }
void operator()(const PrimaryKey &) { columnDefinitionString.append(" PRIMARY KEY"); }
void operator()(const ForeignKey &foreignKey)
{
columnDefinitionString.append(" REFERENCES ");
columnDefinitionString.append(foreignKey.table);
if (foreignKey.column.hasContent()) {
columnDefinitionString.append("(");
columnDefinitionString.append(foreignKey.column);
columnDefinitionString.append(")");
}
if (foreignKey.updateAction != ForeignKeyAction::NoAction) {
columnDefinitionString.append(" ON UPDATE ");
columnDefinitionString.append(actionToText(foreignKey.updateAction));
}
if (foreignKey.deleteAction != ForeignKeyAction::NoAction) {
columnDefinitionString.append(" ON DELETE ");
columnDefinitionString.append(actionToText(foreignKey.deleteAction));
}
if (foreignKey.enforcement == Enforment::Deferred)
columnDefinitionString.append(" DEFERRABLE INITIALLY DEFERRED");
}
void operator()(const NotNull &) { columnDefinitionString.append(" NOT NULL"); }
void operator()(const DefaultValue &defaultValue)
{
columnDefinitionString.append(" DEFAULT ");
switch (defaultValue.value.type()) {
case Sqlite::ValueType::Integer:
columnDefinitionString.append(
Utils::SmallString::number(defaultValue.value.toInteger()));
break;
case Sqlite::ValueType::Float:
columnDefinitionString.append(Utils::SmallString::number(defaultValue.value.toFloat()));
break;
case Sqlite::ValueType::String:
columnDefinitionString.append("\"");
columnDefinitionString.append(defaultValue.value.toStringView());
columnDefinitionString.append("\"");
break;
}
}
void operator()(const DefaultExpression &defaultexpression)
{
columnDefinitionString.append(" DEFAULT (");
columnDefinitionString.append(defaultexpression.expression);
columnDefinitionString.append(")");
}
if (foreignKey.updateAction != ForeignKeyAction::NoAction) {
columnDefinitionString.append(" ON UPDATE ");
columnDefinitionString.append(actionToText(foreignKey.updateAction));
void operator()(const Collate &collate)
{
columnDefinitionString.append(" COLLATE ");
columnDefinitionString.append(collate.collation);
}
if (foreignKey.deleteAction != ForeignKeyAction::NoAction) {
columnDefinitionString.append(" ON DELETE ");
columnDefinitionString.append(actionToText(foreignKey.deleteAction));
void operator()(const GeneratedAlways &generatedAlways)
{
columnDefinitionString.append(" GENERATED ALWAYS AS (");
columnDefinitionString.append(generatedAlways.expression);
columnDefinitionString.append(")");
if (generatedAlways.storage == Sqlite::GeneratedAlwaysStorage::Virtual)
columnDefinitionString.append(" VIRTUAL");
else
columnDefinitionString.append(" STORED");
}
if (foreignKey.enforcement == Enforment::Deferred)
columnDefinitionString.append(" DEFERRABLE INITIALLY DEFERRED");
}
Utils::SmallString &columnDefinitionString;
};
} // namespace
void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
{
@@ -154,19 +209,10 @@ void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
for (const Column &column : m_columns) {
Utils::SmallString columnDefinitionString = {column.name, " ", column.typeString()};
switch (column.constraint) {
case Contraint::PrimaryKey:
columnDefinitionString.append(" PRIMARY KEY");
break;
case Contraint::Unique:
columnDefinitionString.append(" UNIQUE");
break;
case Contraint::ForeignKey:
appendForeignKey(columnDefinitionString, column.foreignKey);
break;
case Contraint::NoConstraint:
break;
}
ContraintsVisiter visiter{columnDefinitionString};
for (const Constraint &constraint : column.constraints)
mpark::visit(visiter, constraint);
columnDefinitionStrings.push_back(columnDefinitionString);
}