static int bsd_global( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread; CHECK_LENGTH( 1); uint8_t opcode = buffer[0]; CHECK_DECODE( decodeInteger( ctx, x, buffer, length, &BS_GLOBAL_INTEGER)); CHECK_DECODE( decodeString( ctx, x, buffer, length, &BS_GLOBAL_STRING)); CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_GLOBAL_LIST)); CHECK_DECODE( decodeCollection( ctx, x, buffer, length, NULL, &BS_GLOBAL_MAP)); CHECK_DECODE( decodeClass( ctx, x, buffer, length)); if( 0x60 <= opcode && opcode <= 0x6f) { /* object (short form) */ CHECK_ERROR( bsd_object( ctx, x, opcode - 0x60)); return nread; } switch( opcode) { case BS_G_NULL: /* null */ decodeNull( ctx, x); break; case 0x01: /* boolean true */ x->kind = BSD_BOOL; x->content.boolean = 1; break; case 0x02: /* boolean false */ x->kind = BSD_BOOL; x->content.boolean = 0; break; case 0x70: /* object (long form) */ CHECK_SUBDECODE( bsd_uis( ctx, x, buffer + nread, length - nread), BSD_INT); CHECK_ERROR( bsd_object( ctx, x, x->content.i + 0x10)); break; case BS_G_FLOAT32: /* float */ CHECK_LENGTH( 5); x->kind = BSD_DOUBLE; float f; memcpy( &f, buffer + 1, sizeof(float)); ntoh( &f, sizeof(float), sendian.float_); x->content.d = f; break; case BS_G_FLOAT64: /* double */ CHECK_LENGTH( 9); x->kind = BSD_DOUBLE; memcpy( &(x->content.d), buffer + 1, sizeof(double)); ntoh( &(x->content.d), sizeof(double), sendian.double_); break; default: return bsd_error( x, BSD_EINVALID); } return nread; }
int main(int argc, char **argv) { //TODO: rewrite this with one list and structure :) // each test set contains: QStringList testSet; // statement (or a set of statements) to be parsed QList<int> testCount; // count of statements (to be checked against parser result) QList<int> testClass; // statement class //=================================================== // Test #1 Simplest DML statement ever testSet.append("select sysdate from dual;"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #2 Double simplest DML statement testSet.append("select sysdate from dual;" "select sysdate from dual;"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #3 Simple DDL statement testSet.append("create table test ( col varchar(12) );"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #4 Simple DML statement with new line in text testSet.append("insert into prova3 (prova)\n" "values ('This insert contains a ''\n" "and now it goes to new line');"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #5 Procedure with exceptions and conditional statements testSet.append("create or replace PROCEDURE prova1\n" "is\n" "v_tmp NUMBER(1);\n" "begin\n" "begin\n" "select 0 into v_tmp from dual;\n" "exception\n" "when 1 = 1 then\n" " v_tmp := 'Dadum';\n" "when others then\n" "if sqlcode=0 then\n" "null;\n" "else\n" "null;\n" "end if;\n" "end;\n" "\n" "if v_tmp=0 then\n" "null;\n" "end if;\n" "end;"); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #6 Comment testSet.append("comment on column prova1.prova1 is 'This comment is\n" "on more than one line';\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #7 Package specification testSet.append("\n" "PACKAGE oasSIMActivation AS\n" " FUNCTION ParseCommand(Command VARCHAR2,inICC VARCHAR2,Param VARCHAR2) RETURN VARCHAR2;\n" "\n" " PROCEDURE InsertActions(inCommandType VARCHAR2,\n" " Sim oasSIM%ROWTYPE,\n" " inParam VARCHAR2);\n" "\n" " PROCEDURE InsertActions(CommandType VARCHAR2,\n" " inICC VARCHAR2,\n" " inParam VARCHAR2);\n" "\n" " PROCEDURE InsertActions(inCommandType VARCHAR2,\n" " Service oasService%ROWTYPE);\n" "\n" " PROCEDURE InsertActions(CommandType VARCHAR2,\n" " inCustomerID NUMBER,\n" " inSubID NUMBER,\n" " inServiceType VARCHAR2,\n" " Param VARCHAR2);\n" "END;\n" ); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #8 Anonymous block with case statement testSet.append("\n" "DECLARE\n" "grade CHAR(1);\n" "appraisal VARCHAR2(20);\n" "BEGIN\n" "CASE grade\n" "WHEN 'A' THEN appraisal := 'Excellent';\n" "WHEN 'B' THEN appraisal := 'Very Good';\n" "WHEN 'C' THEN appraisal := 'Good';\n" "WHEN 'D' THEN appraisal := 'Fair';\n" "WHEN 'F' THEN appraisal := 'Poor';\n" "ELSE appraisal := 'No such grade';\n" "END CASE;\n" "IF appraisal IS NULL THEN\n" "NULL;\n" "END IF;\n" "END;\n" ); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #9 Procedure with conditional statement testSet.append("\n" "CREATE OR REPLACE PROCEDURE A(p IN INTEGER) AS\n" "BEGIN\n" "IF a = 1 THEN NULL;\n" "ELSIF a = 2 THEN NULL;\n" "ELSE NULL;\n" "END IF;\n" "END;\n" ); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #10 Procedure with case statement // Note! Should generate only ONE statement (block) testSet.append("\n" "CREATE OR REPLACE PROCEDURE A AS\n" "BEGIN\n" "CASE a\n" "WHEN 1 THEN NULL;\n" "WHEN 2 THEN NULL;\n" "ELSE NULL;\n" "END CASE;\n" "END;\n" ); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #11 Anonynous block without declaration with query (incorrect syntax but should parse anyway:) testSet.append("BEGIN\n" "IF 1 == 1 THEN\n" "NULL;\n" "END IF;\n" "IF appraisal IS NULL THEN\n" "NULL;\n" "ELSE\n" "SELECT CASE WHEN dummy='X' THEN 'A' ELSE 'B' END, 2 FROM dual;\n" "END IF;\n" "END;\n"); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #12 testSet.append("select count(case when dummy = 'Y' then dummy\n" " else null end) as tot_str\n" "from dual;\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #13 testSet.append("SET TRANSACTION READ ONLY\n" "\n" "PROMPT Hello\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #14 testSet.append("/* Test comment\n" "*/\n" "INSERT INTO cdrProcess(ProcessID,\n" " StartDate,\n" " EnvDate,\n" " ProgramID,\n" " OSUser,\n" " SystemUser,\n" " ExecName,\n" " ExecVersion,\n" " ExecParameters,\n" " HostName)\n" "VALUES (:1,\n" " SYSDATE,\n" " SYSDATE,\n" " :2,\n" " :3,\n" " :4,\n" " :5,\n" " :6,\n" " :7,\n" " :8);\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #15 testSet.append("CREATE or REPLACE Procedure TEST_SPR\n" "(\n" " IN_TICKET_NUM IN VARCHAR2\n" ")\n" "IS\n" "\n" "BEGIN\n" "\n" "BEGIN\n" "\n" "for cur_rec in (select emp_id from employees) loop\n" "\n" " update employees set emp_id = emp_id + 1\n" " where emp_id = cur_rec.emp_id;\n" " commit;\n" "end loop;\n" " \n" "END;\n" "END TEST_SPR;\n"); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #16 testSet.append("SELECT owner,\n" " OBJECT,\n" " TYPE FROM v$access\n" " WHERE sid=:f1<char[101]>\n" " ORDER BY owner,\n" " OBJECT,\n" " TYPE;\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #17 testSet.append("CREATE TABLE ess.EssCalLog (\n" " CalID CHAR(5) NOT NULL, -- Calender type\n" " SeqID NUMBER(8) NOT NULL,\n" " ActStt CHAR(1) NOT NULL\n" " CONSTRAINT EssCalLog_CK_ActStt CHECK (ActStt IN ('A','D') ),\n" " LogRun CHAR(1) NOT NULL -- Should runs of this type be logged\n" " CONSTRAINT EssCalLog_CK_LogRun CHECK (LogRun IN ('Y','N') ),\n" " PrcID NUMBER(8) NOT NULL\n" " CONSTRAINT EssCalDay_FK_PrcID REFERENCES ess.EssPrc(PrcID),\n" " Dsc VARCHAR2(4000) NOT NULL, -- Description of this type\n" " CONSTRAINT EssCal_PK PRIMARY KEY (CalID,SeqID)\n" " USING INDEX TABLESPACE Index02 -- A Comment\n" ");\n" "-- Another comment\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #18 testSet.append("CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER,\n" " oNumSwt OUT NUMBER)\n" "IS\n" " vYear CHAR(4);\n" "BEGIN\n" " <<label>>\n" " DECLARE\n" " oTrdStt NUMBER;\n" " BEGIN\n" " oTrdStt := 0;\n" " END;\n" "\n" " EXCEPTION\n" " WHEN VALUE_ERROR THEN\n" " oRet := 3;\n" " WHEN NO_DATA_FOUND THEN\n" " oRet := 2;\n" " WHEN OTHERS THEN\n" " oRet := 1;\n" "END;\n" "CREATE OR REPLACE procedure spTuxGetAccData as\n" " vYear CHAR(4);\n" "begin\n" " null;\n" "end;\n"); testCount.append(2); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #19 testSet.append("-------------------------------------------------------------------\n" "-- EssCal, Current calendar view\n" "\n" "CREATE VIEW ess.EssCal AS\n" " SELECT CalID,\n" " LogRun,\n" " PrcID,\n" " Dsc\n" " FROM ess.EssCalLog a\n" " WHERE SeqID = (SELECT MAX(aa.SeqID) FROM EssCalLog aa WHERE aa.CalID = a.CalID)\n" " AND ActStt = 'A';\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #20 testSet.append(" /* A little comment\n" " */\n" " SELECT /*+\n" "FULL(a)\n" "*/ a.TskCod TskCod -- Test comment\n" " ,a.CreEdt CreEdt,\n" " a.TspActOprID /* One comment OprID */ , -- Another comment\n" " COUNT(1) Tot,\n" " COUNT(a.TspActOprID) Lft,\n" " b.TraCod TraCod,\n" " SUM(b.FinAmt) FinAmt,\n" " TraCod\n" " FROM EssTsk a,EssTra b\n" " WHERE ((a.TspActOprID = 'Test') OR a.TspActOprID IS NULL)\n" " AND DECODE(a.TspActOprID,NULL,NULL,a.TskID) = b.TskID(+)\n" " GROUP BY a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n" "HAVING COUNT(a.TspActOprID) > 0;\n" "SELECT a.Sid \"-Id\",\n" " a.Serial# \"-Serial#\",\n" " a.SchemaName \"Schema\",\n" " a.Status \"Status\",\n" " a.Server \"Server\",\n" " a.OsUser \"Osuser\",\n" " a.Machine \"Machine\",\n" " a.Program \"Program\",\n" " a.Type \"Type\",\n" " a.Module \"Module\",\n" " a.Action \"Action\",\n" " a.Client_Info \"Client Info\",\n" " b.Block_Gets \"-Block Gets\",\n" " b.Consistent_Gets \"-Consistent Gets\",\n" " b.Physical_Reads \"-Physical Reads\",\n" " b.Block_Changes \"-Block Changes\",\n" " b.Consistent_Changes \"-Consistent Changes\",\n" " c.Value*10 \"-CPU (ms)\",\n" " a.Process \"-Process\",\n" " a.SQL_Address||':'||SQL_Hash_Value \" SQL Address\",\n" " a.Prev_SQL_Addr||':'||Prev_Hash_Value \" Prev SQl Address\"\n" " FROM v$session a,\n" " v$sess_io b,\n" " v$sesstat c\n" " WHERE a.sid = b.sid(+)\n" " AND a.sid = c.sid(+) AND (c.statistic# = 12 OR c.statistic# IS NULL)\n" " ORDER BY a.Sid;\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #21 testSet.append("select a.TskCod TskCod,\n" " count(1) Tot\n" " from (select * from EssTsk where PrsID >= '1940') ,EssTra b\n" " where decode(a.TspActOprID,NULL,NULL,a.PrsID)+5 = b.PrsID(+)\n" " group by a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n" "having count(a.TspActOprID) > 0;\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #22 testSet.append("CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER)\n" "AS\n" " vYear CHAR(4);\n" "BEGIN\n" " DECLARE\n" " oTrdStt NUMBER;\n" " BEGIN\n" " oTrdStt := 0;\n" " END;\n" " EXCEPTION\n" " WHEN VALUE_ERROR THEN\n" " oRet := 3;\n" "END;"); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #23 BIG TEST! Run all statemens at once. Should separate statements correctly. testSet.append("create table test ( col varchar(12) );\n" "insert into prova3 (prova)\n" "values ('This insert contains a ''\n" "and now it goes to new line');\n" "create or replace PROCEDURE prova1\n" "is\n" "v_tmp NUMBER(1);\n" "begin\n" "begin\n" "select 0 into v_tmp from dual;\n" "exception\n" "when 1 = 1 then\n" " v_tmp := 'Dadum';\n" "when others then\n" "if sqlcode=0 then\n" "null;\n" "else\n" "null;\n" "end if;\n" "end;\n" "\n" "if v_tmp=0 then\n" "null;\n" "end if;\n" "end;" "comment on column prova1.prova1 is 'This comment is\n" "on more than one line';\n" "PACKAGE oasSIMActivation AS\n" " FUNCTION ParseCommand(Command VARCHAR2,inICC VARCHAR2,Param VARCHAR2) RETURN VARCHAR2;\n" "\n" " PROCEDURE InsertActions(inCommandType VARCHAR2,\n" " Sim oasSIM%ROWTYPE,\n" " inParam VARCHAR2);\n" "\n" " PROCEDURE InsertActions(CommandType VARCHAR2,\n" " inICC VARCHAR2,\n" " inParam VARCHAR2);\n" "\n" " PROCEDURE InsertActions(inCommandType VARCHAR2,\n" " Service oasService%ROWTYPE);\n" "\n" " PROCEDURE InsertActions(CommandType VARCHAR2,\n" " inCustomerID NUMBER,\n" " inSubID NUMBER,\n" " inServiceType VARCHAR2,\n" " Param VARCHAR2);\n" "END;\n" "DECLARE\n" "grade CHAR(1);\n" "appraisal VARCHAR2(20);\n" "BEGIN\n" "CASE grade\n" "WHEN 'A' THEN appraisal := 'Excellent';\n" "WHEN 'B' THEN appraisal := 'Very Good';\n" "WHEN 'C' THEN appraisal := 'Good';\n" "WHEN 'D' THEN appraisal := 'Fair';\n" "WHEN 'F' THEN appraisal := 'Poor';\n" "ELSE appraisal := 'No such grade';\n" "END;\n" "IF appraisal IS NULL THEN\n" "NULL;\n" "END IF;\n" "END;\n" "\n" "BEGIN\n" "IF 1 == 1 THEN\n" "NULL;\n" "END IF;\n" "IF appraisal IS NULL THEN\n" "NULL;\n" "ELSE\n" "SELECT CASE WHEN dummy='X' THEN 'A' ELSE 'B' END, 2 FROM dual;\n" "END IF;\n" "END;\n" "\n" "select count(case when dummy = 'Y' then dummy\n" " else null end) as tot_str\n" "from dual;\n" "\n" "SET TRANSACTION READ ONLY\n" "\n" "PROMPT Hello\n" "\n" "/* Test comment\n" "*/\n" "INSERT INTO cdrProcess(ProcessID,\n" " StartDate,\n" " EnvDate,\n" " ProgramID,\n" " OSUser,\n" " SystemUser,\n" " ExecName,\n" " ExecVersion,\n" " ExecParameters,\n" " HostName)\n" "VALUES (:1,\n" " SYSDATE,\n" " SYSDATE,\n" " :2,\n" " :3,\n" " :4,\n" " :5,\n" " :6,\n" " :7,\n" " :8);\n" "\n" "CREATE or REPLACE Procedure TEST_SPR\n" "(\n" " IN_TICKET_NUM IN VARCHAR2\n" ")\n" "IS\n" "\n" "BEGIN\n" "\n" "BEGIN\n" "\n" "for cur_rec in (select emp_id from employees) loop\n" "\n" " update employees set emp_id = emp_id + 1\n" " where emp_id = cur_rec.emp_id;\n" " commit;\n" "end loop;\n" " \n" "END;\n" "END TEST_SPR;\n" "\n" "SELECT owner,\n" " OBJECT,\n" " TYPE FROM v$access\n" " WHERE sid=:f1<char[101]>\n" " ORDER BY owner,\n" " OBJECT,\n" " TYPE;\n" "\n" "CREATE TABLE ess.EssCalLog (\n" " CalID CHAR(5) NOT NULL, -- Calender type\n" " SeqID NUMBER(8) NOT NULL,\n" " ActStt CHAR(1) NOT NULL\n" " CONSTRAINT EssCalLog_CK_ActStt CHECK (ActStt IN ('A','D') ),\n" " LogRun CHAR(1) NOT NULL -- Should runs of this type be logged\n" " CONSTRAINT EssCalLog_CK_LogRun CHECK (LogRun IN ('Y','N') ),\n" " PrcID NUMBER(8) NOT NULL\n" " CONSTRAINT EssCalDay_FK_PrcID REFERENCES ess.EssPrc(PrcID),\n" " Dsc VARCHAR2(4000) NOT NULL, -- Description of this type\n" " CONSTRAINT EssCal_PK PRIMARY KEY (CalID,SeqID)\n" " USING INDEX TABLESPACE Index02 -- A Comment\n" ");\n" "-- Another comment\n" "\n" "CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER,\n" " oNumSwt OUT NUMBER)\n" "IS\n" " vYear CHAR(4);\n" "BEGIN\n" " <<label>>\n" " DECLARE\n" " oTrdStt NUMBER;\n" " BEGIN\n" " oTrdStt := 0;\n" " END;\n" "\n" " EXCEPTION\n" " WHEN VALUE_ERROR THEN\n" " oRet := 3;\n" " WHEN NO_DATA_FOUND THEN\n" " oRet := 2;\n" " WHEN OTHERS THEN\n" " oRet := 1;\n" "END;\n" "CREATE OR REPLACE procedure spTuxGetAccData as\n" " vYear CHAR(4);\n" "begin\n" " null;\n" "end;\n" "-------------------------------------------------------------------\n" "-- EssCal, Current calendar view\n" "\n" "CREATE VIEW ess.EssCal AS\n" " SELECT CalID,\n" " LogRun,\n" " PrcID,\n" " Dsc\n" " FROM ess.EssCalLog a\n" " WHERE SeqID = (SELECT MAX(aa.SeqID) FROM EssCalLog aa WHERE aa.CalID = a.CalID)\n" " AND ActStt = 'A';\n" "\n" " /* A little comment\n" " */\n" " SELECT /*+\n" "FULL(a)\n" "*/ a.TskCod TskCod -- Test comment\n" " ,a.CreEdt CreEdt,\n" " a.TspActOprID /* One comment OprID */ , -- Another comment\n" " COUNT(1) Tot,\n" " COUNT(a.TspActOprID) Lft,\n" " b.TraCod TraCod,\n" " SUM(b.FinAmt) FinAmt,\n" " TraCod\n" " FROM EssTsk a,EssTra b\n" " WHERE ((a.TspActOprID = 'Test') OR a.TspActOprID IS NULL)\n" " AND DECODE(a.TspActOprID,NULL,NULL,a.TskID) = b.TskID(+)\n" " GROUP BY a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n" "HAVING COUNT(a.TspActOprID) > 0;\n" "SELECT a.Sid \"-Id\",\n" " a.Serial# \"-Serial#\",\n" " a.SchemaName \"Schema\",\n" " a.Status \"Status\",\n" " a.Server \"Server\",\n" " a.OsUser \"Osuser\",\n" " a.Machine \"Machine\",\n" " a.Program \"Program\",\n" " a.Type \"Type\",\n" " a.Module \"Module\",\n" " a.Action \"Action\",\n" " a.Client_Info \"Client Info\",\n" " b.Block_Gets \"-Block Gets\",\n" " b.Consistent_Gets \"-Consistent Gets\",\n" " b.Physical_Reads \"-Physical Reads\",\n" " b.Block_Changes \"-Block Changes\",\n" " b.Consistent_Changes \"-Consistent Changes\",\n" " c.Value*10 \"-CPU (ms)\",\n" " a.Process \"-Process\",\n" " a.SQL_Address||':'||SQL_Hash_Value \" SQL Address\",\n" " a.Prev_SQL_Addr||':'||Prev_Hash_Value \" Prev SQl Address\"\n" " FROM v$session a,\n" " v$sess_io b,\n" " v$sesstat c\n" " WHERE a.sid = b.sid(+)\n" " AND a.sid = c.sid(+) AND (c.statistic# = 12 OR c.statistic# IS NULL)\n" " ORDER BY a.Sid;\n" "select a.TskCod TskCod,\n" " count(1) Tot\n" " from (select * from EssTsk where PrsID >= '1940') ,EssTra b\n" " where decode(a.TspActOprID,NULL,NULL,a.PrsID)+5 = b.PrsID(+)\n" " group by a.TskCod,a.CreEdt,a.TspActOprID,b.TraCod\n" "having count(a.TspActOprID) > 0;\n" "\n" "CREATE OR REPLACE procedure spTuxGetAccData (oRet OUT NUMBER)\n" "AS\n" " vYear CHAR(4);\n" "BEGIN\n" " DECLARE\n" " oTrdStt NUMBER;\n" " BEGIN\n" " oTrdStt := 0;\n" " END;\n" " EXCEPTION\n" " WHEN VALUE_ERROR THEN\n" " oRet := 3;\n" "END;"); testCount.append(21); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::ddldml); // comment testClass.append(toSQLParse::statement::plsqlblock); // package spec testClass.append(toSQLParse::statement::plsqlblock); // anonymous block testClass.append(toSQLParse::statement::plsqlblock); // anonymous block (without declare) testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); // create table ess.EssCalLog... testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #24 Insert statements ending with "/" rather than ";" testSet.append("insert into a values ('aaa', 222)\n" "/\n" "insert into a values ('bbb', 333)\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #25 Two procedures separated with "/" testSet.append("create procedure a1 as\n" "begin null; end;\n" "/\n" "create procedure a2 as\n" "begin null; end;\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #26 Statement with slash in it testSet.append("select 2/1 from dual;"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #27 Update statements containing "/"'s ending with "/" rather than ";" testSet.append("update a set b=2/1 where c='qqq'\n" "/\n" "update a set b=3/2, c=2/1 where q='qq/qq'\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #28 Merge statement // Note: Semicolon after first merge is only required for reparse test // Initial parse test should be ok without it. Reparse has problems // with it because parser separates statements and removes any "/" // signs which makes these two merge statements as one on second parse. testSet.append("MERGE INTO a\n" "USING (\n" " SELECT 1 id from dual) b on (a.id = b.id)\n" "WHEN MATCHED THEN\n" " UPDATE SET a.c = a.c +1\n" " DELETE WHERE (a.c > 2)\n" "WHEN NOT MATCHED THEN\n" " INSERT (a.id, a.c)\n" " VALUES (b.id, 0)\n" "/" "MERGE INTO a\n" "USING (\n" " SELECT 1 id from dual) b on (a.id = b.id)\n" "WHEN MATCHED THEN\n" " UPDATE SET a.c = a.c +1\n" " DELETE WHERE (a.c > 2)\n" "WHEN NOT MATCHED THEN\n" " INSERT (a.id, a.c)\n" " VALUES (b.id, 0)\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #29 Query statement with "with" structure testSet.append("WITH p AS (SELECT 1/2 as half_a FROM dual),\n" "q AS(SELECT 1/2 half_b FROM dual)\n" "SELECT half_a/half_b FROM p, q;\n" "/\n" "select sysdate from dual\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #30 Placeholder for plsql goto statement testSet.append("create procedure a1 as\n" "begin <<placeholder>> end;\n" "/\n" "create procedure a2 as\n" "begin <<placeholder>> end;\n" "/\n"); testCount.append(2); testClass.append(toSQLParse::statement::plsqlblock); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #31 Statement after an end with "/" and no ";" testSet.append("create view a as select a from a\n" "/\n" "select sysdate from dual\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #32 Statement after an end with "/" and no ";" testSet.append("create table tfr_scenarios\n" " (a number)\n" "/\n" "alter table tfr_scenarios add scn_type date;\n"); testCount.append(2); testClass.append(toSQLParse::statement::ddldml); testClass.append(toSQLParse::statement::ddldml); //=================================================== // Test #33 Create type body statement testSet.append("create or replace type body egz_task_ot is\n" "constructor function egz_task_ot return self as result is\n" "begin return; end;\n" "end;\n" "/\n"); testCount.append(1); testClass.append(toSQLParse::statement::plsqlblock); //=================================================== // Test #34 Create type statement testSet.append("create or replace type egz_task_ot as object\n" "(aaa number(11),\n" " bbb varchar2(2000),\n" "constructor function egz_task_ot return self as result\n" ")\n"); testCount.append(1); testClass.append(toSQLParse::statement::ddldml); QApplication test(argc, argv); toScintilla text(NULL); int n = 1; int e = 0; // error count QString errors; QList<int>::iterator cnt = testCount.begin(); QList<int>::iterator cls = testClass.begin(); for (QStringList::iterator i = testSet.begin(); i != testSet.end(); i++) { printf("Start test %i ", n); // The code below skips all other tests except one particular /*if (n != 34) { n++; for (int j = 1; j <= *cnt; j++) cls++; cnt++; continue; }*/ text.setText(*i); //printf("Initialising editorTokenizer\n"); toSQLParse::editorTokenizer tokens(&text); /* This code will display tokens QString tt = tokens.getToken(); while (!tt.isNull()) { qDebug() << "getToken = " << tt; tt = tokens.getToken(); }*/ //printf("Parsing statement\n"); std::list<toSQLParse::statement> stat = toSQLParse::parse(tokens); //printf("===== List of parsed statements =====\n"); int statementCount = 0; for (std::list<toSQLParse::statement>::iterator i = stat.begin(); i != stat.end(); i++) { //printf("----- Parsed statement ----- (parse test main())\n"); //printSt(*i, 0); //printf("----- End of parsed statement -----\n"); // check if statement class was identified correctly if (i->StatementClass != *cls) { e++; errors = errors + "Incorrect statement class on test #" + QString::number(n) + ". Expected " + decodeClass(*cls) + " got " + decodeClass(i->StatementClass) + "\n"; printf("[Error]"); } else { printf("[OK]"); } statementCount++; cls++; } //printf("===== End of list of parsed statements =====\n"); //printf("Number of statements: %i, should have been %i\n", statementCount, *cnt); // check if correct number of statements was identified if (statementCount != *cnt) { e++; errors = errors + "Incorrect number of parsed statements on test #" + QString::number(n) + ". Expected " + QString::number(*cnt) + " got " + QString::number(statementCount) + "\n"; printf("[Error]"); } else { printf("[OK]"); } //QString firstparse = toSQLParse::indent(stat); //qDebug() << "parsed=" << QString("\n") + firstparse; QString firstparse = toSQLParse::indent(stat); // Note that secondparse will go directly to stringTokenizer::getToken // bypassing editorTokenizer QString secondparse = toSQLParse::indent(firstparse); //printf("First\n\n%s\n", (const char *)firstparse.toUtf8()); if (firstparse != secondparse) { //printf("Reparse doesn't match\n"); //printf("Second\n\n%s\n", (const char *)secondparse.toUtf8()); e++; errors = errors + "Reparse doesn't match for test #" + QString::number(n) + "\n"; printf("[ERROR]\n"); } else { printf("[OK]\n"); } n++; cnt++; } if (e == 0) { printf("Done. No errors!!!\n"); } else { printf("Done. Number of errors: %i\n", e); qDebug() << errors; } return 0; }