1 #include "sqlitecreatetable.h"
2 #include "parser/statementtokenbuilder.h"
3 #include "common/utils_sql.h"
4 #include "common/global.h"
5 
6 const QRegExp SqliteCreateTable::Column::GENERATED_ALWAYS_REGEXP = QRegExp("GENERATED\\s+ALWAYS");
7 
SqliteCreateTable()8 SqliteCreateTable::SqliteCreateTable()
9 {
10     queryType = SqliteQueryType::CreateTable;
11 }
12 
SqliteCreateTable(const SqliteCreateTable & other)13 SqliteCreateTable::SqliteCreateTable(const SqliteCreateTable& other) :
14     SqliteQuery(other), ifNotExistsKw(other.ifNotExistsKw), tempKw(other.tempKw), temporaryKw(other.temporaryKw),
15     database(other.database), table(other.table), withOutRowId(other.withOutRowId)
16 {
17     DEEP_COPY_COLLECTION(Column, columns);
18     DEEP_COPY_COLLECTION(Constraint, constraints);
19     DEEP_COPY_FIELD(SqliteSelect, select);
20 }
21 
SqliteCreateTable(bool ifNotExistsKw,int temp,const QString & name1,const QString & name2,const QList<Column * > & columns,const QList<Constraint * > & constraints)22 SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString &name1, const QString &name2, const QList<Column *> &columns, const QList<Constraint*>& constraints)
23     : SqliteCreateTable()
24 {
25     init(ifNotExistsKw, temp, name1, name2);
26     this->columns = columns;
27     for (Column* column : columns)
28         column->setParent(this);
29 
30     for (SqliteCreateTable::Constraint* constr : constraints)
31     {
32         if (this->constraints.size() > 0 &&
33             this->constraints.last()->type == SqliteCreateTable::Constraint::NAME_ONLY)
34         {
35             constr->name = this->constraints.last()->name;
36             delete this->constraints.takeLast();
37         }
38         this->constraints << constr;
39         constr->setParent(this);
40     }
41 }
42 
SqliteCreateTable(bool ifNotExistsKw,int temp,const QString & name1,const QString & name2,const QList<SqliteCreateTable::Column * > & columns,const QList<SqliteCreateTable::Constraint * > & constraints,const QString & withOutRowId)43 SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2, const QList<SqliteCreateTable::Column*>& columns, const QList<SqliteCreateTable::Constraint*>& constraints, const QString& withOutRowId) :
44     SqliteCreateTable(ifNotExistsKw, temp, name1, name2, columns, constraints)
45 {
46     this->withOutRowId = withOutRowId;
47 }
48 
SqliteCreateTable(bool ifNotExistsKw,int temp,const QString & name1,const QString & name2,SqliteSelect * select)49 SqliteCreateTable::SqliteCreateTable(bool ifNotExistsKw, int temp, const QString &name1, const QString &name2, SqliteSelect *select)
50     : SqliteCreateTable()
51 {
52     init(ifNotExistsKw, temp, name1, name2);
53     this->select = select;
54     if (select)
55         select->setParent(this);
56 }
57 
~SqliteCreateTable()58 SqliteCreateTable::~SqliteCreateTable()
59 {
60 }
61 
clone()62 SqliteStatement*SqliteCreateTable::clone()
63 {
64     return new SqliteCreateTable(*this);
65 }
66 
getConstraints(SqliteCreateTable::Constraint::Type type) const67 QList<SqliteCreateTable::Constraint*> SqliteCreateTable::getConstraints(SqliteCreateTable::Constraint::Type type) const
68 {
69     QList<SqliteCreateTable::Constraint*> results;
70     for (Constraint* constr : constraints)
71         if (constr->type == type)
72             results << constr;
73 
74     return results;
75 }
76 
getPrimaryKey() const77 SqliteStatement* SqliteCreateTable::getPrimaryKey() const
78 {
79     for (Constraint* constr : getConstraints(Constraint::PRIMARY_KEY))
80         return constr;
81 
82     Column::Constraint* colConstr = nullptr;
83     for (Column* col : columns)
84     {
85         colConstr = col->getConstraint(Column::Constraint::PRIMARY_KEY);
86         if (colConstr)
87             return colConstr;
88     }
89 
90     return nullptr;
91 }
92 
getPrimaryKeyColumns() const93 QStringList SqliteCreateTable::getPrimaryKeyColumns() const
94 {
95     QStringList colNames;
96     SqliteStatement* primaryKey = getPrimaryKey();
97     if (!primaryKey)
98         return colNames;
99 
100     SqliteCreateTable::Column::Constraint* columnConstr = dynamic_cast<SqliteCreateTable::Column::Constraint*>(primaryKey);
101     if (columnConstr)
102     {
103         colNames << dynamic_cast<SqliteCreateTable::Column*>(columnConstr->parentStatement())->name;
104         return colNames;
105     }
106 
107     SqliteCreateTable::Constraint* tableConstr = dynamic_cast<SqliteCreateTable::Constraint*>(primaryKey);
108     if (tableConstr)
109     {
110         for (SqliteIndexedColumn* idxCol : tableConstr->indexedColumns)
111             colNames << idxCol->name;
112     }
113     return colNames;
114 }
115 
getColumn(const QString & colName)116 SqliteCreateTable::Column* SqliteCreateTable::getColumn(const QString& colName)
117 {
118     for (Column* col : columns)
119     {
120         if (col->name.compare(colName, Qt::CaseInsensitive) == 0)
121             return col;
122     }
123     return nullptr;
124 }
125 
getForeignKeysByTable(const QString & foreignTable) const126 QList<SqliteCreateTable::Constraint*> SqliteCreateTable::getForeignKeysByTable(const QString& foreignTable) const
127 {
128     QList<Constraint*> results;
129     for (Constraint* constr : constraints)
130         if (constr->type == Constraint::FOREIGN_KEY && constr->foreignKey->foreignTable.compare(foreignTable, Qt::CaseInsensitive) == 0)
131             results << constr;
132 
133     return results;
134 }
135 
getColumnForeignKeysByTable(const QString & foreignTable) const136 QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::getColumnForeignKeysByTable(const QString& foreignTable) const
137 {
138     QList<Column::Constraint*> results;
139     for (Column* col : columns)
140         results += col->getForeignKeysByTable(foreignTable);
141 
142     return results;
143 }
144 
getColumnNames() const145 QStringList SqliteCreateTable::getColumnNames() const
146 {
147     QStringList names;
148     for (Column* col : columns)
149         names << col->name;
150 
151     return names;
152 }
153 
getModifiedColumnsMap(bool lowercaseKeys,Qt::CaseSensitivity cs) const154 QHash<QString, QString> SqliteCreateTable::getModifiedColumnsMap(bool lowercaseKeys, Qt::CaseSensitivity cs) const
155 {
156     QHash<QString, QString> colMap;
157     QString key;
158     for (Column* col : columns)
159     {
160         key = lowercaseKeys ? col->originalName.toLower() : col->originalName;
161         if (col->name.compare(col->originalName, cs) != 0)
162             colMap[key] = col->name;
163     }
164 
165     return colMap;
166 }
167 
getTablesInStatement()168 QStringList SqliteCreateTable::getTablesInStatement()
169 {
170     return getStrListFromValue(table);
171 }
172 
getDatabasesInStatement()173 QStringList SqliteCreateTable::getDatabasesInStatement()
174 {
175     return getStrListFromValue(database);
176 }
177 
getTableTokensInStatement()178 TokenList SqliteCreateTable::getTableTokensInStatement()
179 {
180     return getObjectTokenListFromFullname();
181 }
182 
getDatabaseTokensInStatement()183 TokenList SqliteCreateTable::getDatabaseTokensInStatement()
184 {
185     return getDbTokenListFromFullname();
186 }
187 
getFullObjectsInStatement()188 QList<SqliteStatement::FullObject> SqliteCreateTable::getFullObjectsInStatement()
189 {
190     QList<FullObject> result;
191 
192     // Table object
193     FullObject fullObj = getFullObjectFromFullname(FullObject::TABLE);
194 
195     if (fullObj.isValid())
196         result << fullObj;
197 
198     // Db object
199     fullObj = getFirstDbFullObject();
200     if (fullObj.isValid())
201     {
202         result << fullObj;
203         dbTokenForFullObjects = fullObj.database;
204     }
205 
206     return result;
207 }
208 
rebuildTokensFromContents()209 TokenList SqliteCreateTable::rebuildTokensFromContents()
210 {
211     StatementTokenBuilder builder;
212     builder.withTokens(SqliteQuery::rebuildTokensFromContents());
213     builder.withKeyword("CREATE");
214     if (tempKw)
215         builder.withSpace().withKeyword("TEMP");
216     else if (temporaryKw)
217         builder.withSpace().withKeyword("TEMPORARY");
218 
219     builder.withSpace().withKeyword("TABLE");
220     if (ifNotExistsKw)
221         builder.withSpace().withKeyword("IF").withSpace().withKeyword("NOT").withSpace().withKeyword("EXISTS");
222 
223     builder.withSpace();
224     if (!database.isNull())
225         builder.withOther(database).withOperator(".");
226 
227     builder.withOther(table);
228 
229     if (select)
230         builder.withSpace().withKeyword("AS").withSpace().withStatement(select);
231     else
232     {
233         builder.withSpace().withParLeft().withStatementList(columns);
234         if (constraints.size() > 0)
235             builder.withOperator(",").withStatementList(constraints);
236 
237         builder.withParRight();
238 
239         if (!withOutRowId.isNull())
240             builder.withSpace().withKeyword("WITHOUT").withSpace().withOther("ROWID");
241     }
242 
243     builder.withOperator(";");
244 
245     return builder.build();
246 }
247 
init(bool ifNotExistsKw,int temp,const QString & name1,const QString & name2)248 void SqliteCreateTable::init(bool ifNotExistsKw, int temp, const QString &name1, const QString &name2)
249 {
250     this->ifNotExistsKw = ifNotExistsKw;
251     if (temp == 2)
252         temporaryKw = true;
253     else if (temp == 1)
254         tempKw = true;
255 
256     if (name2.isNull())
257         table = name1;
258     else
259     {
260         database = name1;
261         table = name2;
262     }
263 }
264 
265 
Constraint()266 SqliteCreateTable::Column::Constraint::Constraint()
267 {
268 }
269 
Constraint(const SqliteCreateTable::Column::Constraint & other)270 SqliteCreateTable::Column::Constraint::Constraint(const SqliteCreateTable::Column::Constraint& other) :
271     SqliteStatement(other), type(other.type), name(other.name), sortOrder(other.sortOrder), onConflict(other.onConflict),
272     autoincrKw(other.autoincrKw), generatedKw(other.generatedKw), literalValue(other.literalValue), literalNull(other.literalNull),
273     ctime(other.ctime), id(other.id), collationName(other.collationName), generatedType(other.generatedType),
274     deferrable(other.deferrable), initially(other.initially)
275 {
276     DEEP_COPY_FIELD(SqliteExpr, expr);
277     DEEP_COPY_FIELD(SqliteForeignKey, foreignKey);
278 }
279 
~Constraint()280 SqliteCreateTable::Column::Constraint::~Constraint()
281 {
282 }
283 
clone()284 SqliteStatement* SqliteCreateTable::Column::Constraint::clone()
285 {
286     return new SqliteCreateTable::Column::Constraint(*this);
287 }
288 
toString(SqliteCreateTable::Column::Constraint::GeneratedType type)289 QString SqliteCreateTable::Column::Constraint::toString(SqliteCreateTable::Column::Constraint::GeneratedType type)
290 {
291     switch (type) {
292         case SqliteCreateTable::Column::Constraint::GeneratedType::STORED:
293             return "STORED";
294         case SqliteCreateTable::Column::Constraint::GeneratedType::VIRTUAL:
295             return "VIRTUAL";
296         case SqliteCreateTable::Column::Constraint::GeneratedType::null:
297             break;
298     }
299     return QString();
300 }
301 
generatedTypeFrom(const QString & type)302 SqliteCreateTable::Column::Constraint::GeneratedType SqliteCreateTable::Column::Constraint::generatedTypeFrom(const QString& type)
303 {
304     QString upType = type.toUpper();
305     if (upType == "STORED")
306         return GeneratedType::STORED;
307     else if (upType == "VIRTUAL")
308         return GeneratedType::VIRTUAL;
309     else
310         return GeneratedType::null;
311 }
312 
initDefNameOnly(const QString & name)313 void SqliteCreateTable::Column::Constraint::initDefNameOnly(const QString &name)
314 {
315     this->type = SqliteCreateTable::Column::Constraint::NAME_ONLY;
316     this->name = name;
317 }
318 
initDefId(const QString & id)319 void SqliteCreateTable::Column::Constraint::initDefId(const QString &id)
320 {
321     this->type = SqliteCreateTable::Column::Constraint::DEFAULT;
322     this->id = id;
323 }
324 
initDefTerm(const QVariant & value,bool minus)325 void SqliteCreateTable::Column::Constraint::initDefTerm(const QVariant &value, bool minus)
326 {
327     this->type = SqliteCreateTable::Column::Constraint::DEFAULT;
328     if (minus)
329     {
330         if (value.type() == QVariant::Double)
331             literalValue = -(value.toDouble());
332         else if (value.type() == QVariant::LongLong)
333             literalValue = -(value.toLongLong());
334     }
335     else if (value.isNull())
336     {
337         literalValue = value;
338         literalNull = true;
339     }
340     else
341         literalValue = value;
342 }
343 
initDefCTime(const QString & name)344 void SqliteCreateTable::Column::Constraint::initDefCTime(const QString &name)
345 {
346     this->type = SqliteCreateTable::Column::Constraint::DEFAULT;
347     ctime = name;
348 }
349 
initDefExpr(SqliteExpr * expr)350 void SqliteCreateTable::Column::Constraint::initDefExpr(SqliteExpr *expr)
351 {
352     this->type = SqliteCreateTable::Column::Constraint::DEFAULT;
353     this->expr = expr;
354     if (expr)
355         expr->setParent(this);
356 }
357 
initNull(SqliteConflictAlgo algo)358 void SqliteCreateTable::Column::Constraint::initNull(SqliteConflictAlgo algo)
359 {
360     this->type = SqliteCreateTable::Column::Constraint::NULL_;
361     onConflict = algo;
362 }
363 
initNotNull(SqliteConflictAlgo algo)364 void SqliteCreateTable::Column::Constraint::initNotNull(SqliteConflictAlgo algo)
365 {
366     this->type = SqliteCreateTable::Column::Constraint::NOT_NULL;
367     onConflict = algo;
368 }
369 
initPk(SqliteSortOrder order,SqliteConflictAlgo algo,bool autoincr)370 void SqliteCreateTable::Column::Constraint::initPk(SqliteSortOrder order, SqliteConflictAlgo algo, bool autoincr)
371 {
372     this->type = SqliteCreateTable::Column::Constraint::PRIMARY_KEY;
373     sortOrder = order;
374     onConflict = algo;
375     autoincrKw = autoincr;
376 }
377 
initUnique(SqliteConflictAlgo algo)378 void SqliteCreateTable::Column::Constraint::initUnique(SqliteConflictAlgo algo)
379 {
380     this->type = SqliteCreateTable::Column::Constraint::UNIQUE;
381     onConflict = algo;
382 }
383 
initCheck()384 void SqliteCreateTable::Column::Constraint::initCheck()
385 {
386     this->type = SqliteCreateTable::Column::Constraint::CHECK;
387 }
388 
initCheck(SqliteExpr * expr)389 void SqliteCreateTable::Column::Constraint::initCheck(SqliteExpr *expr)
390 {
391     this->type = SqliteCreateTable::Column::Constraint::CHECK;
392     this->expr = expr;
393     if (expr)
394         expr->setParent(this);
395 }
396 
initCheck(SqliteExpr * expr,SqliteConflictAlgo algo)397 void SqliteCreateTable::Column::Constraint::initCheck(SqliteExpr *expr, SqliteConflictAlgo algo)
398 {
399     initCheck(expr);
400     this->onConflict = algo;
401 }
402 
initFk(const QString & table,const QList<SqliteIndexedColumn * > & indexedColumns,const QList<SqliteForeignKey::Condition * > & conditions)403 void SqliteCreateTable::Column::Constraint::initFk(const QString& table, const QList<SqliteIndexedColumn*>& indexedColumns, const QList<SqliteForeignKey::Condition*>& conditions)
404 {
405     this->type = SqliteCreateTable::Column::Constraint::FOREIGN_KEY;
406 
407     SqliteForeignKey* fk = new SqliteForeignKey();
408     fk->foreignTable = table;
409     fk->indexedColumns = indexedColumns;
410     fk->conditions = conditions;
411     foreignKey = fk;
412     fk->setParent(this);
413 
414     for (SqliteIndexedColumn* idxCol : indexedColumns)
415         idxCol->setParent(fk);
416 
417     for (SqliteForeignKey::Condition* cond : conditions)
418         cond->setParent(fk);
419 }
420 
initDefer(SqliteInitially initially,SqliteDeferrable deferrable)421 void SqliteCreateTable::Column::Constraint::initDefer(SqliteInitially initially, SqliteDeferrable deferrable)
422 {
423     this->type = SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY;
424     this->deferrable = deferrable;
425     this->initially = initially;
426 }
427 
initColl(const QString & name)428 void SqliteCreateTable::Column::Constraint::initColl(const QString &name)
429 {
430     this->type = SqliteCreateTable::Column::Constraint::COLLATE;
431     this->collationName = name;
432 }
433 
initGeneratedAs(SqliteExpr * expr,bool genKw,const QString & type)434 void SqliteCreateTable::Column::Constraint::initGeneratedAs(SqliteExpr* expr, bool genKw, const QString& type)
435 {
436     this->type = SqliteCreateTable::Column::Constraint::GENERATED;
437     this->expr = expr;
438     this->generatedKw = genKw;
439     this->generatedType = generatedTypeFrom(type);
440 }
441 
typeString() const442 QString SqliteCreateTable::Column::Constraint::typeString() const
443 {
444     switch (type)
445     {
446         case SqliteCreateTable::Column::Constraint::PRIMARY_KEY:
447             return "PRIMARY KEY";
448         case SqliteCreateTable::Column::Constraint::NOT_NULL:
449             return "NOT NULL";
450         case SqliteCreateTable::Column::Constraint::UNIQUE:
451             return "UNIQUE";
452         case SqliteCreateTable::Column::Constraint::CHECK:
453             return "CHECK";
454         case SqliteCreateTable::Column::Constraint::DEFAULT:
455             return "DEFAULT";
456         case SqliteCreateTable::Column::Constraint::GENERATED:
457             return "GENERATED";
458         case SqliteCreateTable::Column::Constraint::COLLATE:
459             return "COLLATE";
460         case SqliteCreateTable::Column::Constraint::FOREIGN_KEY:
461             return "FOREIGN KEY";
462         case SqliteCreateTable::Column::Constraint::NULL_:
463         case SqliteCreateTable::Column::Constraint::NAME_ONLY:
464         case SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY:
465             break;
466     }
467     return QString();
468 }
469 
Constraint()470 SqliteCreateTable::Constraint::Constraint()
471 {
472 }
473 
Constraint(const SqliteCreateTable::Constraint & other)474 SqliteCreateTable::Constraint::Constraint(const SqliteCreateTable::Constraint& other) :
475     SqliteStatement(other),  type(other.type), name(other.name), autoincrKw(other.autoincrKw), onConflict(other.onConflict),
476     afterComma(other.afterComma)
477 {
478     DEEP_COPY_FIELD(SqliteForeignKey, foreignKey);
479     DEEP_COPY_FIELD(SqliteExpr, expr);
480     DEEP_COPY_COLLECTION(SqliteIndexedColumn, indexedColumns);
481 }
482 
~Constraint()483 SqliteCreateTable::Constraint::~Constraint()
484 {
485 }
486 
clone()487 SqliteStatement*SqliteCreateTable::Constraint::clone()
488 {
489     return new SqliteCreateTable::Constraint(*this);
490 }
491 
initNameOnly(const QString & name)492 void SqliteCreateTable::Constraint::initNameOnly(const QString &name)
493 {
494     this->type = SqliteCreateTable::Constraint::NAME_ONLY;
495     this->name = name;
496 }
497 
initPk(const QList<SqliteIndexedColumn * > & indexedColumns,bool autoincr,SqliteConflictAlgo algo)498 void SqliteCreateTable::Constraint::initPk(const QList<SqliteIndexedColumn *> &indexedColumns, bool autoincr, SqliteConflictAlgo algo)
499 {
500     this->type = SqliteCreateTable::Constraint::PRIMARY_KEY;
501     this->indexedColumns = indexedColumns;
502     autoincrKw = autoincr;
503     onConflict = algo;
504 
505     for (SqliteIndexedColumn* idxCol : indexedColumns)
506         idxCol->setParent(this);
507 }
508 
initUnique(const QList<SqliteIndexedColumn * > & indexedColumns,SqliteConflictAlgo algo)509 void SqliteCreateTable::Constraint::initUnique(const QList<SqliteIndexedColumn *> &indexedColumns, SqliteConflictAlgo algo)
510 {
511     this->type = SqliteCreateTable::Constraint::UNIQUE;
512     this->indexedColumns = indexedColumns;
513     onConflict = algo;
514 
515     for (SqliteIndexedColumn* idxCol : indexedColumns)
516         idxCol->setParent(this);
517 }
518 
initCheck(SqliteExpr * expr,SqliteConflictAlgo algo)519 void SqliteCreateTable::Constraint::initCheck(SqliteExpr *expr, SqliteConflictAlgo algo)
520 {
521     this->type = SqliteCreateTable::Constraint::CHECK;
522     this->expr = expr;
523     onConflict = algo;
524     if (expr)
525         expr->setParent(this);
526 }
527 
initCheck()528 void SqliteCreateTable::Constraint::initCheck()
529 {
530     this->type = SqliteCreateTable::Constraint::CHECK;
531 }
532 
initFk(const QList<SqliteIndexedColumn * > & indexedColumns,const QString & table,const QList<SqliteIndexedColumn * > & fkColumns,const QList<SqliteForeignKey::Condition * > & conditions,SqliteInitially initially,SqliteDeferrable deferrable)533 void SqliteCreateTable::Constraint::initFk(const QList<SqliteIndexedColumn *> &indexedColumns, const QString& table, const QList<SqliteIndexedColumn *> &fkColumns, const QList<SqliteForeignKey::Condition *> &conditions, SqliteInitially initially, SqliteDeferrable deferrable)
534 {
535     this->type = SqliteCreateTable::Constraint::FOREIGN_KEY;
536     this->indexedColumns = indexedColumns;
537 
538     for (SqliteIndexedColumn* idxCol : indexedColumns)
539         idxCol->setParent(this);
540 
541     SqliteForeignKey* fk = new SqliteForeignKey();
542     fk->foreignTable = table;
543     fk->indexedColumns = fkColumns;
544     fk->conditions = conditions;
545     fk->deferrable = deferrable;
546     fk->initially = initially;
547 
548     fk->setParent(this);
549 
550     for (SqliteIndexedColumn* idxCol : fkColumns)
551         idxCol->setParent(fk);
552 
553     for (SqliteForeignKey::Condition* cond : conditions)
554         cond->setParent(fk);
555 
556     this->foreignKey = fk;
557 }
558 
doesAffectColumn(const QString & columnName)559 bool SqliteCreateTable::Constraint::doesAffectColumn(const QString& columnName)
560 {
561     return getAffectedColumnIdx(columnName) > -1;
562 }
563 
getAffectedColumnIdx(const QString & columnName)564 int SqliteCreateTable::Constraint::getAffectedColumnIdx(const QString& columnName)
565 {
566     int i = 0;
567     for (SqliteIndexedColumn* idxCol : indexedColumns)
568     {
569         if (idxCol->name.compare(columnName, Qt::CaseInsensitive) == 0)
570             return i;
571 
572         i++;
573     }
574 
575     return -1;
576 }
577 
typeString() const578 QString SqliteCreateTable::Constraint::typeString() const
579 {
580     switch (type)
581     {
582         case SqliteCreateTable::Constraint::PRIMARY_KEY:
583             return "PRIMARY KEY";
584         case SqliteCreateTable::Constraint::UNIQUE:
585             return "UNIQUE";
586         case SqliteCreateTable::Constraint::CHECK:
587             return "CHECK";
588         case SqliteCreateTable::Constraint::FOREIGN_KEY:
589             return "FOREIGN KEY";
590         case SqliteCreateTable::Constraint::NAME_ONLY:
591             return QString();
592     }
593     return QString();
594 }
595 
rebuildTokensFromContents()596 TokenList SqliteCreateTable::Constraint::rebuildTokensFromContents()
597 {
598     StatementTokenBuilder builder;
599 
600     if (!name.isNull())
601         builder.withKeyword("CONSTRAINT").withSpace().withOther(name).withSpace();
602 
603     switch (type)
604     {
605         case SqliteCreateTable::Constraint::PRIMARY_KEY:
606         {
607             builder.withKeyword("PRIMARY").withSpace().withKeyword("KEY").withSpace().withParLeft().withStatementList(indexedColumns).withParRight();
608 
609             if (autoincrKw)
610                 builder.withSpace().withKeyword("AUTOINCREMENT");
611 
612             builder.withConflict(onConflict);
613             break;
614         }
615         case SqliteCreateTable::Constraint::UNIQUE:
616         {
617             builder.withKeyword("UNIQUE").withSpace().withParLeft().withStatementList(indexedColumns).withParRight().withConflict(onConflict);
618             break;
619         }
620         case SqliteCreateTable::Constraint::CHECK:
621         {
622             builder.withKeyword("CHECK").withSpace().withParLeft().withStatement(expr).withParRight().withConflict(onConflict);
623             break;
624         }
625         case SqliteCreateTable::Constraint::FOREIGN_KEY:
626         {
627             builder.withKeyword("FOREIGN").withSpace().withKeyword("KEY").withSpace().withParLeft().withStatementList(indexedColumns)
628                     .withParRight().withStatement(foreignKey);
629             break;
630         }
631         case SqliteCreateTable::Constraint::NAME_ONLY:
632             break;
633     }
634 
635     return builder.build();
636 }
637 
Column()638 SqliteCreateTable::Column::Column()
639 {
640 }
641 
Column(const SqliteCreateTable::Column & other)642 SqliteCreateTable::Column::Column(const SqliteCreateTable::Column& other) :
643     SqliteStatement(other), name(other.name), originalName(other.originalName)
644 {
645     DEEP_COPY_FIELD(SqliteColumnType, type);
646     DEEP_COPY_COLLECTION(Constraint, constraints);
647 }
648 
Column(const QString & name,SqliteColumnType * type,const QList<Constraint * > & constraints)649 SqliteCreateTable::Column::Column(const QString &name, SqliteColumnType *type, const QList<Constraint *> &constraints)
650 {
651     this->name = name;
652     this->originalName = name;
653     this->type = type;
654 
655     if (type)
656         type->setParent(this);
657 
658     for (SqliteCreateTable::Column::Constraint* constr : constraints)
659     {
660         // If last constraint on list is NAME_ONLY we apply the name
661         // to current constraint and remove NAME_ONLY.
662         // Exception is DEFERRABLE_ONLY.
663         if (this->constraints.size() > 0 &&
664             this->constraints.last()->type == SqliteCreateTable::Column::Constraint::NAME_ONLY &&
665             constr->type != SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY)
666         {
667             constr->name = this->constraints.last()->name;
668             delete this->constraints.takeLast();
669         }
670 
671         // And the opposite of above. Now we apply DEFERRABLE_ONLY,
672         // but only if last item in the list is not NAME_ONLY.
673         if (constr->type == SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY &&
674             this->constraints.size() > 0 &&
675             this->constraints.last()->type != SqliteCreateTable::Column::Constraint::NAME_ONLY)
676         {
677             SqliteCreateTable::Column::Constraint* last = this->constraints.last();
678             last->foreignKey->deferrable = constr->deferrable;
679             last->foreignKey->initially = constr->initially;
680             delete constr;
681 
682             // We don't want deleted constr to be added to list. We finish this now.
683             continue;
684         }
685 
686         this->constraints << constr;
687         constr->setParent(this);
688     }
689 }
690 
~Column()691 SqliteCreateTable::Column::~Column()
692 {
693 }
694 
clone()695 SqliteStatement*SqliteCreateTable::Column::clone()
696 {
697     return new SqliteCreateTable::Column(*this);
698 }
699 
hasConstraint(SqliteCreateTable::Column::Constraint::Type type) const700 bool SqliteCreateTable::Column::hasConstraint(SqliteCreateTable::Column::Constraint::Type type) const
701 {
702     return getConstraint(type) != nullptr;
703 }
704 
getConstraint(SqliteCreateTable::Column::Constraint::Type type) const705 SqliteCreateTable::Column::Constraint* SqliteCreateTable::Column::getConstraint(SqliteCreateTable::Column::Constraint::Type type) const
706 {
707     for (Constraint* constr : constraints)
708         if (constr->type == type)
709             return constr;
710 
711     return nullptr;
712 }
713 
getConstraints(SqliteCreateTable::Column::Constraint::Type type) const714 QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::Column::getConstraints(SqliteCreateTable::Column::Constraint::Type type) const
715 {
716     QList<Constraint*> list;
717     for (Constraint* constr : constraints)
718         if (constr->type == type)
719             list << constr;
720 
721     return list;
722 }
723 
getForeignKeysByTable(const QString & foreignTable) const724 QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::Column::getForeignKeysByTable(const QString& foreignTable) const
725 {
726     QList<Constraint*> results;
727     for (Constraint* constr : constraints)
728         if (constr->type == Constraint::FOREIGN_KEY && constr->foreignKey->foreignTable.compare(foreignTable, Qt::CaseInsensitive) == 0)
729             results << constr;
730 
731     return results;
732 }
733 
fixTypeVsGeneratedAs()734 void SqliteCreateTable::Column::fixTypeVsGeneratedAs()
735 {
736     // This is a workaround for lemon parser taking "GENERATED ALWAYS" as part of the typename,
737     // despite 2 days effort of forcing proper precedense to parse it as part of a constraint.
738     // Lemon keeps reducing these 2 keywords into the typename by using fallback of GENERATED & ALWAYS to ID,
739     // regardless of rule order and explicit precedence. By throwing the GENERATED keyword out of the fallback list,
740     // we would make the syntax incompatible with official SQLite syntax, which allows usage of GENERATED as ID.
741     // I've tried to use more recent Lemon parser, but it's different a lot from current one and it is no longer possible
742     // to collect tokens parsed per rule (needed tor SqliteStatement's tokens & tokenMap). At least not in the way
743     // that it used to be so far.
744     // This is the last resort to make it right.
745     // This method is called from parser rule that reduces column definition (rule "column(X)").
746     Constraint* generatedConstr = getConstraint(Constraint::GENERATED);
747     if (generatedConstr && !generatedConstr->generatedKw && type && type->name.toUpper().contains(GENERATED_ALWAYS_REGEXP))
748     {
749         type->name.replace(GENERATED_ALWAYS_REGEXP, "");
750         type->tokens = type->rebuildTokensFromContents();
751         type->tokensMap["typename"] = type->tokens;
752         generatedConstr->generatedKw = true;
753     }
754 }
755 
evaluatePostParsing()756 void SqliteCreateTable::Column::evaluatePostParsing()
757 {
758     fixTypeVsGeneratedAs();
759 }
760 
getColumnsInStatement()761 QStringList SqliteCreateTable::Column::getColumnsInStatement()
762 {
763     return getStrListFromValue(name);
764 }
765 
getColumnTokensInStatement()766 TokenList SqliteCreateTable::Column::getColumnTokensInStatement()
767 {
768     return getTokenListFromNamedKey("columnid");
769 }
770 
rebuildTokensFromContents()771 TokenList SqliteCreateTable::Column::rebuildTokensFromContents()
772 {
773     StatementTokenBuilder builder;
774     builder.withOther(name).withStatement(type).withStatementList(constraints, "");
775     return builder.build();
776 }
777 
rebuildTokensFromContents()778 TokenList SqliteCreateTable::Column::Constraint::rebuildTokensFromContents()
779 {
780     StatementTokenBuilder builder;
781     if (!name.isNull())
782         builder.withKeyword("CONSTRAINT").withSpace().withOther(name).withSpace();
783 
784     switch (type)
785     {
786         case SqliteCreateTable::Column::Constraint::PRIMARY_KEY:
787         {
788             builder.withKeyword("PRIMARY").withSpace().withKeyword("KEY").withSortOrder(sortOrder).withConflict(onConflict);
789             if (autoincrKw)
790                 builder.withSpace().withKeyword("AUTOINCREMENT");
791 
792             break;
793         }
794         case SqliteCreateTable::Column::Constraint::NOT_NULL:
795         {
796             builder.withKeyword("NOT").withSpace().withKeyword("NULL").withConflict(onConflict);
797             break;
798         }
799         case SqliteCreateTable::Column::Constraint::UNIQUE:
800         {
801             builder.withKeyword("UNIQUE").withConflict(onConflict);
802             break;
803         }
804         case SqliteCreateTable::Column::Constraint::CHECK:
805         {
806             builder.withKeyword("CHECK").withSpace().withParLeft().withStatement(expr).withParRight().withConflict(onConflict);
807             break;
808         }
809         case SqliteCreateTable::Column::Constraint::DEFAULT:
810         {
811             builder.withKeyword("DEFAULT").withSpace();
812             if (!id.isNull())
813                 builder.withOther(id);
814             else if (!ctime.isNull())
815                 builder.withKeyword(ctime.toUpper());
816             else if (expr)
817                 builder.withParLeft().withStatement(expr).withParRight();
818             else if (literalNull)
819                 builder.withKeyword("NULL");
820             else
821                 builder.withLiteralValue(literalValue);
822 
823             break;
824         }
825         case SqliteCreateTable::Column::Constraint::COLLATE:
826         {
827             builder.withKeyword("COLLATE").withSpace().withOther(collationName);
828             break;
829         }
830         case SqliteCreateTable::Column::Constraint::FOREIGN_KEY:
831         {
832             builder.withStatement(foreignKey);
833             break;
834         }
835         case SqliteCreateTable::Column::Constraint::GENERATED:
836         {
837             if (generatedKw)
838                 builder.withKeyword("GENERATED").withSpace().withKeyword("ALWAYS").withSpace();
839 
840             builder.withKeyword("AS").withSpace().withParLeft().withStatement(expr).withParRight();
841             if (generatedType != GeneratedType::null)
842                 builder.withSpace().withOther(toString(generatedType), false);
843 
844             break;
845         }
846         case SqliteCreateTable::Column::Constraint::NULL_:
847         case SqliteCreateTable::Column::Constraint::NAME_ONLY:
848         case SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY:
849             break;
850     }
851 
852     return builder.build();
853 }
854 
getTargetDatabase() const855 QString SqliteCreateTable::getTargetDatabase() const
856 {
857     return database;
858 }
859 
setTargetDatabase(const QString & database)860 void SqliteCreateTable::setTargetDatabase(const QString& database)
861 {
862     this->database = database;
863 }
864