1 #include "formatstatement.h"
2 #include "formatselect.h"
3 #include "formatexpr.h"
4 #include "formatlimit.h"
5 #include "formatraise.h"
6 #include "formatwith.h"
7 #include "formatcreatetable.h"
8 #include "formatcreatevirtualtable.h"
9 #include "formatforeignkey.h"
10 #include "formatcolumntype.h"
11 #include "formatindexedcolumn.h"
12 #include "formatinsert.h"
13 #include "formatempty.h"
14 #include "formataltertable.h"
15 #include "formatanalyze.h"
16 #include "formatattach.h"
17 #include "formatbegintrans.h"
18 #include "formatcommittrans.h"
19 #include "formatcopy.h"
20 #include "formatcreateindex.h"
21 #include "formatcreatetrigger.h"
22 #include "formatcreateview.h"
23 #include "formatdelete.h"
24 #include "formatupdate.h"
25 #include "formatdropindex.h"
26 #include "formatpragma.h"
27 #include "formatdroptable.h"
28 #include "formatdroptrigger.h"
29 #include "formatdropview.h"
30 #include "formatorderby.h"
31 #include "formatupsert.h"
32 #include "formatwindowdefinition.h"
33 #include "formatfilterover.h"
34 #include "parser/ast/sqliteselect.h"
35 #include "parser/ast/sqliteexpr.h"
36 #include "parser/ast/sqlitelimit.h"
37 #include "parser/ast/sqliteraise.h"
38 #include "parser/ast/sqlitewith.h"
39 #include "parser/ast/sqlitecreatetable.h"
40 #include "parser/ast/sqlitecreatevirtualtable.h"
41 #include "parser/ast/sqliteforeignkey.h"
42 #include "parser/ast/sqlitecolumntype.h"
43 #include "parser/ast/sqliteindexedcolumn.h"
44 #include "parser/ast/sqliteinsert.h"
45 #include "parser/ast/sqliteemptyquery.h"
46 #include "parser/ast/sqlitealtertable.h"
47 #include "parser/ast/sqliteanalyze.h"
48 #include "parser/ast/sqliteattach.h"
49 #include "parser/ast/sqlitebegintrans.h"
50 #include "parser/ast/sqlitecommittrans.h"
51 #include "parser/ast/sqlitecopy.h"
52 #include "parser/ast/sqlitecreateindex.h"
53 #include "parser/ast/sqlitecreatetrigger.h"
54 #include "parser/ast/sqlitecreateview.h"
55 #include "parser/ast/sqliteupdate.h"
56 #include "parser/ast/sqlitedelete.h"
57 #include "parser/ast/sqlitedropindex.h"
58 #include "parser/ast/sqlitedroptable.h"
59 #include "parser/ast/sqlitedroptrigger.h"
60 #include "parser/ast/sqlitedropview.h"
61 #include "parser/ast/sqliteorderby.h"
62 #include "parser/ast/sqlitepragma.h"
63 #include "parser/ast/sqliteupsert.h"
64 #include "parser/ast/sqlitewindowdefinition.h"
65 #include "parser/ast/sqlitefilterover.h"
66 #include "sqlenterpriseformatter.h"
67 #include "common/utils_sql.h"
68 #include "common/global.h"
69 #include <QRegularExpression>
70 #include <QDebug>
71
72 #define FORMATTER_FACTORY_ENTRY(query, Type, FormatType) \
73 if (dynamic_cast<Type*>(query)) \
74 return new FormatType(dynamic_cast<Type*>(query))
75
76 const QString FormatStatement::SPACE = " ";
77 const QString FormatStatement::NEWLINE = "\n";
78 qint64 FormatStatement::nameSeq = 0;
79
FormatStatement()80 FormatStatement::FormatStatement()
81 {
82 static_qstring(nameTpl, "statement_%1");
83
84 indents.push(0);
85 statementName = nameTpl.arg(QString::number(nameSeq++));
86 }
87
~FormatStatement()88 FormatStatement::~FormatStatement()
89 {
90 cleanup();
91 }
92
format()93 QString FormatStatement::format()
94 {
95 buildTokens();
96 return detokenize() + NEWLINE; // extra space when formatting multiple top level (not in CREATE TRIGGER) queries
97 }
98
setSelectedWrapper(NameWrapper wrapper)99 void FormatStatement::setSelectedWrapper(NameWrapper wrapper)
100 {
101 this->wrapper = wrapper;
102 }
103
setConfig(Cfg::SqlEnterpriseFormatterConfig * cfg)104 void FormatStatement::setConfig(Cfg::SqlEnterpriseFormatterConfig* cfg)
105 {
106 this->cfg = cfg;
107 }
108
buildTokens()109 void FormatStatement::buildTokens()
110 {
111 cleanup();
112 resetInternal();
113 formatInternal();
114 }
115
forQuery(SqliteStatement * query)116 FormatStatement *FormatStatement::forQuery(SqliteStatement *query)
117 {
118 FormatStatement* stmt = nullptr;
119 FORMATTER_FACTORY_ENTRY(query, SqliteSelect, FormatSelect);
120 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core, FormatSelectCore);
121 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::ResultColumn, FormatSelectCoreResultColumn);
122 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::JoinConstraint, FormatSelectCoreJoinConstraint);
123 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::JoinOp, FormatSelectCoreJoinOp);
124 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::JoinSource, FormatSelectCoreJoinSource);
125 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::JoinSourceOther, FormatSelectCoreJoinSourceOther);
126 FORMATTER_FACTORY_ENTRY(query, SqliteSelect::Core::SingleSource, FormatSelectCoreSingleSource);
127 FORMATTER_FACTORY_ENTRY(query, SqliteExpr, FormatExpr);
128 FORMATTER_FACTORY_ENTRY(query, SqliteWith, FormatWith);
129 FORMATTER_FACTORY_ENTRY(query, SqliteWith::CommonTableExpression, FormatWithCommonTableExpression);
130 FORMATTER_FACTORY_ENTRY(query, SqliteRaise, FormatRaise);
131 FORMATTER_FACTORY_ENTRY(query, SqliteLimit, FormatLimit);
132 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTable, FormatCreateTable);
133 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTable::Column, FormatCreateTableColumn);
134 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTable::Column::Constraint, FormatCreateTableColumnConstraint);
135 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTable::Constraint, FormatCreateTableConstraint);
136 FORMATTER_FACTORY_ENTRY(query, SqliteForeignKey, FormatForeignKey);
137 FORMATTER_FACTORY_ENTRY(query, SqliteForeignKey::Condition, FormatForeignKeyCondition);
138 FORMATTER_FACTORY_ENTRY(query, SqliteColumnType, FormatColumnType);
139 FORMATTER_FACTORY_ENTRY(query, SqliteIndexedColumn, FormatIndexedColumn);
140 FORMATTER_FACTORY_ENTRY(query, SqliteInsert, FormatInsert);
141 FORMATTER_FACTORY_ENTRY(query, SqliteUpsert, FormatUpsert);
142 FORMATTER_FACTORY_ENTRY(query, SqliteEmptyQuery, FormatEmpty);
143 FORMATTER_FACTORY_ENTRY(query, SqliteAlterTable, FormatAlterTable);
144 FORMATTER_FACTORY_ENTRY(query, SqliteAnalyze, FormatAnalyze);
145 FORMATTER_FACTORY_ENTRY(query, SqliteAttach, FormatAttach);
146 FORMATTER_FACTORY_ENTRY(query, SqliteBeginTrans, FormatBeginTrans);
147 FORMATTER_FACTORY_ENTRY(query, SqliteCommitTrans, FormatCommitTrans);
148 FORMATTER_FACTORY_ENTRY(query, SqliteCopy, FormatCopy);
149 FORMATTER_FACTORY_ENTRY(query, SqliteCreateVirtualTable, FormatCreateVirtualTable);
150 FORMATTER_FACTORY_ENTRY(query, SqliteCreateIndex, FormatCreateIndex);
151 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTrigger, FormatCreateTrigger);
152 FORMATTER_FACTORY_ENTRY(query, SqliteCreateTrigger::Event, FormatCreateTriggerEvent);
153 FORMATTER_FACTORY_ENTRY(query, SqliteCreateView, FormatCreateView);
154 FORMATTER_FACTORY_ENTRY(query, SqliteUpdate, FormatUpdate);
155 FORMATTER_FACTORY_ENTRY(query, SqliteDelete, FormatDelete);
156 FORMATTER_FACTORY_ENTRY(query, SqliteDropIndex, FormatDropIndex);
157 FORMATTER_FACTORY_ENTRY(query, SqliteDropTable, FormatDropTable);
158 FORMATTER_FACTORY_ENTRY(query, SqliteDropTrigger, FormatDropTrigger);
159 FORMATTER_FACTORY_ENTRY(query, SqliteDropView, FormatDropView);
160 FORMATTER_FACTORY_ENTRY(query, SqliteOrderBy, FormatOrderBy);
161 FORMATTER_FACTORY_ENTRY(query, SqlitePragma, FormatPragma);
162 FORMATTER_FACTORY_ENTRY(query, SqliteWindowDefinition, FormatWindowDefinition);
163 FORMATTER_FACTORY_ENTRY(query, SqliteWindowDefinition::Window, FormatWindowDefinitionWindow);
164 FORMATTER_FACTORY_ENTRY(query, SqliteWindowDefinition::Window::Frame, FormatWindowDefinitionWindowFrame);
165 FORMATTER_FACTORY_ENTRY(query, SqliteWindowDefinition::Window::Frame::Bound, FormatWindowDefinitionWindowFrameBound);
166 FORMATTER_FACTORY_ENTRY(query, SqliteFilterOver, FormatFilterOver);
167 FORMATTER_FACTORY_ENTRY(query, SqliteFilterOver::Filter, FormatFilterOverFilter);
168 FORMATTER_FACTORY_ENTRY(query, SqliteFilterOver::Over, FormatFilterOverOver);
169
170 if (!stmt)
171 {
172 if (query)
173 qWarning() << "Unhandled query passed to enterprise formatter!";
174 else
175 qWarning() << "Null query passed to enterprise formatter!";
176 }
177
178 return stmt;
179 }
180
resetInternal()181 void FormatStatement::resetInternal()
182 {
183 }
184
withKeyword(const QString & kw)185 FormatStatement& FormatStatement::withKeyword(const QString& kw)
186 {
187 withToken(FormatToken::KEYWORD, kw);
188 return *this;
189 }
190
withLinedUpKeyword(const QString & kw,const QString & lineUpName)191 FormatStatement& FormatStatement::withLinedUpKeyword(const QString& kw, const QString& lineUpName)
192 {
193 withToken(FormatToken::LINED_UP_KEYWORD, kw, getFinalLineUpName(lineUpName));
194 return *this;
195 }
196
withId(const QString & id)197 FormatStatement& FormatStatement::withId(const QString& id)
198 {
199 withToken(FormatToken::ID, id);
200 return *this;
201 }
202
withId(const QString & id,bool wrapIfNeeded)203 FormatStatement& FormatStatement::withId(const QString& id, bool wrapIfNeeded)
204 {
205 withToken(wrapIfNeeded ? FormatToken::ID : FormatToken::ID_NO_WRAP, id);
206 return *this;
207 }
208
withOperator(const QString & oper,FormatToken::Flags flags)209 FormatStatement& FormatStatement::withOperator(const QString& oper, FormatToken::Flags flags)
210 {
211 withToken(FormatToken::OPERATOR, oper, flags);
212 return *this;
213 }
214
withStringOrId(const QString & id)215 FormatStatement&FormatStatement::withStringOrId(const QString& id)
216 {
217 withToken(FormatToken::STRING_OR_ID, id);
218 return *this;
219 }
220
withIdDot(FormatToken::Flags flags)221 FormatStatement& FormatStatement::withIdDot(FormatToken::Flags flags)
222 {
223 withToken(FormatToken::ID_DOT, ".", flags);
224 return *this;
225 }
226
withStar(FormatToken::Flags flags)227 FormatStatement& FormatStatement::withStar(FormatToken::Flags flags)
228 {
229 withToken(FormatToken::STAR, "*", flags);
230 return *this;
231 }
232
withFloat(double value)233 FormatStatement& FormatStatement::withFloat(double value)
234 {
235 withToken(FormatToken::FLOAT, value);
236 return *this;
237 }
238
withInteger(qint64 value)239 FormatStatement& FormatStatement::withInteger(qint64 value)
240 {
241 withToken(FormatToken::INTEGER, value);
242 return *this;
243 }
244
withString(const QString & value)245 FormatStatement& FormatStatement::withString(const QString& value)
246 {
247 withToken(FormatToken::STRING, value);
248 return *this;
249 }
250
withBlob(const QString & value)251 FormatStatement& FormatStatement::withBlob(const QString& value)
252 {
253 withToken(FormatToken::BLOB, value);
254 return *this;
255 }
256
withBindParam(const QString & name)257 FormatStatement& FormatStatement::withBindParam(const QString& name)
258 {
259 withToken(FormatToken::BIND_PARAM, name);
260 return *this;
261 }
262
withParDefLeft(FormatToken::Flags flags)263 FormatStatement& FormatStatement::withParDefLeft(FormatToken::Flags flags)
264 {
265 withToken(FormatToken::PAR_DEF_LEFT, "(", flags);
266 return *this;
267 }
268
withParDefRight(FormatToken::Flags flags)269 FormatStatement& FormatStatement::withParDefRight(FormatToken::Flags flags)
270 {
271 withToken(FormatToken::PAR_DEF_RIGHT, ")", flags);
272 return *this;
273 }
274
withParExprLeft(FormatToken::Flags flags)275 FormatStatement& FormatStatement::withParExprLeft(FormatToken::Flags flags)
276 {
277 withToken(FormatToken::PAR_EXPR_LEFT, "(", flags);
278 return *this;
279 }
280
withParExprRight(FormatToken::Flags flags)281 FormatStatement& FormatStatement::withParExprRight(FormatToken::Flags flags)
282 {
283 withToken(FormatToken::PAR_EXPR_RIGHT, ")", flags);
284 return *this;
285 }
286
withParFuncLeft(FormatToken::Flags flags)287 FormatStatement& FormatStatement::withParFuncLeft(FormatToken::Flags flags)
288 {
289 withToken(FormatToken::PAR_FUNC_LEFT, "(", flags);
290 return *this;
291 }
292
withParFuncRight(FormatToken::Flags flags)293 FormatStatement& FormatStatement::withParFuncRight(FormatToken::Flags flags)
294 {
295 withToken(FormatToken::PAR_FUNC_RIGHT, ")", flags);
296 return *this;
297 }
298
withSemicolon(FormatToken::Flags flags)299 FormatStatement& FormatStatement::withSemicolon(FormatToken::Flags flags)
300 {
301 FormatToken* lastRealToken = getLastRealToken();
302 if ((lastRealToken && lastRealToken->type != FormatToken::SEMICOLON) || tokens.size() == 0)
303 withToken(FormatToken::SEMICOLON, ";", flags);
304
305 return *this;
306 }
307
withListComma(FormatToken::Flags flags)308 FormatStatement& FormatStatement::withListComma(FormatToken::Flags flags)
309 {
310 withToken(FormatToken::COMMA_LIST, ",", flags);
311 return *this;
312 }
313
withCommaOper(FormatToken::Flags flags)314 FormatStatement& FormatStatement::withCommaOper(FormatToken::Flags flags)
315 {
316 withToken(FormatToken::COMMA_OPER, ",", flags);
317 return *this;
318 }
319
withSortOrder(SqliteSortOrder sortOrder)320 FormatStatement&FormatStatement::withSortOrder(SqliteSortOrder sortOrder)
321 {
322 if (sortOrder != SqliteSortOrder::null)
323 withKeyword(sqliteSortOrder(sortOrder));
324
325 return *this;
326 }
327
withConflict(SqliteConflictAlgo onConflict)328 FormatStatement&FormatStatement::withConflict(SqliteConflictAlgo onConflict)
329 {
330 if (onConflict != SqliteConflictAlgo::null)
331 withKeyword("ON").withKeyword("CONFLICT").withKeyword(sqliteConflictAlgo(onConflict));
332
333 return *this;
334 }
335
withFuncId(const QString & func)336 FormatStatement& FormatStatement::withFuncId(const QString& func)
337 {
338 withToken(FormatToken::FUNC_ID, func);
339 return *this;
340 }
341
withDataType(const QString & dataType)342 FormatStatement& FormatStatement::withDataType(const QString& dataType)
343 {
344 withToken(FormatToken::DATA_TYPE, dataType);
345 return *this;
346 }
347
withNewLine()348 FormatStatement& FormatStatement::withNewLine()
349 {
350 withToken(FormatToken::NEW_LINE, NEWLINE);
351 return *this;
352 }
353
withLiteral(const QVariant & value)354 FormatStatement& FormatStatement::withLiteral(const QVariant& value)
355 {
356 if (value.isNull())
357 return *this;
358
359 if (value.userType() == QVariant::String)
360 {
361 withString(value.toString());
362 return *this;
363 }
364
365 bool ok;
366 if (value.userType() == QVariant::Double)
367 {
368 value.toDouble(&ok);
369 if (ok)
370 {
371 withFloat(value.toDouble());
372 return *this;
373 }
374 }
375
376 qint64 longVal = value.toLongLong(&ok);
377 if (ok)
378 {
379 withInteger(longVal);
380 return *this;
381 }
382
383 QString str = value.toString();
384 if (str.startsWith("x'", Qt::CaseInsensitive) && str.endsWith("'"))
385 {
386 withBlob(str);
387 return *this;
388 }
389
390 withString(str);
391 return *this;
392 }
393
withStatement(SqliteStatement * stmt,const QString & indentName,FormatStatementEnricher enricher)394 FormatStatement& FormatStatement::withStatement(SqliteStatement* stmt, const QString& indentName, FormatStatementEnricher enricher)
395 {
396 if (!stmt)
397 return *this;
398
399 FormatStatement* formatStmt = forQuery(stmt, wrapper, cfg);
400 if (!formatStmt)
401 return *this;
402
403 formatStmt->parentFormatStatement = this;
404
405 if (enricher)
406 enricher(formatStmt);
407
408 formatStmt->buildTokens();
409 formatStmt->deleteTokens = false;
410
411 if (!indentName.isNull())
412 markAndKeepIndent(indentName);
413
414 tokens += formatStmt->tokens;
415
416 if (!indentName.isNull())
417 withDecrIndent();
418
419 delete formatStmt;
420 return *this;
421 }
422
markIndent(const QString & name)423 FormatStatement& FormatStatement::markIndent(const QString& name)
424 {
425 withToken(FormatToken::INDENT_MARKER, statementName + "_" + name);
426 return *this;
427 }
428
markAndKeepIndent(const QString & name)429 FormatStatement& FormatStatement::markAndKeepIndent(const QString& name)
430 {
431 markIndent(name);
432 withIncrIndent(name);
433 return *this;
434 }
435
withIncrIndent(int newIndent)436 FormatStatement&FormatStatement::withIncrIndent(int newIndent)
437 {
438 withToken(FormatToken::SET_INDENT, newIndent);
439 return *this;
440 }
441
withIncrIndent(const QString & name)442 FormatStatement& FormatStatement::withIncrIndent(const QString& name)
443 {
444 if (name.isNull())
445 withToken(FormatToken::INCR_INDENT, name);
446 else
447 withToken(FormatToken::INCR_INDENT, statementName + "_" + name);
448
449 return *this;
450 }
451
withDecrIndent()452 FormatStatement& FormatStatement::withDecrIndent()
453 {
454 withToken(FormatToken::DECR_INDENT, QString());
455 return *this;
456 }
457
markKeywordLineUp(const QString & keyword,const QString & lineUpName)458 FormatStatement&FormatStatement::markKeywordLineUp(const QString& keyword, const QString& lineUpName)
459 {
460 withToken(FormatToken::MARK_KEYWORD_LINEUP, getFinalLineUpName(lineUpName), keyword.length());
461 return *this;
462 }
463
withSeparator(FormatStatement::ListSeparator sep,FormatToken::Flags flags)464 FormatStatement&FormatStatement::withSeparator(FormatStatement::ListSeparator sep, FormatToken::Flags flags)
465 {
466 switch (sep)
467 {
468 case ListSeparator::COMMA:
469 withListComma(flags);
470 break;
471 case ListSeparator::EXPR_COMMA:
472 withCommaOper(flags);
473 break;
474 case ListSeparator::NEW_LINE:
475 withNewLine();
476 break;
477 case ListSeparator::SEMICOLON:
478 withSemicolon(flags);
479 break;
480 case ListSeparator::NONE:
481 break;
482 }
483 return *this;
484 }
485
handleExplainQuery(SqliteQuery * query)486 void FormatStatement::handleExplainQuery(SqliteQuery* query)
487 {
488 if (query->explain)
489 {
490 withKeyword("EXPLAIN");
491 if (query->queryPlan)
492 withKeyword("QUERY").withKeyword("PLAN").withNewLine();
493 }
494 }
495
withIdList(const QStringList & names,const QString & indentName,ListSeparator sep)496 FormatStatement& FormatStatement::withIdList(const QStringList& names, const QString& indentName, ListSeparator sep)
497 {
498 if (!indentName.isNull())
499 markAndKeepIndent(indentName);
500
501 bool first = true;
502 for (const QString& name : names)
503 {
504 if (!first)
505 withSeparator(sep);
506
507 withId(name);
508 first = false;
509 }
510
511 if (!indentName.isNull())
512 withDecrIndent();
513
514 return *this;
515 }
516
withToken(FormatStatement::FormatToken::Type type,const QVariant & value,const QVariant & additionalValue,FormatToken::Flags flags)517 FormatStatement::FormatToken* FormatStatement::withToken(FormatStatement::FormatToken::Type type, const QVariant& value, const QVariant& additionalValue, FormatToken::Flags flags)
518 {
519 FormatToken* token = new FormatToken;
520 token->type = type;
521 token->value = value;
522 token->additionalValue = additionalValue;
523 token->flags = flags;
524 tokens << token;
525 return token;
526 }
527
withToken(FormatStatement::FormatToken::Type type,const QVariant & value,FormatToken::Flags flags)528 FormatStatement::FormatToken* FormatStatement::withToken(FormatStatement::FormatToken::Type type, const QVariant& value, FormatToken::Flags flags)
529 {
530 return withToken(type, value, QVariant(), flags);
531 }
532
cleanup()533 void FormatStatement::cleanup()
534 {
535 kwLineUpPosition.clear();
536 line = "";
537 lines.clear();
538 namedIndents.clear();
539 resetIndents();
540 if (deleteTokens)
541 {
542 for (FormatToken* token : tokens)
543 delete token;
544 }
545
546 tokens.clear();
547 }
548
getLineUpValue(const QString & lineUpName)549 int FormatStatement::getLineUpValue(const QString& lineUpName)
550 {
551 if (kwLineUpPosition.contains(lineUpName))
552 return kwLineUpPosition[lineUpName];
553
554 return 0;
555 }
556
detokenize()557 QString FormatStatement::detokenize()
558 {
559 bool uppercaseKeywords = cfg->SqlEnterpriseFormatter.UppercaseKeywords.get();
560
561 for (FormatToken* token : tokens)
562 {
563 applySpace(token->type);
564 switch (token->type)
565 {
566 case FormatToken::LINED_UP_KEYWORD:
567 {
568 if (cfg->SqlEnterpriseFormatter.LineUpKeywords.get())
569 {
570 QString kw = token->value.toString();
571 QString lineUpName = token->additionalValue.toString();
572 int lineUpValue = getLineUpValue(lineUpName);
573
574 int indentLength = lineUpValue - kw.length();
575 if (indentLength > 0)
576 line += SPACE.repeated(indentLength);
577
578 line += uppercaseKeywords ? kw.toUpper() : kw.toLower();
579
580 break;
581 }
582 else
583 {
584 // No 'break', so we go to next case, the regular KEYWORD
585 }
586 __attribute__((__fallthrough__));
587 }
588 case FormatToken::KEYWORD:
589 {
590 applyIndent();
591 line += uppercaseKeywords ? token->value.toString().toUpper() : token->value.toString().toLower();
592 break;
593 }
594 case FormatToken::FUNC_ID:
595 case FormatToken::DATA_TYPE:
596 {
597 applyIndent();
598 line += wrapObjIfNeeded(token->value.toString(), wrapper);
599 break;
600 }
601 case FormatToken::ID:
602 {
603 applyIndent();
604 formatId(token->value.toString(), true);
605 break;
606 }
607 case FormatToken::ID_NO_WRAP:
608 {
609 applyIndent();
610 formatId(token->value.toString(), false);
611 break;
612 }
613 case FormatToken::STRING_OR_ID:
614 {
615 applyIndent();
616 QString val = token->value.toString();
617 if (val.contains("\""))
618 formatId(token->value.toString(), true);
619 else
620 line += wrapObjName(token->value.toString(), NameWrapper::DOUBLE_QUOTE);
621
622 break;
623 }
624 case FormatToken::STRING:
625 {
626 applyIndent();
627 line += wrapString(token->value.toString());
628 break;
629 }
630 case FormatToken::BLOB:
631 case FormatToken::BIND_PARAM:
632 case FormatToken::STAR:
633 case FormatToken::INTEGER:
634 {
635 applyIndent();
636 line += token->value.toString();
637 break;
638 }
639 case FormatToken::FLOAT:
640 {
641 applyIndent();
642 line += doubleToString(token->value);
643 break;
644 }
645 case FormatToken::OPERATOR:
646 {
647 bool spaceAdded = endsWithSpace() || applyIndent();
648 if (cfg->SqlEnterpriseFormatter.SpaceBeforeMathOp.get() && !spaceAdded && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE))
649 line += SPACE;
650
651 line += token->value.toString();
652 if (cfg->SqlEnterpriseFormatter.SpaceAfterMathOp.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER))
653 line += SPACE;
654
655 break;
656 }
657 case FormatToken::ID_DOT:
658 {
659 bool spaceAdded = endsWithSpace() || applyIndent();
660 if (cfg->SqlEnterpriseFormatter.SpaceBeforeDot.get() && !spaceAdded && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE))
661 line += SPACE;
662
663 line += token->value.toString();
664 if (cfg->SqlEnterpriseFormatter.SpaceAfterDot.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER))
665 line += SPACE;
666
667 break;
668 }
669 case FormatToken::PAR_DEF_LEFT:
670 {
671 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE);
672 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
673 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeOpenParDef.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
674 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterOpenParDef.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
675 detokenizeLeftPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
676 break;
677 }
678 case FormatToken::PAR_DEF_RIGHT:
679 {
680 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE);
681 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
682 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeCloseParDef.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
683 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterCloseParDef.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
684 detokenizeRightPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
685 break;
686 }
687 case FormatToken::PAR_EXPR_LEFT:
688 {
689 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE);
690 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
691 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeOpenParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
692 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterOpenParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
693 detokenizeLeftPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
694 break;
695 }
696 case FormatToken::PAR_EXPR_RIGHT:
697 {
698 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE);
699 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
700 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeCloseParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
701 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterCloseParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
702 detokenizeRightPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
703 break;
704 }
705 case FormatToken::PAR_FUNC_LEFT:
706 {
707 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE) && !cfg->SqlEnterpriseFormatter.NoSpaceAfterFunctionName.get();
708 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterOpenPar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
709 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeOpenParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
710 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterOpenParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
711 detokenizeLeftPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
712 break;
713 }
714 case FormatToken::PAR_FUNC_RIGHT:
715 {
716 bool spaceBefore = cfg->SqlEnterpriseFormatter.SpaceBeforeClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_BEFORE);
717 bool spaceAfter = cfg->SqlEnterpriseFormatter.SpaceAfterClosePar.get() && !token->flags.testFlag(FormatToken::Flag::NO_SPACE_AFTER);
718 bool nlBefore = cfg->SqlEnterpriseFormatter.NlBeforeCloseParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE);
719 bool nlAfter = cfg->SqlEnterpriseFormatter.NlAfterCloseParExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER);
720 detokenizeRightPar(token, spaceBefore, spaceAfter, nlBefore, nlAfter);
721 break;
722 }
723 case FormatToken::SEMICOLON:
724 {
725 if (cfg->SqlEnterpriseFormatter.SpaceNeverBeforeSemicolon.get())
726 {
727 removeAllSpaces();
728 }
729 else
730 {
731 bool spaceAdded = endsWithSpace() || applyIndent();
732 if (cfg->SqlEnterpriseFormatter.SpaceBeforeMathOp.get() && !spaceAdded)
733 line += SPACE;
734 }
735
736 line += token->value.toString();
737 if (cfg->SqlEnterpriseFormatter.NlAfterSemicolon.get())
738 newLine();
739 else if (cfg->SqlEnterpriseFormatter.SpaceAfterMathOp.get())
740 line += SPACE;
741
742 break;
743 }
744 case FormatToken::COMMA_LIST:
745 {
746 if (cfg->SqlEnterpriseFormatter.SpaceNeverBeforeComma.get() || token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_BEFORE))
747 {
748 removeAllSpaces();
749 }
750 else
751 {
752 bool spaceAdded = endsWithSpace() || applyIndent();
753 if (cfg->SqlEnterpriseFormatter.SpaceBeforeCommaInList.get() && !spaceAdded)
754 line += SPACE;
755 }
756
757 line += token->value.toString();
758 if (cfg->SqlEnterpriseFormatter.NlAfterComma.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER))
759 newLine();
760 else if (cfg->SqlEnterpriseFormatter.SpaceAfterCommaInList.get())
761 line += SPACE;
762
763 break;
764 }
765 case FormatToken::COMMA_OPER:
766 {
767 if (cfg->SqlEnterpriseFormatter.SpaceNeverBeforeComma.get())
768 {
769 removeAllSpaces();
770 }
771 else
772 {
773 bool spaceAdded = endsWithSpace() || applyIndent();
774 if (cfg->SqlEnterpriseFormatter.SpaceBeforeCommaInList.get() && !spaceAdded)
775 line += SPACE;
776 }
777
778 line += token->value.toString();
779 if (cfg->SqlEnterpriseFormatter.NlAfterCommaInExpr.get() && !token->flags.testFlag(FormatToken::Flag::NO_NEWLINE_AFTER))
780 newLine();
781 else if (cfg->SqlEnterpriseFormatter.SpaceAfterCommaInList.get())
782 line += SPACE;
783
784 break;
785 }
786 case FormatToken::NEW_LINE:
787 {
788 newLine();
789 break;
790 }
791 case FormatToken::INDENT_MARKER:
792 {
793 QString indentName = token->value.toString();
794 namedIndents[indentName] = predictCurrentIndent(token);
795 break;
796 }
797 case FormatToken::INCR_INDENT:
798 {
799 if (!token->value.isNull())
800 incrIndent(token->value.toString());
801 else
802 incrIndent();
803
804 break;
805 }
806 case FormatToken::SET_INDENT:
807 {
808 setIndent(indents.top() + token->value.toInt());
809 break;
810 }
811 case FormatToken::DECR_INDENT:
812 {
813 decrIndent();
814 break;
815 }
816 case FormatToken::MARK_KEYWORD_LINEUP:
817 {
818 QString lineUpName = token->value.toString();
819 int lineUpLength = predictCurrentIndent(token) + token->additionalValue.toInt();
820 if (!kwLineUpPosition.contains(lineUpName) || lineUpLength > kwLineUpPosition[lineUpName])
821 kwLineUpPosition[lineUpName] = lineUpLength;
822
823 break;
824 }
825 }
826 updateLastToken(token);
827 }
828 newLine();
829 return lines.join(NEWLINE);
830 }
831
applyIndent()832 bool FormatStatement::applyIndent()
833 {
834 int indentToAdd = indents.top() - line.length();
835 if (indentToAdd <= 0)
836 return false;
837
838 line += SPACE.repeated(indentToAdd);
839 return true;
840 }
841
applySpace(FormatToken::Type type)842 void FormatStatement::applySpace(FormatToken::Type type)
843 {
844 if (lastToken && isSpaceExpectingType(type) && isSpaceExpectingType(lastToken->type) && !endsWithSpace())
845 line += SPACE;
846 }
847
isSpaceExpectingType(FormatStatement::FormatToken::Type type)848 bool FormatStatement::isSpaceExpectingType(FormatStatement::FormatToken::Type type)
849 {
850 switch (type)
851 {
852 case FormatToken::KEYWORD:
853 case FormatToken::LINED_UP_KEYWORD:
854 case FormatToken::ID:
855 case FormatToken::ID_NO_WRAP:
856 case FormatToken::STRING_OR_ID:
857 case FormatToken::FLOAT:
858 case FormatToken::STRING:
859 case FormatToken::INTEGER:
860 case FormatToken::BLOB:
861 case FormatToken::BIND_PARAM:
862 case FormatToken::FUNC_ID:
863 case FormatToken::DATA_TYPE:
864 case FormatToken::STAR:
865 return true;
866 case FormatToken::OPERATOR:
867 case FormatToken::ID_DOT:
868 case FormatToken::PAR_DEF_LEFT:
869 case FormatToken::PAR_DEF_RIGHT:
870 case FormatToken::PAR_EXPR_LEFT:
871 case FormatToken::PAR_EXPR_RIGHT:
872 case FormatToken::PAR_FUNC_LEFT:
873 case FormatToken::PAR_FUNC_RIGHT:
874 case FormatToken::SEMICOLON:
875 case FormatToken::COMMA_LIST:
876 case FormatToken::COMMA_OPER:
877 case FormatToken::NEW_LINE:
878 case FormatToken::INDENT_MARKER:
879 case FormatToken::INCR_INDENT:
880 case FormatToken::DECR_INDENT:
881 case FormatToken::SET_INDENT:
882 case FormatToken::MARK_KEYWORD_LINEUP:
883 break;
884 }
885 return false;
886 }
887
isMetaType(FormatStatement::FormatToken::Type type)888 bool FormatStatement::isMetaType(FormatStatement::FormatToken::Type type)
889 {
890 switch (type)
891 {
892 case FormatToken::INDENT_MARKER:
893 case FormatToken::INCR_INDENT:
894 case FormatToken::DECR_INDENT:
895 case FormatToken::SET_INDENT:
896 case FormatToken::MARK_KEYWORD_LINEUP:
897 return true;
898 case FormatToken::KEYWORD:
899 case FormatToken::LINED_UP_KEYWORD:
900 case FormatToken::ID:
901 case FormatToken::ID_NO_WRAP:
902 case FormatToken::STRING_OR_ID:
903 case FormatToken::FLOAT:
904 case FormatToken::STRING:
905 case FormatToken::INTEGER:
906 case FormatToken::BLOB:
907 case FormatToken::BIND_PARAM:
908 case FormatToken::FUNC_ID:
909 case FormatToken::DATA_TYPE:
910 case FormatToken::OPERATOR:
911 case FormatToken::STAR:
912 case FormatToken::ID_DOT:
913 case FormatToken::PAR_DEF_LEFT:
914 case FormatToken::PAR_DEF_RIGHT:
915 case FormatToken::PAR_EXPR_LEFT:
916 case FormatToken::PAR_EXPR_RIGHT:
917 case FormatToken::PAR_FUNC_LEFT:
918 case FormatToken::PAR_FUNC_RIGHT:
919 case FormatToken::SEMICOLON:
920 case FormatToken::COMMA_LIST:
921 case FormatToken::COMMA_OPER:
922 case FormatToken::NEW_LINE:
923 break;
924 }
925 return false;
926 }
927
newLine()928 void FormatStatement::newLine()
929 {
930 if (line.length() == 0) // prevents double new-line when for example "))" occurs and it has new-line before and after
931 return;
932
933 lines << line;
934 line = "";
935 }
936
incrIndent(const QString & name)937 void FormatStatement::incrIndent(const QString& name)
938 {
939 if (!name.isNull())
940 {
941 if (namedIndents.contains(name))
942 {
943 indents.push(namedIndents[name]);
944 }
945 else
946 {
947 indents.push(indents.top() + cfg->SqlEnterpriseFormatter.TabSize.get());
948 qCritical() << __func__ << "No named indent found:" << name;
949 }
950 }
951 else
952 indents.push(indents.top() + cfg->SqlEnterpriseFormatter.TabSize.get());
953 }
954
decrIndent()955 void FormatStatement::decrIndent()
956 {
957 if (indents.size() <= 1)
958 return;
959
960 indents.pop();
961 }
962
setIndent(int newIndent)963 void FormatStatement::setIndent(int newIndent)
964 {
965 indents.push(newIndent);
966 }
967
endsWithSpace()968 bool FormatStatement::endsWithSpace()
969 {
970 return line.length() == 0 || line[line.length() - 1].isSpace();
971 }
972
getLastRealToken(bool skipNewLines)973 FormatStatement::FormatToken* FormatStatement::getLastRealToken(bool skipNewLines)
974 {
975 for (FormatToken* tk : reverse(tokens))
976 {
977 if (!isMetaType(tk->type) && (!skipNewLines || tk->type != FormatToken::NEW_LINE))
978 return tk;
979 }
980 return nullptr;
981 }
982
getLastToken()983 FormatStatement::FormatToken* FormatStatement::getLastToken()
984 {
985 return tokens.last();
986 }
987
detokenizeLeftPar(FormatToken * token,bool spaceBefore,bool spaceAfter,bool nlBefore,bool nlAfter)988 void FormatStatement::detokenizeLeftPar(FormatToken* token, bool spaceBefore, bool spaceAfter, bool nlBefore, bool nlAfter)
989 {
990 bool spaceAdded = endsWithSpace();
991 if (nlBefore)
992 {
993 newLine();
994 spaceAdded = true;
995 }
996
997 spaceAdded |= applyIndent();
998 if (spaceBefore && !spaceAdded)
999 line += SPACE;
1000
1001 line += token->value.toString();
1002 if (nlAfter)
1003 {
1004 newLine();
1005 if (cfg->SqlEnterpriseFormatter.IndentParenthesisBlock.get())
1006 incrIndent();
1007 }
1008 else if (spaceAfter)
1009 line += SPACE;
1010 }
1011
detokenizeRightPar(FormatStatement::FormatToken * token,bool spaceBefore,bool spaceAfter,bool nlBefore,bool nlAfter)1012 void FormatStatement::detokenizeRightPar(FormatStatement::FormatToken* token, bool spaceBefore, bool spaceAfter, bool nlBefore, bool nlAfter)
1013 {
1014 bool spaceAdded = endsWithSpace();
1015 if (nlBefore)
1016 {
1017 newLine();
1018 spaceAdded = true;
1019 if (cfg->SqlEnterpriseFormatter.IndentParenthesisBlock.get())
1020 decrIndent();
1021 }
1022
1023 spaceAdded |= applyIndent();
1024 if (spaceBefore && !spaceAdded)
1025 line += SPACE;
1026
1027 line += token->value.toString();
1028 if (nlAfter)
1029 newLine();
1030 else if (spaceAfter)
1031 line += SPACE;
1032 }
1033
resetIndents()1034 void FormatStatement::resetIndents()
1035 {
1036 indents.clear();
1037 indents.push(0);
1038 }
1039
removeAllSpaces()1040 void FormatStatement::removeAllSpaces()
1041 {
1042 removeAllSpacesFromLine();
1043 while (endsWithSpace() && lines.size() > 0)
1044 {
1045 line = lines.takeLast();
1046 removeAllSpacesFromLine();
1047
1048 if (lines.size() == 0)
1049 break;
1050 }
1051 }
1052
removeAllSpacesFromLine()1053 void FormatStatement::removeAllSpacesFromLine()
1054 {
1055 while (endsWithSpace() && line.length() > 0)
1056 line.chop(1);
1057 }
1058
updateLastToken(FormatStatement::FormatToken * token)1059 void FormatStatement::updateLastToken(FormatStatement::FormatToken* token)
1060 {
1061 if (!isMetaType(token->type))
1062 lastToken = token;
1063 }
1064
getFinalLineUpName(const QString & lineUpName)1065 QString FormatStatement::getFinalLineUpName(const QString& lineUpName)
1066 {
1067 QString finalName = statementName;
1068 if (!lineUpName.isNull())
1069 finalName += "_" + lineUpName;
1070
1071 return finalName;
1072 }
1073
predictCurrentIndent(FormatToken * currentMetaToken)1074 int FormatStatement::predictCurrentIndent(FormatToken* currentMetaToken)
1075 {
1076 QString lineBackup = line;
1077 bool isSpace = applyIndent() || endsWithSpace();
1078
1079 if (!isSpace)
1080 {
1081 // We haven't added any space and there is no space currently at the end of line.
1082 // We need to predict if next real (printable) token will require space to be added.
1083 // If yes, we add it virtually here, so we know the indent required afterwards.
1084 // First we need to find next real token:
1085 int tokenIdx = tokens.indexOf(currentMetaToken);
1086 FormatToken* nextRealToken = nullptr;
1087 for (FormatToken* tk : tokens.mid(tokenIdx + 1))
1088 {
1089 if (!isMetaType(tk->type))
1090 {
1091 nextRealToken = tk;
1092 break;
1093 }
1094 }
1095
1096 // If the real token was found we can see if it will require additional space for indent:
1097 if ((nextRealToken && isSpaceExpectingType(lastToken->type) && isSpaceExpectingType(nextRealToken->type)) || willStartWithNewLine(nextRealToken))
1098 {
1099 // Next real token does not start with new line, but it does require additional space:
1100 line += SPACE;
1101 }
1102 }
1103
1104 int result = line.length();
1105 line = lineBackup;
1106 return result;
1107 }
1108
willStartWithNewLine(FormatStatement::FormatToken * token)1109 bool FormatStatement::willStartWithNewLine(FormatStatement::FormatToken* token)
1110 {
1111 return (token->type == FormatToken::PAR_DEF_LEFT && cfg->SqlEnterpriseFormatter.NlBeforeOpenParDef) ||
1112 (token->type == FormatToken::PAR_EXPR_LEFT && cfg->SqlEnterpriseFormatter.NlBeforeOpenParExpr) ||
1113 (token->type == FormatToken::PAR_FUNC_LEFT && cfg->SqlEnterpriseFormatter.NlBeforeOpenParExpr) ||
1114 (token->type == FormatToken::PAR_DEF_RIGHT && cfg->SqlEnterpriseFormatter.NlBeforeCloseParDef) ||
1115 (token->type == FormatToken::PAR_EXPR_RIGHT && cfg->SqlEnterpriseFormatter.NlBeforeCloseParExpr) ||
1116 (token->type == FormatToken::PAR_FUNC_RIGHT && cfg->SqlEnterpriseFormatter.NlBeforeCloseParExpr) ||
1117 (token->type == FormatToken::NEW_LINE);
1118 }
1119
formatId(const QString & value,bool applyWrapping)1120 void FormatStatement::formatId(const QString& value, bool applyWrapping)
1121 {
1122 if (!applyWrapping)
1123 {
1124 line += value;
1125 return;
1126 }
1127
1128 if (cfg->SqlEnterpriseFormatter.AlwaysUseNameWrapping.get())
1129 line += wrapObjName(value, true, wrapper);
1130 else
1131 line += wrapObjIfNeeded(value, true, wrapper);
1132 }
1133
forQuery(SqliteStatement * query,NameWrapper wrapper,Cfg::SqlEnterpriseFormatterConfig * cfg)1134 FormatStatement* FormatStatement::forQuery(SqliteStatement* query, NameWrapper wrapper, Cfg::SqlEnterpriseFormatterConfig* cfg)
1135 {
1136 FormatStatement* formatStmt = forQuery(query);
1137 if (formatStmt)
1138 {
1139 formatStmt->wrapper = wrapper;
1140 formatStmt->cfg = cfg;
1141 }
1142 return formatStmt;
1143 }
1144