3
* TOra - An Oracle Toolkit for DBA's and developers
4
* Copyright (C) 2003-2005 Quest Software, Inc
5
* Portions Copyright (C) 2005 Other Contributors
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; only version 2 of
10
* the License is valid for this program.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
* As a special exception, you have permission to link this program
22
* with the Oracle Client libraries and distribute executables, as long
23
* as you follow the requirements of the GNU GPL in regard to all of the
24
* software in the executable aside from Oracle client libraries.
26
* Specifically you are not permitted to link this program with the
27
* Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech.
28
* And you are not permitted to distribute binaries compiled against
29
* these libraries without written consent from Quest Software, Inc.
30
* Observe that this does not disallow linking to the Qt Free Edition.
32
* You may link this product with any GPL'd Qt library such as Qt/Free
34
* All trademarks belong to their respective owners.
40
#include "toconnection.h"
41
#include "tohighlightedtext.h"
42
#include "tosqlparse.h"
44
#include <qapplication.h>
45
#include <qstringlist.h>
51
bool toMonolithic(void)
56
void printStatement(toSQLParse::statement &stat, int level)
58
for (int i = 0;i < level;i++)
63
case toSQLParse::statement::Block:
66
case toSQLParse::statement::Statement:
69
case toSQLParse::statement::List:
72
case toSQLParse::statement::Keyword:
75
case toSQLParse::statement::Token:
78
case toSQLParse::statement::Raw:
82
printf("%s (%d)\n", (const char *)stat.String, stat.Line);
83
if (!stat.Comment.isNull())
85
for (int i = 0;i < level;i++)
87
printf("Comment:%s\n", (const char *)stat.Comment);
89
for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin();
90
i != stat.subTokens().end();
92
printStatement(*i, level + 1);
95
int main(int argc, char **argv)
98
"create table test ( col varchar(12) );\n"
99
"insert into prova3 (prova)\n"
100
"values ('This insert contains a ''\n"
101
"and now it goes to new line');\n"
102
"create or replace PROCEDURE prova1\n"
107
"select 0 into v_tmp from dual;\n"
110
" v_tmp := 'Dadum';\n"
112
"if sqlcode=0 then\n"
123
"comment on column prova1.prova1 is 'This comment is\n"
124
"on more than one line';\n"
125
"PACKAGE oasSIMActivation AS\n"
126
" FUNCTION ParseCommand(Command VARCHAR2,inICC VARCHAR2,Param VARCHAR2) RETURN VARCHAR2;\n"
128
" PROCEDURE InsertActions(inCommandType VARCHAR2,\n"
129
" Sim oasSIM%ROWTYPE,\n"
130
" inParam VARCHAR2);\n"
132
" PROCEDURE InsertActions(CommandType VARCHAR2,\n"
134
" inParam VARCHAR2);\n"
136
" PROCEDURE InsertActions(inCommandType VARCHAR2,\n"
137
" Service oasService%ROWTYPE);\n"
139
" PROCEDURE InsertActions(CommandType VARCHAR2,\n"
140
" inCustomerID NUMBER,\n"
142
" inServiceType VARCHAR2,\n"
143
" Param VARCHAR2);\n"
147
"appraisal VARCHAR2(20);\n"
150
"WHEN 'A' THEN 'Excellent'\n"
151
"WHEN 'B' THEN 'Very Good'\n"
152
"WHEN 'C' THEN 'Good'\n"
153
"WHEN 'D' THEN 'Fair'\n"
154
"WHEN 'F' THEN 'Poor'\n"
155
"ELSE 'No such grade'\n"
157
"IF appraisal IS NULL THEN\n"
166
"IF appraisal IS NULL THEN\n"
169
"SELECT CASE WHEN dummy='X' THEN 'A' ELSE 'B' END, 2 FROM dual;\n"
173
"select count(case when dummy = 'Y' then dummy\n"
174
" else null end) as tot_str\n"
177
"SET TRANSACTION READ ONLY\n"
183
"INSERT INTO cdrProcess(ProcessID,\n"
204
"CREATE or REPLACE Procedure TEST_SPR\n"
206
" IN_TICKET_NUM IN VARCHAR2\n"
214
"for cur_rec in (select emp_id from employees) loop\n"
216
" update employees set emp_id = emp_id + 1\n"
217
" where emp_id = cur_rec.emp_id;\n"
226
" TYPE FROM v$access\n"
227
" WHERE sid=:f1<char[101]>\n"
232
"CREATE TABLE ess.EssCalLog (\n"
233
" CalID CHAR(5) NOT NULL, -- Calender type\n"
234
" SeqID NUMBER(8) NOT NULL,\n"
235
" ActStt CHAR(1) NOT NULL\n"
236
" CONSTRAINT EssCalLog_CK_ActStt CHECK (ActStt IN ('A','D') ),\n"
237
" LogRun CHAR(1) NOT NULL -- Should runs of this type be logged\n"
238
" CONSTRAINT EssCalLog_CK_LogRun CHECK (LogRun IN ('Y','N') ),\n"
239
" PrcID NUMBER(8) NOT NULL\n"
240
" CONSTRAINT EssCalDay_FK_PrcID REFERENCES ess.EssPrc(PrcID),\n"
241
" Dsc VARCHAR2(4000) NOT NULL, -- Description of this type\n"
242
" CONSTRAINT EssCal_PK PRIMARY KEY (CalID,SeqID)\n"
243
" USING INDEX TABLESPACE Index02 -- A Comment\n"
245
"-- Another comment\n"
247
"CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER,\n"
248
" oNumSwt OUT NUMBER)\n"
260
" WHEN VALUE_ERROR THEN\n"
262
" WHEN NO_DATA_FOUND THEN\n"
264
" WHEN OTHERS THEN\n"
267
"CREATE OR REPLACE procedure spTuxGetAccData as\n"
272
"-------------------------------------------------------------------\n"
273
"-- EssCal, Current calendar view\n"
275
"CREATE VIEW ess.EssCal AS\n"
280
" FROM ess.EssCalLog a\n"
281
" WHERE SeqID = (SELECT MAX(aa.SeqID) FROM EssCalLog aa WHERE aa.CalID = a.CalID)\n"
282
" AND ActStt = 'A';\n"
284
" /* A little comment\n"
288
"*/ a.TskCod TskCod -- Test comment\n"
289
" ,a.CreEdt CreEdt,\n"
290
" a.TspActOprID /* One comment OprID */ , -- Another comment\n"
292
" COUNT(a.TspActOprID) Lft,\n"
293
" b.TraCod TraCod,\n"
294
" SUM(b.FinAmt) FinAmt,\n"
296
" FROM EssTsk a,EssTra b\n"
297
" WHERE ((a.TspActOprID = 'Test') OR a.TspActOprID IS NULL)\n"
298
" AND DECODE(a.TspActOprID,NULL,NULL,a.TskID) = b.TskID(+)\n"
299
" GROUP BY a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n"
300
"HAVING COUNT(a.TspActOprID) > 0;\n"
301
"SELECT a.Sid \"-Id\",\n"
302
" a.Serial# \"-Serial#\",\n"
303
" a.SchemaName \"Schema\",\n"
304
" a.Status \"Status\",\n"
305
" a.Server \"Server\",\n"
306
" a.OsUser \"Osuser\",\n"
307
" a.Machine \"Machine\",\n"
308
" a.Program \"Program\",\n"
309
" a.Type \"Type\",\n"
310
" a.Module \"Module\",\n"
311
" a.Action \"Action\",\n"
312
" a.Client_Info \"Client Info\",\n"
313
" b.Block_Gets \"-Block Gets\",\n"
314
" b.Consistent_Gets \"-Consistent Gets\",\n"
315
" b.Physical_Reads \"-Physical Reads\",\n"
316
" b.Block_Changes \"-Block Changes\",\n"
317
" b.Consistent_Changes \"-Consistent Changes\",\n"
318
" c.Value*10 \"-CPU (ms)\",\n"
319
" a.Process \"-Process\",\n"
320
" a.SQL_Address||':'||SQL_Hash_Value \" SQL Address\",\n"
321
" a.Prev_SQL_Addr||':'||Prev_Hash_Value \" Prev SQl Address\"\n"
322
" FROM v$session a,\n"
325
" WHERE a.sid = b.sid(+)\n"
326
" AND a.sid = c.sid(+) AND (c.statistic# = 12 OR c.statistic# IS NULL)\n"
328
"select a.TskCod TskCod,\n"
330
" from (select * from EssTsk where PrsID >= '1940') ,EssTra b\n"
331
" where decode(a.TspActOprID,NULL,NULL,a.PrsID)+5 = b.PrsID(+)\n"
332
" group by a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n"
333
"having count(a.TspActOprID) > 0;\n"
335
"CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER)\n"
345
" WHEN VALUE_ERROR THEN\n"
353
QApplication test(argc, argv);
354
toMarkedText text(NULL);
358
toSQLParse::editorTokenizer tokens(&text);
360
std::list<toSQLParse::statement> stat = toSQLParse::parse(tokens);
362
for (std::list<toSQLParse::statement>::iterator i = stat.begin();i != stat.end();i++)
364
printStatement(*i, 1);
368
QString firstparse = toSQLParse::indent(res);
369
QString secondparse = toSQLParse::indent(firstparse);
371
printf("First\n\n%s\n", (const char *)firstparse);
373
if (firstparse != secondparse)
375
printf("Reparse doesn't match\n");
376
printf("Second\n\n%s\n", (const char *)secondparse);
384
toSQLParse::statement::statement(type ntype, const QString &token, int cline)
385
: Type(ntype), String(token), Line(cline)
390
std::list<toSQLParse::statement> &toSQLParse::statement::subTokens(void)
393
SubTokens = new std::list<statement>;
397
toSQLParse::statement::~statement()
402
toSQLParse::statement::statement(const statement &stat)
405
String = stat.String;
406
Comment = stat.Comment;
410
SubTokens = new std::list<statement>;
411
(*SubTokens) = (*stat.SubTokens);
417
const toSQLParse::statement &toSQLParse::statement::operator = (const statement &stat)
420
String = stat.String;
421
Comment = stat.Comment;
426
SubTokens = new std::list<statement>;
427
(*SubTokens) = (*stat.SubTokens);
434
bool toSQLParse::statement::operator == (const statement &stat) const
436
if (Type != stat.Type ||
437
Comment != stat.Comment ||
438
String != stat.String)
442
if (!stat.SubTokens && SubTokens->begin() != SubTokens->end())
444
if ((*SubTokens) != (*stat.SubTokens))
447
else if (stat.SubTokens && stat.SubTokens->begin() != stat.SubTokens->end())
452
static const char *Operators[] =
469
QString toSQLParse::stringTokenizer::getToken(bool forward, bool comments)
488
int inc = forward ? 1 : -1;
490
while ((forward && Offset < int(String.length())) || (!forward && Offset >= 1))
497
if ((forward && Offset < int(String.length() - 1)) || (!forward && Offset > 0))
498
nc = String[Offset + inc];
503
if (forward && c == '-' && nc == '-')
507
for (Offset++;Offset < int(String.length()) && String[Offset] != '\n';Offset++)
510
return String.mid(spos, Offset - spos);
513
if (c == '/' && nc == '*')
515
else if ((forward && c == '<' && nc == '<') ||
516
(!forward && c == '>' && nc == '>'))
518
else if (!c.isSpace())
534
if (c == '*' && nc == '/')
546
token = QString::null;
551
if ((forward && c == '>' && nc == '>') ||
552
(!forward && c == '<' && nc == '<'))
578
if (c == ':' && toIsIdent(nc))
582
else if (toIsIdent(c))
588
else if (c == '\'' || c == analyzer().quoteCharacter())
595
for (int i = 0;Operators[i];i++)
597
if ((forward && c == Operators[i][0] && nc == Operators[i][1]) ||
598
(!forward && nc == Operators[i][0] && c == Operators[i][1]))
641
QString toSQLParse::stringTokenizer::remaining(bool eol)
646
int pos = String.find('\n', Offset);
649
ret = String.mid(Offset, pos - Offset);
654
ret = String.mid(Offset);
655
Offset = String.length();
660
toSQLParse::editorTokenizer::editorTokenizer(toMarkedText *editor, int offset, int line)
661
: tokenizer(offset, line)
664
toHighlightedText *text = dynamic_cast<toHighlightedText *>(editor);
666
setAnalyzer(text->analyzer());
669
QString toSQLParse::editorTokenizer::getToken(bool forward, bool comments)
672
while (Line < int(Editor->lines()) && Line >= 0)
674
QString line = Editor->text(Line);
680
Offset = line.length();
682
stringTokenizer token(line, analyzer(), Offset, forward);
683
QString ret = token.getToken(forward, true);
684
Offset = token.offset();
691
if (ret.startsWith(("/*")) &&
692
(ret.at(ret.length() - 2) != '*' ||
693
ret.at(ret.length() - 1) != '/'))
697
else if (ret.startsWith("'") && ((ret.contains("'") % 2) != 0 || ret.at(ret.length() - 1) != '\''))
701
else if (ret.startsWith(analyzer().quoteCharacter()) &&
702
((ret.contains(analyzer().quoteCharacter()) % 2) != 0 || ret.at(ret.length() - 1) != analyzer().quoteCharacter()))
704
end = analyzer().quoteCharacter();
709
Line < int(Editor->lines()) && (Offset = Editor->text(Line).find(end)) < 0;
711
ret += ("\n") + Editor->text(Line);
712
if (Line < int(Editor->lines()))
714
ret += ("\n") + Editor->text(Line).mid(0, Offset + end.length());
715
Offset += end.length();
722
if (ret.length() >= 2 &&
723
ret.at(ret.length() - 2) == '*' &&
724
ret.at(ret.length() - 1) == '/' &&
725
!ret.startsWith(("/*")))
729
else if ((ret.length() >= 1 && ret.at(ret.length() - 1) == '\'') &&
730
(ret.length() < 2 || ret[0] != '\''))
734
else if ((ret.length() >= 1 && ret.at(ret.length() - 1) == analyzer().quoteCharacter()) &&
735
(ret.length() < 2 || ret.at(0) != analyzer().quoteCharacter()))
737
end = analyzer().quoteCharacter();
742
Line >= 0 && (Offset = Editor->text(Line).findRev(end)) < 0;
744
ret.prepend(Editor->text(Line) + ("\n"));
747
QString str = Editor->text(Line);
748
ret.prepend(str.mid(Offset, str.length() - Offset) + ("\n"));
752
if (comments || (!ret.startsWith(("/*")) && !ret.startsWith(("--")) && !ret.startsWith("//")))
760
Line += (forward ? 1 : -1);
763
return QString::null;
766
QString toSQLParse::editorTokenizer::remaining(bool eol)
768
if (Line >= Editor->lines())
769
return QString::null;
773
rows << Editor->text(Line).mid(Offset);
774
for (int i = Line;i < Editor->lines();i++)
775
rows << Editor->text(i);
776
Line = Editor->lines();
778
return rows.join(("\n"));
782
QString line = Editor->text(Line);
783
QString ret = line.mid(offset());
784
Offset = line.length();
789
toSQLParse::statement toSQLParse::parseStatement(tokenizer &tokens, bool declare, bool lst)
791
statement ret(statement::Statement);
793
toSyntaxAnalyzer &syntax = tokens.analyzer();
799
for (QString token = tokens.getToken(true, true);
801
token = tokens.getToken(true, true))
803
QString upp = token.upper();
806
printf("%s (%d)\n", (const char*)token, tokens.line());
809
if (first.isNull() && !token.startsWith(("/*")) && !token.startsWith("--") && !token.startsWith("//"))
810
realfirst = first = upp;
812
if (upp == ("PROCEDURE") ||
813
upp == ("FUNCTION") ||
820
if (first != ("END") && ((first == ("IF") && upp == ("THEN")) ||
823
(syntax.declareBlock() && upp == ("DECLARE")) ||
824
(block && upp == ("AS")) ||
825
(block && upp == ("IS")) ||
826
((!declare || block) && upp == ("BEGIN"))))
829
statement blk(statement::Block);
830
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Keyword, token, tokens.line()));
831
blk.subTokens().insert(blk.subTokens().end(), ret);
832
statement cur(statement::Statement);
833
bool dcl = (upp == ("DECLARE") || upp == ("IS") || upp == ("AS"));
836
cur = parseStatement(tokens, dcl, false);
837
if (cur.Type == statement::List)
838
toStatusMessage(qApp->translate("toSQLparse", "Unbalanced parenthesis (Too many ')')"));
839
blk.subTokens().insert(blk.subTokens().end(), cur);
840
if (cur.subTokens().begin() != cur.subTokens().end() &&
841
(*(cur.subTokens().begin())).String.upper() == ("BEGIN"))
844
while (cur.subTokens().begin() != cur.subTokens().end() &&
845
(*cur.subTokens().begin()).String.upper() != ("END"));
848
else if (((first == "IF" && upp == "THEN") ||
849
(first == "WHEN" && upp == "THEN") ||
850
(first == "ELSIF" && upp == "THEN") ||
852
upp == ("EXCEPTION") ||
853
first == ("ELSE")) && !lst)
855
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Keyword, token, tokens.line()));
858
else if (first == ("ASSIGN") ||
860
first == ("PROMPT") ||
861
first == ("COLUMN") ||
862
first == ("SPOOL") ||
863
first == ("STORE") ||
864
first == ("REMARK") ||
867
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Keyword, token, tokens.line()));
868
int line = tokens.line();
869
int offset = tokens.offset();
870
for (QString tmp = tokens.getToken(true, true);line == tokens.line();tmp = tokens.getToken(true, true))
871
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token, tmp, line));
872
tokens.setLine(line);
873
tokens.setOffset(offset);
874
tokens.remaining(true);
877
else if (upp == (",") ||
878
(syntax.reservedWord(upp) &&
886
upp != ("BETWEEN") &&
889
upp != ("NULL")) && !nokey)
891
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Keyword, token, tokens.line()));
894
else if (upp == ("("))
896
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token, token, tokens.line()));
897
statement lst = parseStatement(tokens, false, true);
898
statement t = toPop(lst.subTokens());
899
if (lst.Type != statement::List)
900
toStatusMessage(qApp->translate("toSQLparse", "Unbalanced parenthesis (Too many '(')"));
902
if (first == ("CREATE") && !block)
904
statement end = parseStatement(tokens, false, true);
905
statement blk(statement::Block);
906
blk.subTokens().insert(blk.subTokens().end(), ret);
907
blk.subTokens().insert(blk.subTokens().end(), lst);
908
end.subTokens().insert(end.subTokens().begin(), t);
909
blk.subTokens().insert(blk.subTokens().end(), end);
914
ret.subTokens().insert(ret.subTokens().end(), lst);
915
ret.subTokens().insert(ret.subTokens().end(), t);
918
else if (upp == (")"))
920
ret.Type = statement::List;
921
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token, token, tokens.line()));
924
else if (upp == (";"))
926
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token, token, tokens.line()));
929
else if (upp.startsWith(("/*+")) || upp.startsWith(("--+")))
932
if (com.startsWith(("--+")))
933
com = ("/*+ ") + com.mid(3) + (" */");
934
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token,
935
com.simplifyWhiteSpace(), tokens.line()));
937
else if (upp.startsWith(("/*")) || upp.startsWith(("--")) || upp.startsWith("//"))
939
if ( ret.subTokens().empty() )
941
if (ret.Comment.isNull())
944
ret.Comment += ("\n") + token;
948
QString &com = (*ret.subTokens().rbegin()).Comment;
952
com += ("\n") + token;
957
ret.subTokens().insert(ret.subTokens().end(), statement(statement::Token, token, tokens.line()));
958
nokey = (token == ("."));
960
if (upp == ("AS") || upp == ("IS"))
962
else if (first == ("IS") && upp == ("NULL"))
968
std::list<toSQLParse::statement> toSQLParse::parse(tokenizer &tokens)
970
std::list<toSQLParse::statement> ret;
971
statement cur(statement::Statement);
972
for (cur = parseStatement(tokens, false, false);
973
cur.subTokens().begin() != cur.subTokens().end();
974
cur = parseStatement(tokens, false, false))
976
if (cur.Type == statement::List)
977
toStatusMessage(qApp->translate("toSQLparse", "Unbalanced parenthesis (Too many ')')"));
978
ret.insert(ret.end(), cur);
980
QString str = tokens.remaining(false);
982
ret.insert(ret.end(), statement(statement::Raw,
983
str, tokens.line()));
987
toSQLParse::statement toSQLParse::parseStatement(tokenizer &tokens)
989
statement cur(statement::Statement);
990
cur = parseStatement(tokens, false, false);
991
if (cur.Type == statement::List)
992
toStatusMessage(qApp->translate("toSQLparse", "Unbalanced parenthesis (Too many ')')"));
996
int toSQLParse::countIndent(const QString &txt, int &chars)
999
while (txt[chars].isSpace() && chars < int(txt.length()))
1001
char c = txt[chars].latin1();
1007
level = (level / toMarkedText::defaultTabWidth() + 1) * toMarkedText::defaultTabWidth();
1013
toSQLParse::settings toSQLParse::Settings = {true,
1023
QString toSQLParse::indentString(int level)
1026
if (Settings.ExpandSpaces)
1028
for (int i = 0;i < level / 8;i++)
1030
for (int j = 0;j < level % 8;j++)
1034
for (int j = 0;j < level;j++)
1039
static int CurrentColumn(const QString &txt)
1041
int pos = txt.findRev(("\n"));
1048
while (pos < int(txt.length()))
1050
char c = txt[pos].latin1();
1054
level = (level / toMarkedText::defaultTabWidth() + 1) * toMarkedText::defaultTabWidth();
1063
static QString IndentComment(int level, int current, const QString &comment, bool endNl)
1067
if (comment.length())
1069
if (level <= current && (level || current))
1074
for (unsigned int i = 0;i < comment.length();i++)
1076
if (!nl || !comment.at(i).isSpace())
1081
ret += toSQLParse::indentString(level);
1084
while (current < level)
1090
if (comment.at(i) == ("*"))
1097
ret += comment.at(i);
1098
if (comment.at(i) == '\n')
1117
static QString AddComment(const QString &old, const QString &comment)
1120
if (!ret.isEmpty() && !comment.isEmpty())
1126
QString toSQLParse::indentStatement(statement &stat, int level)
1128
return indentStatement(stat, level, toSyntaxAnalyzer::defaultAnalyzer());
1131
QString toSQLParse::indentStatement(statement &stat, toConnection &conn, int level)
1133
return indentStatement(stat, level, conn.analyzer());
1136
QString toSQLParse::indentStatement(statement &stat, int level, toSyntaxAnalyzer &syntax)
1143
throw qApp->translate("toSQLparse", "Internal error in toSQLParse, should never get here");
1144
case statement::Block:
1146
ret = IndentComment(level, 0, stat.Comment, false);
1148
for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin();
1149
i != stat.subTokens().end();
1154
std::list<toSQLParse::statement>::iterator j = i;
1156
if (i != stat.subTokens().begin() &&
1157
j != stat.subTokens().end())
1159
= Settings.IndentLevel;
1164
if ((*i).subTokens().begin() != (*i).subTokens().
1166
t = (*(*i).subTokens().begin()).String.upper();
1167
if (t == ("BEGIN") || t == ("WHEN") || t == ("ELSE") || t == ("ELSIF"))
1170
if ((*i).Type == statement::List)
1171
ret += indentString(level + add
1173
ret += indentStatement(*i, level + add
1175
if ((*i).Type == statement::List)
1178
for (i = ret.length() - 1;i >= 0 && ret[i].isSpace();i--)
1180
ret = ret.mid(0, std::max(i + 1, 0));
1182
ret += indentString(level + exc);
1184
if (t == ("EXCEPTION"))
1185
exc = Settings.IndentLevel * 2;
1187
if (Settings.EndBlockNewline && level != 0)
1191
case statement::List:
1192
case statement::Statement:
1195
bool useMaxLev = false;
1199
bool noKeyBreak = false;
1200
bool lineList = false;
1202
if (stat.Type == statement::Statement)
1204
ret = IndentComment(level, 0, stat.Comment, false);
1211
for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin();
1212
i != stat.subTokens().end();)
1214
if ((*i).Type != statement::Keyword)
1226
for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin();
1227
i != stat.subTokens().end();
1232
QString upp = (*i).String.upper();
1233
if ((*i).Type == statement::Keyword &&
1240
if (int((*i).String.length()) + 1 > maxlev)
1241
maxlev = (*i).String.length() + 1;
1245
else if (i == stat.subTokens().begin())
1251
else if ((*i).Type == statement::Token)
1253
if ((*i).Type == statement::List)
1256
if (count <= 1 && maxlev > 0)
1258
maxlevorig = maxlev;
1262
for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin();
1263
i != stat.subTokens().end();
1266
comment = AddComment(comment, (*i).Comment);
1267
QString upp = (*i).String.upper();
1268
#ifdef TOPARSE_DEBUG
1270
printf("%s\n", (const char*)(*i).String.latin1());
1273
if ((*i).Type == statement::List)
1275
if (Settings.OperatorSpace)
1280
QString t = indentStatement(*i, current, syntax);
1281
if (t.find(("\n")) >= 0)
1282
current = CurrentColumn(t);
1284
current += CurrentColumn(t);
1288
else if ((*i).String == (","))
1290
if (Settings.CommaBefore)
1292
ret += IndentComment(Settings.CommentColumn, current, comment, true);
1293
comment = QString::null;
1294
ret += indentString(level + maxlev - (Settings.OperatorSpace ? 2 : 1));
1300
ret += IndentComment(Settings.CommentColumn, current + 1, comment, true);
1301
comment = QString::null;
1302
ret += indentString(level + maxlev);
1304
current = level + maxlev;
1308
else if ((*i).Type == statement::Keyword && (upp == ("LOOP") ||
1314
if (!Settings.BlockOpenLine)
1316
if (ret.length() > 0)
1318
if (toIsIdent(ret.at(ret.length() - 1)) ||
1319
ret.at(ret.length() - 1) == syntax.quoteCharacter() ||
1320
ret.at(ret.length() - 1) == '\'' ||
1321
Settings.OperatorSpace)
1327
ret += Settings.KeywordUpper ? (*i).String.upper() : (*i).String;
1328
current += (*i).String.length();
1332
ret += IndentComment(Settings.CommentColumn, current, comment, true);
1333
comment = QString::null;
1334
ret += indentString(level);
1335
ret += Settings.KeywordUpper ? (*i).String.upper() : (*i).String;
1336
current = level + (*i).String.length();
1340
else if (any && (*i).Type == statement::Keyword && !noKeyBreak)
1346
ret += IndentComment(Settings.CommentColumn, current, comment, true);
1348
comment = QString::null;
1352
ret += indentString(level);
1356
while (current < level)
1361
maxlev = maxlevorig;
1362
QString word = Settings.KeywordUpper ? (*i).String.upper() : (*i).String;
1365
ret += QString("%1").arg(word,
1366
Settings.RightSeparator ? maxlev - 1 : 1 - maxlev);
1367
current = level + std::max(int(word.length()), maxlev - 1);
1372
current = level + word.length();
1379
QString t = (*i).String;
1382
if ((*i).Type == statement::Keyword)
1386
(*i).Type == statement::Keyword &&
1396
if (syntax.reservedWord(upp) && Settings.KeywordUpper)
1408
if (ret.length() > 0 &&
1409
!ret.at(ret.length() - 1).isSpace() &&
1410
(Settings.OperatorSpace || ((toIsIdent(t[0]) ||
1411
t[0] == syntax.quoteCharacter() || t[0] == '\'') &&
1412
(toIsIdent(ret.at(ret.length() - 1)) ||
1413
ret.at(ret.length() - 1) == syntax.quoteCharacter() ||
1414
ret.at(ret.length() - 1) == '\'')
1421
ret.at(ret.length() - 1) != '.' &&
1428
else if (ret.length() > 2 && ret.at(ret.length() - 2) == '*' && ret.at(ret.length() - 1) == '/')
1435
if (current < level + maxlev)
1438
ret += indentString(level + maxlev);
1440
while (current < level + maxlev)
1445
current = level + maxlev;
1448
current += t.length();
1449
if (t.startsWith(("<<")))
1457
maxlev += t.length() + 1;
1460
if (stat.Type == statement::Statement)
1462
ret += IndentComment(Settings.CommentColumn, current, comment, true);
1463
comment = QString::null;
1464
if (Settings.EndBlockNewline &&
1466
stat.subTokens().begin() != stat.subTokens().end() &&
1467
(*stat.subTokens().rbegin()).String == (";"))
1470
else if (!comment.isEmpty())
1472
ret += IndentComment(Settings.CommentColumn, current, comment, true);
1473
comment = QString::null;
1474
ret += indentString(level - (Settings.OperatorSpace ? 2 : 1));
1481
QString toSQLParse::indent(const QString &str)
1483
return indent(str, toSyntaxAnalyzer::defaultAnalyzer());
1486
QString toSQLParse::indent(const QString &str, toConnection &conn)
1488
return indent(str, conn.analyzer());
1491
QString toSQLParse::indent(std::list<statement> &stat)
1493
return indent(stat, toSyntaxAnalyzer::defaultAnalyzer());
1496
QString toSQLParse::indent(std::list<statement> &stat, toConnection &conn)
1498
return indent(stat, conn.analyzer());
1501
QString toSQLParse::indent(const QString &str, toSyntaxAnalyzer &syntax)
1503
stringTokenizer tokenizer(str, syntax);
1504
std::list<toSQLParse::statement> blk = parse(tokenizer);
1506
int level = countIndent(str, pos);
1509
for (std::list<toSQLParse::statement>::iterator i = blk.begin();
1513
ret += indentStatement(*i, level, syntax);
1516
while (pos > 0 && ret[pos - 1].isSpace())
1520
return ret.mid(0, pos) + ("\n");
1523
QString toSQLParse::indent(std::list<statement> &stat, toSyntaxAnalyzer &syntax)
1528
for (std::list<toSQLParse::statement>::iterator i = stat.begin();
1532
ret += indentStatement(*i, 0, syntax);
1535
while (pos > 0 && ret[pos - 1].isSpace())
1539
return ret.mid(0, pos) + ("\n");
1542
std::list<toSQLParse::statement> toSQLParse::parse(const QString &str, toConnection &conn)
1544
stringTokenizer tokenizer(str, conn.analyzer());
1545
return parse(tokenizer);
1548
toSQLParse::statement toSQLParse::parseStatement(toSQLParse::tokenizer &tokens, toConnection &conn)
1550
tokens.setAnalyzer(conn.analyzer());
1551
return parseStatement(tokens);
1554
toSyntaxAnalyzer &toSQLParse::tokenizer::analyzer()
1559
return toSyntaxAnalyzer::defaultAnalyzer();