1 #include "statementtokenbuilder.h"
2 #include "parser/ast/sqlitestatement.h"
3 #include "common/utils_sql.h"
4 #include <QVariant>
5 
withKeyword(const QString & value)6 StatementTokenBuilder& StatementTokenBuilder::withKeyword(const QString& value)
7 {
8     return with(Token::KEYWORD, value);
9 }
10 
withOther(const QString & value)11 StatementTokenBuilder& StatementTokenBuilder::withOther(const QString& value)
12 {
13     return withOther(value, true);
14 }
15 
withOther(const QString & value,bool wrapIfNeeded)16 StatementTokenBuilder& StatementTokenBuilder::withOther(const QString& value, bool wrapIfNeeded)
17 {
18     return with(Token::OTHER, wrapIfNeeded ? wrapObjIfNeeded(value) : value);
19 }
20 
withStringPossiblyOther(const QString & value)21 StatementTokenBuilder&StatementTokenBuilder::withStringPossiblyOther(const QString& value)
22 {
23     if (value.contains("\""))
24         return withOther(wrapObjIfNeeded(value));
25     else
26         return withOther(wrapObjName(value, NameWrapper::DOUBLE_QUOTE));
27 }
28 
withOtherList(const QList<QString> & value,const QString & separator)29 StatementTokenBuilder& StatementTokenBuilder::withOtherList(const QList<QString>& value, const QString& separator)
30 {
31     bool first = true;
32     for (const QString& str : value)
33     {
34         if (!first)
35         {
36             if (!separator.isEmpty())
37                 withOperator(separator);
38 
39             withSpace();
40         }
41         withOther(str);
42         first = false;
43     }
44     return *this;
45 }
46 
withOperator(const QString & value)47 StatementTokenBuilder& StatementTokenBuilder::withOperator(const QString& value)
48 {
49     return with(Token::OPERATOR, value);
50 }
51 
withComment(const QString & value)52 StatementTokenBuilder& StatementTokenBuilder::withComment(const QString& value)
53 {
54     return with(Token::COMMENT, value);
55 }
56 
withFloat(const QVariant & value)57 StatementTokenBuilder& StatementTokenBuilder::withFloat(const QVariant& value)
58 {
59     return with(Token::FLOAT, doubleToString(value));
60 }
61 
withInteger(qint64 value)62 StatementTokenBuilder& StatementTokenBuilder::withInteger(qint64 value)
63 {
64     return with(Token::INTEGER, QString::number(value));
65 }
66 
withBindParam(const QString & value)67 StatementTokenBuilder& StatementTokenBuilder::withBindParam(const QString& value)
68 {
69     return with(Token::BIND_PARAM, value);
70 }
71 
withParLeft()72 StatementTokenBuilder& StatementTokenBuilder::withParLeft()
73 {
74     return with(Token::PAR_LEFT, "(");
75 }
76 
withParRight()77 StatementTokenBuilder& StatementTokenBuilder::withParRight()
78 {
79     return with(Token::PAR_RIGHT, ")");
80 }
81 
withSpace()82 StatementTokenBuilder& StatementTokenBuilder::withSpace()
83 {
84     return with(Token::SPACE, " ");
85 }
86 
withBlob(const QString & value)87 StatementTokenBuilder& StatementTokenBuilder::withBlob(const QString& value)
88 {
89     return with(Token::BLOB, value);
90 }
91 
withString(const QString & value)92 StatementTokenBuilder& StatementTokenBuilder::withString(const QString& value)
93 {
94     return with(Token::STRING, wrapStringIfNeeded(value));
95 }
96 
withConflict(SqliteConflictAlgo onConflict)97 StatementTokenBuilder& StatementTokenBuilder::withConflict(SqliteConflictAlgo onConflict)
98 {
99     if (onConflict != SqliteConflictAlgo::null)
100         return withSpace().withKeyword("ON").withSpace().withKeyword("CONFLICT")
101                 .withSpace().withKeyword(sqliteConflictAlgo(onConflict));
102 
103     return *this;
104 }
105 
withSortOrder(SqliteSortOrder sortOrder)106 StatementTokenBuilder& StatementTokenBuilder::withSortOrder(SqliteSortOrder sortOrder)
107 {
108     if (sortOrder != SqliteSortOrder::null)
109         return withSpace().withKeyword(sqliteSortOrder(sortOrder));
110 
111     return *this;
112 }
113 
withStatement(SqliteStatement * stmt)114 StatementTokenBuilder& StatementTokenBuilder::withStatement(SqliteStatement* stmt)
115 {
116     if (!stmt)
117         return *this;
118 
119     stmt->rebuildTokens();
120     if (stmt->tokens.size() > 0)
121     {
122         if (tokens.size() > 0 && !tokens.last()->isWhitespace() && tokens.last()->type != Token::PAR_LEFT)
123             withSpace();
124 
125         tokens += stmt->tokens;
126         tokens.trimRight(Token::OPERATOR, ";");
127     }
128     return *this;
129 }
130 
withTokens(TokenList tokens)131 StatementTokenBuilder& StatementTokenBuilder::withTokens(TokenList tokens)
132 {
133     this->tokens += tokens;
134     return *this;
135 }
136 
withLiteralValue(const QVariant & value)137 StatementTokenBuilder& StatementTokenBuilder::withLiteralValue(const QVariant& value)
138 {
139     if (value.isNull())
140         return *this;
141 
142     if (value.userType() == QVariant::String)
143     {
144         withString(value.toString());
145         return *this;
146     }
147 
148     bool ok;
149     if (value.userType() == QVariant::Double)
150     {
151         value.toDouble(&ok);
152         if (ok)
153         {
154             withFloat(value);
155             return *this;
156         }
157     }
158 
159     qint64 longVal = value.toLongLong(&ok);
160     if (ok)
161     {
162         withInteger(longVal);
163         return *this;
164     }
165 
166     QString str = value.toString();
167     if (str.startsWith("x'", Qt::CaseInsensitive) && str.endsWith("'"))
168     {
169         withBlob(str);
170         return *this;
171     }
172 
173     withString(str);
174     return *this;
175 }
176 
build() const177 TokenList StatementTokenBuilder::build() const
178 {
179     return tokens;
180 }
181 
clear()182 void StatementTokenBuilder::clear()
183 {
184     tokens.clear();
185     currentIdx = 0;
186 }
187 
with(Token::Type type,const QString & value)188 StatementTokenBuilder& StatementTokenBuilder::with(Token::Type type, const QString& value)
189 {
190     int size = value.size();
191     tokens << TokenPtr::create(type, value, currentIdx, currentIdx + size - 1);
192     currentIdx += size;
193     return *this;
194 }
195