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