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