From f41c0c9ff974b919f24170cc1c39fefffcf5b58f Mon Sep 17 00:00:00 2001 From: ibre5041 Date: Sun, 8 Apr 2012 21:16:34 +0200 Subject: [PATCH 01/43] use memoize for performance improvement - testcase for Gokul --- parsers/PLSQL_DMLParser.g | 8 ++++++-- parsers/no-ast/PLSQL_DMLParser.g | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index e20c6e9..d867bee 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -186,14 +186,16 @@ compilation_unit //SHOULD BE OVERRIDEN! seq_of_statements - : select_statement + : + ( select_statement | update_statement | delete_statement | insert_statement | lock_table_statement | merge_statement | explain_statement -// | case_statement[true] + ) + ( SEMICOLON | EOF ) ; explain_statement @@ -1023,6 +1025,7 @@ unary_expression options { backtrack=true; +memoize=true; } : MINUS_SIGN unary_expression -> ^(UNARY_OPERATOR[$MINUS_SIGN] unary_expression) | PLUS_SIGN unary_expression -> ^(UNARY_OPERATOR[$PLUS_SIGN] unary_expression) @@ -1081,6 +1084,7 @@ atom options { backtrack=true; +memoize=true; } : (table_element outer_join_sign) => table_element outer_join_sign | bind_variable diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index 1d87a13..1724c44 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -101,14 +101,16 @@ compilation_unit //SHOULD BE OVERRIDEN! seq_of_statements - : select_statement + : + ( select_statement | update_statement | delete_statement | insert_statement | lock_table_statement | merge_statement | explain_statement -// | case_statement[true] + ) + ( SEMICOLON | EOF ) ; explain_statement @@ -827,6 +829,7 @@ unary_expression options { backtrack=true; +memoize=true; } : MINUS_SIGN unary_expression | PLUS_SIGN unary_expression @@ -883,6 +886,7 @@ atom options { backtrack=true; +memoize=true; } : (table_element outer_join_sign) => table_element outer_join_sign | bind_variable From 19733f0def668fb9185dc56a4cf400df332754d5 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 18 May 2012 16:57:24 +0200 Subject: [PATCH 02/43] memoize option removed - requires global menoize option to be enabled --- parsers/PLSQL_DMLParser.g | 2 -- parsers/no-ast/PLSQL_DMLParser.g | 2 -- 2 files changed, 4 deletions(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index d867bee..9edd7a6 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -1025,7 +1025,6 @@ unary_expression options { backtrack=true; -memoize=true; } : MINUS_SIGN unary_expression -> ^(UNARY_OPERATOR[$MINUS_SIGN] unary_expression) | PLUS_SIGN unary_expression -> ^(UNARY_OPERATOR[$PLUS_SIGN] unary_expression) @@ -1084,7 +1083,6 @@ atom options { backtrack=true; -memoize=true; } : (table_element outer_join_sign) => table_element outer_join_sign | bind_variable diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index 1724c44..b7b254e 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -829,7 +829,6 @@ unary_expression options { backtrack=true; -memoize=true; } : MINUS_SIGN unary_expression | PLUS_SIGN unary_expression @@ -886,7 +885,6 @@ atom options { backtrack=true; -memoize=true; } : (table_element outer_join_sign) => table_element outer_join_sign | bind_variable From 71745c7576a2d252d4f11a6b2f00ce4b64c863d0 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 18 May 2012 17:27:26 +0200 Subject: [PATCH 03/43] new test condition of type: current of c_ref --- parsers/TestPLSQL_DML.testsuite | 1 + tests/condition17.sql | 2 ++ tests/condition18.sql | 4 ++++ 3 files changed, 7 insertions(+) create mode 100644 tests/condition17.sql create mode 100644 tests/condition18.sql diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index 187d661..6d20573 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -598,6 +598,7 @@ update_statement: set salary = 1.1 where department_id = 100 returning salary into :bnd1>> OK +condition18.sql OK merge_statement: merge01.sql OK diff --git a/tests/condition17.sql b/tests/condition17.sql new file mode 100644 index 0000000..6d8b269 --- /dev/null +++ b/tests/condition17.sql @@ -0,0 +1,2 @@ +delete from table_name +where current of cursor_name diff --git a/tests/condition18.sql b/tests/condition18.sql new file mode 100644 index 0000000..e66f6fb --- /dev/null +++ b/tests/condition18.sql @@ -0,0 +1,4 @@ +update tab1 +set c1 = 'x' +where current of c_cur1 + From e0afe5ebf1da2045bb2a5749b8c19ba85dbc2232 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 18 May 2012 17:56:43 +0200 Subject: [PATCH 04/43] more tests, one of them fails --- parsers/TestPLSQL_DML.testsuite | 3 +++ tests/cast_multiset09.sql | 2 ++ tests/cast_multiset10.sql | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 tests/cast_multiset09.sql create mode 100644 tests/cast_multiset10.sql diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index 6d20573..ba3a0bf 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -104,6 +104,8 @@ cast_multiset05.sql OK cast_multiset06.sql OK cast_multiset07.sql OK cast_multiset08.sql OK +//!! FAILs ATM cast_multiset09.sql OK +cast_multiset10.sql OK case_when01.sql OK case_when02.sql OK case_when03.sql OK @@ -563,6 +565,7 @@ delete_statement: where job_id = 'sa_rep' and hire_date < 10 returning salary into :bnd1>> OK +condition17.sql OK update_statement: < Date: Tue, 26 Jun 2012 00:08:52 +0200 Subject: [PATCH 05/43] strange query example --- tests/comment02.sql | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/comment02.sql diff --git a/tests/comment02.sql b/tests/comment02.sql new file mode 100644 index 0000000..3051de2 --- /dev/null +++ b/tests/comment02.sql @@ -0,0 +1,35 @@ +WITH REFS +AS +( + SELECT DISTINCT + c.constraint_name + -- max(a.constraint_name) as constraint_name + -- , c.constraint_name + -- , max(r.constraint_name) as r_constraint_name + , c.owner as owner + , c.table_name as table_name + -- , c.column_name as column_name + -- , ' => ' as "ARW" + , r.owner as r_owner + , r.table_name as r_table_name + -- , max(r.column_name) as r_column_name + -- , max(a.constraint_type) + FROM + sys.all_constraints a + JOIN sys.all_cons_columns c ON (c.constraint_name = a.constraint_name AND c.owner = a.owner) + JOIN sys.all_cons_columns r ON (r.constraint_name = a.r_constraint_name AND r.owner = a.r_owner AND r.position = c.position) + WHERE + a.Owner = 'SCHEMA_TEST' -- :f1 +-- AND a.Table_Name = 'T_MN_1' -- :f2 + AND a.constraint_type = 'R' +) +SELECT -- REFS.* + REFS.table_name + , REFS.r_table_name + , CONNECT_BY_ISCYCLE CYCLE + , LEVEL -- level this is strange case, this is not a comment but a column alias + -- , SYS_CONNECT_BY_PATH(table_name, '/') "Path" +FROM REFS +CONNECT BY NOCYCLE PRIOR r_owner = owner AND PRIOR r_table_name = table_name +/ + From ae1b1618fedd66cdc43fd4c925463839cc789d09 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Wed, 27 Jun 2012 11:22:01 +0200 Subject: [PATCH 06/43] datawarehousing group by --- tests/groupby08.sql | 20 ++++++++++++++++++++ tests/groupby09.sql | 10 ++++++++++ tests/groupby10.sql | 8 ++++++++ tests/groupby11.sql | 9 +++++++++ tests/groupby12.sql | 8 ++++++++ tests/groupby13.sql | 8 ++++++++ tests/groupby14.sql | 8 ++++++++ tests/groupby15.sql | 8 ++++++++ tests/groupby16.sql | 7 +++++++ tests/groupby17.sql | 7 +++++++ tests/groupby18.sql | 9 +++++++++ tests/groupby19.sql | 9 +++++++++ tests/groupby20.sql | 13 +++++++++++++ tests/groupby21.sql | 10 ++++++++++ tests/groupby22.sql | 12 ++++++++++++ tests/groupby23.sql | 15 +++++++++++++++ 16 files changed, 161 insertions(+) create mode 100644 tests/groupby08.sql create mode 100644 tests/groupby09.sql create mode 100644 tests/groupby10.sql create mode 100644 tests/groupby11.sql create mode 100644 tests/groupby12.sql create mode 100644 tests/groupby13.sql create mode 100644 tests/groupby14.sql create mode 100644 tests/groupby15.sql create mode 100644 tests/groupby16.sql create mode 100644 tests/groupby17.sql create mode 100644 tests/groupby18.sql create mode 100644 tests/groupby19.sql create mode 100644 tests/groupby20.sql create mode 100644 tests/groupby21.sql create mode 100644 tests/groupby22.sql create mode 100644 tests/groupby23.sql diff --git a/tests/groupby08.sql b/tests/groupby08.sql new file mode 100644 index 0000000..274e3ca --- /dev/null +++ b/tests/groupby08.sql @@ -0,0 +1,20 @@ +select + c.constraint_name + -- max(a.constraint_name) as constraint_name + -- , c.constraint_name + , max(r.constraint_name) as r_constraint_name + , max(c.owner) as owner + , max(c.table_name) as table_name + , c.column_name as column_name + , max(r.owner) as r_owner + , max(r.table_name) as r_table_name + , max(r.column_name) as r_column_name + , max(a.constraint_type) + from sys.all_constraints a + join sys.all_cons_columns c on (c.constraint_name = a.constraint_name and c.owner = a.owner) + join sys.all_cons_columns r on (r.constraint_name = a.r_constraint_name and r.owner = a.r_owner and r.position = c.position) + where + a.r_owner = :f1 + and a.constraint_type = 'r' + group by c.constraint_name, rollup (c.column_name) + \ No newline at end of file diff --git a/tests/groupby09.sql b/tests/groupby09.sql new file mode 100644 index 0000000..ad28d77 --- /dev/null +++ b/tests/groupby09.sql @@ -0,0 +1,10 @@ +select fact_1_id, + fact_2_id, + sum(sales_value) as sales_value, + grouping(fact_1_id) as f1g, + grouping(fact_2_id) as f2g +from dimension_tab +group by cube (fact_1_id, fact_2_id) +having grouping(fact_1_id) = 1 or grouping(fact_2_id) = 1 +order by grouping(fact_1_id), grouping(fact_2_id) +l \ No newline at end of file diff --git a/tests/groupby10.sql b/tests/groupby10.sql new file mode 100644 index 0000000..8de57ab --- /dev/null +++ b/tests/groupby10.sql @@ -0,0 +1,8 @@ +select fact_1_id, + fact_2_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id) as grouping_id, + group_id() as group_id +from dimension_tab +group by grouping sets(fact_1_id, cube (fact_1_id, fact_2_id)) +order by fact_1_id, fact_2_id diff --git a/tests/groupby11.sql b/tests/groupby11.sql new file mode 100644 index 0000000..d664366 --- /dev/null +++ b/tests/groupby11.sql @@ -0,0 +1,9 @@ +select fact_1_id, + fact_2_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id) as grouping_id, + group_id() as group_id +from dimension_tab +group by grouping sets(fact_1_id, cube (fact_1_id, fact_2_id)) +having group_id() = 0 +order by fact_1_id, fact_2_id diff --git a/tests/groupby12.sql b/tests/groupby12.sql new file mode 100644 index 0000000..8c75f15 --- /dev/null +++ b/tests/groupby12.sql @@ -0,0 +1,8 @@ +select fact_1_id, + fact_2_id, + fact_3_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id, fact_3_id) as grouping_id +from dimension_tab +group by cube(fact_1_id, fact_2_id, fact_3_id) +order by fact_1_id, fact_2_id, fact_3_id \ No newline at end of file diff --git a/tests/groupby13.sql b/tests/groupby13.sql new file mode 100644 index 0000000..6633347 --- /dev/null +++ b/tests/groupby13.sql @@ -0,0 +1,8 @@ +select fact_1_id, + fact_2_id, + fact_3_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id, fact_3_id) as grouping_id +from dimension_tab +group by grouping sets((fact_1_id, fact_2_id), (fact_1_id, fact_3_id)) +order by fact_1_id, fact_2_id, fact_3_id \ No newline at end of file diff --git a/tests/groupby14.sql b/tests/groupby14.sql new file mode 100644 index 0000000..1048264 --- /dev/null +++ b/tests/groupby14.sql @@ -0,0 +1,8 @@ +select fact_1_id, + fact_2_id, + fact_3_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id, fact_3_id) as grouping_id +from dimension_tab +group by cube(fact_1_id, fact_2_id, fact_3_id) +order by fact_1_id, fact_2_id, fact_3_id diff --git a/tests/groupby15.sql b/tests/groupby15.sql new file mode 100644 index 0000000..bd3da1c --- /dev/null +++ b/tests/groupby15.sql @@ -0,0 +1,8 @@ +select fact_1_id, + fact_2_id, + fact_3_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id, fact_3_id) as grouping_id +from dimension_tab +group by cube((fact_1_id, fact_2_id), fact_3_id) +order by fact_1_id, fact_2_id, fact_3_id diff --git a/tests/groupby16.sql b/tests/groupby16.sql new file mode 100644 index 0000000..d5aeb49 --- /dev/null +++ b/tests/groupby16.sql @@ -0,0 +1,7 @@ +select fact_1_id, + fact_2_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id) as grouping_id +from dimension_tab +group by grouping sets(fact_1_id, fact_2_id) +order by fact_1_id, fact_2_id \ No newline at end of file diff --git a/tests/groupby17.sql b/tests/groupby17.sql new file mode 100644 index 0000000..03166a8 --- /dev/null +++ b/tests/groupby17.sql @@ -0,0 +1,7 @@ +select fact_3_id, + fact_4_id, + sum(sales_value) as sales_value, + grouping_id(fact_3_id, fact_4_id) as grouping_id +from dimension_tab +group by grouping sets(fact_3_id, fact_4_id) +order by fact_3_id, fact_4_id \ No newline at end of file diff --git a/tests/groupby18.sql b/tests/groupby18.sql new file mode 100644 index 0000000..92b7ad7 --- /dev/null +++ b/tests/groupby18.sql @@ -0,0 +1,9 @@ +select fact_1_id, + fact_2_id, + fact_3_id, + fact_4_id, + sum(sales_value) as sales_value, + grouping_id(fact_1_id, fact_2_id, fact_3_id, fact_4_id) as grouping_id +from dimension_tab +group by grouping sets(fact_1_id, fact_2_id), grouping sets(fact_3_id, fact_4_id) +order by fact_1_id, fact_2_id, fact_3_id, fact_4_id \ No newline at end of file diff --git a/tests/groupby19.sql b/tests/groupby19.sql new file mode 100644 index 0000000..4344eb3 --- /dev/null +++ b/tests/groupby19.sql @@ -0,0 +1,9 @@ +select channels.channel_desc, countries.country_iso_code, + to_char(sum(amount_sold), '9,999,999,999') sales$ +from sales, customers, times, channels, countries +where sales.time_id=times.time_id and sales.cust_id=customers.cust_id and + sales.channel_id= channels.channel_id and channels.channel_desc in + ('direct sales', 'internet') and times.calendar_month_desc='2000-09' + and customers.country_id=countries.country_id + and countries.country_iso_code in ('us','fr') +group by cube(channels.channel_desc, countries.country_iso_code) diff --git a/tests/groupby20.sql b/tests/groupby20.sql new file mode 100644 index 0000000..f1c87a7 --- /dev/null +++ b/tests/groupby20.sql @@ -0,0 +1,13 @@ +select channels.channel_desc, calendar_month_desc, + countries.country_iso_code, + to_char(sum(amount_sold), '9,999,999,999') sales$ +from sales, customers, times, channels, countries +where sales.time_id=times.time_id + and sales.cust_id=customers.cust_id + and customers.country_id = countries.country_id + and sales.channel_id = channels.channel_id + and channels.channel_desc in ('direct sales', 'internet') + and times.calendar_month_desc in ('2000-09', '2000-10') + and countries.country_iso_code in ('gb', 'us') +group by + rollup(channels.channel_desc, calendar_month_desc, countries.country_iso_code); \ No newline at end of file diff --git a/tests/groupby21.sql b/tests/groupby21.sql new file mode 100644 index 0000000..a9686aa --- /dev/null +++ b/tests/groupby21.sql @@ -0,0 +1,10 @@ +select channel_desc, calendar_month_desc, countries.country_iso_code, + to_char(sum(amount_sold), '9,999,999,999') sales$ +from sales, customers, times, channels, countries +where sales.time_id=times.time_id and sales.cust_id=customers.cust_id and + sales.channel_id= channels.channel_id + and customers.country_id = countries.country_id + and channels.channel_desc in + ('direct sales', 'internet') and times.calendar_month_desc in + ('2000-09', '2000-10') and countries.country_iso_code in ('gb', 'us') +group by cube(channel_desc, calendar_month_desc, countries.country_iso_code) \ No newline at end of file diff --git a/tests/groupby22.sql b/tests/groupby22.sql new file mode 100644 index 0000000..5b0c9c6 --- /dev/null +++ b/tests/groupby22.sql @@ -0,0 +1,12 @@ +select channel_desc, calendar_month_desc, country_iso_code, +to_char(sum(amount_sold), '9,999,999,999') sales$, grouping(channel_desc) as ch, + grouping(calendar_month_desc) as mo, grouping(country_iso_code) as co +from sales, customers, times, channels, countries +where sales.time_id=times.time_id + and sales.cust_id=customers.cust_id + and customers.country_id = countries.country_id + and sales.channel_id= channels.channel_id + and channels.channel_desc in ('direct sales', 'internet') + and times.calendar_month_desc in ('2000-09', '2000-10') + and countries.country_iso_code in ('gb', 'us') +group by rollup(channel_desc, calendar_month_desc, countries.country_iso_code) diff --git a/tests/groupby23.sql b/tests/groupby23.sql new file mode 100644 index 0000000..4b16c2c --- /dev/null +++ b/tests/groupby23.sql @@ -0,0 +1,15 @@ +select channel_desc, calendar_month_desc, country_iso_code, to_char( +sum(amount_sold), '9,999,999,999') sales$, grouping(channel_desc) ch, grouping + (calendar_month_desc) mo, grouping(country_iso_code) co +from sales, customers, times, channels, countries +where sales.time_id=times.time_id and sales.cust_id=customers.cust_id + and customers.country_id = countries.country_id + and sales.channel_id= channels.channel_id + and channels.channel_desc in ('direct sales', 'internet') + and times.calendar_month_desc in ('2000-09', '2000-10') + and country_iso_code in ('gb', 'us') +group by cube(channel_desc, calendar_month_desc, country_iso_code) +having (grouping(channel_desc)=1 and grouping(calendar_month_desc)= 1 + and grouping(country_iso_code)=1) or (grouping(channel_desc)=1 + and grouping (calendar_month_desc)= 1) or (grouping(country_iso_code)=1 + and grouping(calendar_month_desc)= 1) From e98ac472883368fc87225d11fdbd2de3a27fc933 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Wed, 29 Aug 2012 15:07:58 +0200 Subject: [PATCH 07/43] update bunch of records in a row --- tests/cast_multiset11.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/cast_multiset11.sql diff --git a/tests/cast_multiset11.sql b/tests/cast_multiset11.sql new file mode 100644 index 0000000..c5dc0a6 --- /dev/null +++ b/tests/cast_multiset11.sql @@ -0,0 +1,4 @@ +update table_name +set row = array_of_records(i) +where 1=1 + \ No newline at end of file From 118052403f5852b17223a4aad81c28f931663c58 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Thu, 27 Sep 2012 12:12:32 +0200 Subject: [PATCH 08/43] new tests, returning into bulk collect --- tests/loop01.sql | 8 ++++++++ tests/returning01.sql | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 tests/loop01.sql create mode 100644 tests/returning01.sql diff --git a/tests/loop01.sql b/tests/loop01.sql new file mode 100644 index 0000000..05c2532 --- /dev/null +++ b/tests/loop01.sql @@ -0,0 +1,8 @@ +begin + forall i in indices of :jobs + update emp + set ename = lower(ename) + where job = :jobs(i) + returning empno + bulk collect into :empnos; +end; diff --git a/tests/returning01.sql b/tests/returning01.sql new file mode 100644 index 0000000..0aacd03 --- /dev/null +++ b/tests/returning01.sql @@ -0,0 +1,5 @@ +update emp +set ename = lower(ename) +where job = :jobs(i) +returning empno +bulk collect into :empnos From 324e97a1532c511c2bba43b19691f43479f1b328 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 19 Nov 2012 16:10:25 +0100 Subject: [PATCH 09/43] testcase fixed --- tests/comment02.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/comment02.sql b/tests/comment02.sql index 3051de2..da9654b 100644 --- a/tests/comment02.sql +++ b/tests/comment02.sql @@ -31,5 +31,3 @@ SELECT -- REFS.* -- , SYS_CONNECT_BY_PATH(table_name, '/') "Path" FROM REFS CONNECT BY NOCYCLE PRIOR r_owner = owner AND PRIOR r_table_name = table_name -/ - From 489212a2d11fffe2d1be667ed14333283626c06e Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 19 Nov 2012 19:59:39 +0100 Subject: [PATCH 10/43] CAST and MULTISET are now treated as reserved words, multiset operations like UNION and EXCEPT are not supported yet --- parsers/PLSQLCommons.g | 6 ++++++ parsers/PLSQLKeys.g | 6 ++++-- parsers/PLSQLLexer.g | 8 ++++++++ parsers/PLSQL_DMLParser.g | 14 +++++++------- parsers/no-ast/PLSQLCommons.g | 6 ++++++ parsers/no-ast/PLSQLKeys.g | 6 ++++-- parsers/no-ast/PLSQL_DMLParser.g | 19 ++++++++++--------- tests/cast_multiset01.sql | 19 ++++++++++++++----- tests/cast_multiset12.sql | 6 ++++++ tests/cast_multiset13.sql | 3 +++ tests/cast_multiset14.sql | 4 ++++ tests/cast_multiset15.sql | 4 ++++ tests/condition19.sql | 5 +++++ tests/condition20.sql | 4 ++++ 14 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 tests/cast_multiset12.sql create mode 100644 tests/cast_multiset13.sql create mode 100644 tests/cast_multiset14.sql create mode 100644 tests/cast_multiset15.sql create mode 100644 tests/condition19.sql create mode 100644 tests/condition20.sql diff --git a/parsers/PLSQLCommons.g b/parsers/PLSQLCommons.g index f247964..9fd86b4 100644 --- a/parsers/PLSQLCommons.g +++ b/parsers/PLSQLCommons.g @@ -511,6 +511,12 @@ concatenation_op | VERTICAL_BAR VERTICAL_BAR ; +//multiset_op +// : multiset_key +// ( except_key | intersect_key | union_key ) +// ( all_key | distinct_key )? +// ; + outer_join_sign : LEFT_PAREN PLUS_SIGN RIGHT_PAREN ; diff --git a/parsers/PLSQLKeys.g b/parsers/PLSQLKeys.g index feaa5f4..a9ec7eb 100644 --- a/parsers/PLSQLKeys.g +++ b/parsers/PLSQLKeys.g @@ -1514,7 +1514,8 @@ over_key ; multiset_key - : {input.LT(1).getText().equalsIgnoreCase("multiset")}?=> REGULAR_ID +// : {input.LT(1).getText().equalsIgnoreCase("multiset")}?=> REGULAR_ID + : PLSQL_NON_RESERVED_MULTISET ; connect_by_root_key @@ -2082,7 +2083,8 @@ match_key ; cast_key - : {input.LT(1).getText().equalsIgnoreCase("cast")}? REGULAR_ID -> CAST_VK[$REGULAR_ID] +// : {input.LT(1).getText().equalsIgnoreCase("cast")}? REGULAR_ID -> CAST_VK[$REGULAR_ID] + : PLSQL_NON_RESERVED_CAST ; full_key: {input.LT(1).getText().equalsIgnoreCase("full")}?=> REGULAR_ID -> FULL_VK[$REGULAR_ID] diff --git a/parsers/PLSQLLexer.g b/parsers/PLSQLLexer.g index fd03941..6fef6dd 100644 --- a/parsers/PLSQLLexer.g +++ b/parsers/PLSQLLexer.g @@ -815,6 +815,14 @@ SQL92_RESERVED_WITH : 'with' ; +PLSQL_NON_RESERVED_CAST + : 'cast' + ; + +PLSQL_NON_RESERVED_MULTISET + : 'multiset' + ; + PLSQL_NON_RESERVED_USING : 'using' ; diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 9edd7a6..eddae20 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -853,7 +853,7 @@ negated_expression equality_expression @init { boolean isNegated = false; } - : (multiset_expression -> multiset_expression) + : (multiset_comparsion -> multiset_comparsion) ( is_key (not_key {isNegated = true;})? ( null_key -> {isNegated}? ^(IS_NOT_NULL $equality_expression) @@ -881,10 +881,10 @@ equality_expression ; -multiset_expression +multiset_comparsion : (relational_expression -> relational_expression) ( multiset_type of_key? concatenation - -> ^(multiset_type $multiset_expression ^(EXPR concatenation)))? + -> ^(multiset_type $multiset_comparsion ^(EXPR concatenation)))? ; multiset_type @@ -1123,10 +1123,10 @@ standard_function RIGHT_PAREN! over_clause? | (cast_key^|xmlcast_key^) LEFT_PAREN! - ( (multiset_key LEFT_PAREN (select_key|with_key)) => (multiset_key! LEFT_PAREN! subquery RIGHT_PAREN!) - | concatenation_wrapper - ) - as_key! type_spec + ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => (multiset_key! LEFT_PAREN! subquery RIGHT_PAREN!) + (as_key! type_spec)? + | concatenation_wrapper as_key! type_spec + ) RIGHT_PAREN! | chr_key^ LEFT_PAREN! diff --git a/parsers/no-ast/PLSQLCommons.g b/parsers/no-ast/PLSQLCommons.g index 0a3d237..de14513 100644 --- a/parsers/no-ast/PLSQLCommons.g +++ b/parsers/no-ast/PLSQLCommons.g @@ -406,6 +406,12 @@ concatenation_op | VERTICAL_BAR VERTICAL_BAR ; +// multiset_op +// : multiset_key +// ( except_key | intersect_key | union_key ) +// ( all_key | distinct_key )? +// ; + outer_join_sign : LEFT_PAREN PLUS_SIGN RIGHT_PAREN ; diff --git a/parsers/no-ast/PLSQLKeys.g b/parsers/no-ast/PLSQLKeys.g index fcf5b68..10f07c3 100644 --- a/parsers/no-ast/PLSQLKeys.g +++ b/parsers/no-ast/PLSQLKeys.g @@ -1190,7 +1190,8 @@ over_key ; multiset_key - : {input.LT(1).getText().equalsIgnoreCase("multiset")}?=> REGULAR_ID +// : {input.LT(1).getText().equalsIgnoreCase("multiset")}?=> REGULAR_ID + : PLSQL_NON_RESERVED_MULTISET ; connect_by_root_key @@ -1758,7 +1759,8 @@ match_key ; cast_key - : {input.LT(1).getText().equalsIgnoreCase("cast")}? REGULAR_ID +// : {input.LT(1).getText().equalsIgnoreCase("cast")}? REGULAR_ID + : PLSQL_NON_RESERVED_CAST ; full_key: {input.LT(1).getText().equalsIgnoreCase("full")}?=> REGULAR_ID diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index b7b254e..0bac50d 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -680,7 +680,8 @@ condition_wrapper ; expression - : (cursor_key LEFT_PAREN (select_key|with_key)) => cursor_expression + : (cursor_key LEFT_PAREN (select_key|with_key)) => cursor_expression +// | (atom multiset_op atom) => atom multiset_op atom | logical_and_expression ( or_key logical_and_expression )* ; @@ -698,7 +699,7 @@ negated_expression ; equality_expression - : multiset_expression + : multiset_comparsion ( is_key not_key? ( null_key | nan_key @@ -712,7 +713,7 @@ equality_expression ; -multiset_expression +multiset_comparsion : relational_expression ( multiset_type of_key? concatenation)? ; @@ -920,12 +921,12 @@ standard_function ( ASTERISK | (distinct_key|unique_key|all_key)? concatenation_wrapper ) RIGHT_PAREN over_clause? | (cast_key|xmlcast_key) - LEFT_PAREN - ( (multiset_key LEFT_PAREN (select_key|with_key)) => multiset_key LEFT_PAREN subquery RIGHT_PAREN - | concatenation_wrapper - ) - as_key type_spec - RIGHT_PAREN + LEFT_PAREN + ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => multiset_key LEFT_PAREN subquery RIGHT_PAREN + (as_key type_spec)? + | concatenation_wrapper as_key type_spec + ) + RIGHT_PAREN | chr_key LEFT_PAREN concatenation_wrapper using_key nchar_cs_key diff --git a/tests/cast_multiset01.sql b/tests/cast_multiset01.sql index bc68388..13eafc5 100644 --- a/tests/cast_multiset01.sql +++ b/tests/cast_multiset01.sql @@ -1,7 +1,16 @@ select t1.department_id, t2.* - from hr_info t1, table(cast(multiset( - select t3.last_name, t3.department_id, t3.salary - from people t3 - where t3.department_id = t1.department_id) - as people_tab_typ)) t2 + from hr_info t1, + table + ( + cast + ( + multiset + ( + select t3.last_name, t3.department_id, t3.salary + from people t3 + where t3.department_id = t1.department_id + ) + as people_tab_typ + ) +) t2 diff --git a/tests/cast_multiset12.sql b/tests/cast_multiset12.sql new file mode 100644 index 0000000..3974ec0 --- /dev/null +++ b/tests/cast_multiset12.sql @@ -0,0 +1,6 @@ +update customers_demo cd + set cust_address2_ntab = + cast(multiset(select cust_address + from customers c + where c.customer_id = + cd.customer_id) as cust_address_tab_typ) diff --git a/tests/cast_multiset13.sql b/tests/cast_multiset13.sql new file mode 100644 index 0000000..83b69c3 --- /dev/null +++ b/tests/cast_multiset13.sql @@ -0,0 +1,3 @@ +select customer_id, cust_address_ntab +multiset except distinct cust_address2_ntab multiset_except +from customers_demo diff --git a/tests/cast_multiset14.sql b/tests/cast_multiset14.sql new file mode 100644 index 0000000..a2013a2 --- /dev/null +++ b/tests/cast_multiset14.sql @@ -0,0 +1,4 @@ +select customer_id, cust_address_ntab +multiset intersect all cust_address2_ntab multiset_intersect +from customers_demo +order by customer_id diff --git a/tests/cast_multiset15.sql b/tests/cast_multiset15.sql new file mode 100644 index 0000000..e34fa93 --- /dev/null +++ b/tests/cast_multiset15.sql @@ -0,0 +1,4 @@ +select customer_id, cust_address_ntab +multiset union cust_address2_ntab multiset_union +from customers_demo +order by customer_id diff --git a/tests/condition19.sql b/tests/condition19.sql new file mode 100644 index 0000000..de23d24 --- /dev/null +++ b/tests/condition19.sql @@ -0,0 +1,5 @@ +select * from employees + where (salary, salary) >= + some ( 1400, 3000) + order by employee_id + \ No newline at end of file diff --git a/tests/condition20.sql b/tests/condition20.sql new file mode 100644 index 0000000..77419b6 --- /dev/null +++ b/tests/condition20.sql @@ -0,0 +1,4 @@ +select * from employees + where (salary, salary) >= + some ( select 1, 2 from dual ) + order by employee_id From 3dd727583586bbe675da470d48550c88a2778c70 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Nov 2012 16:17:21 +0100 Subject: [PATCH 11/43] Full support for set operators within SQL expressions --- parsers/PLSQLCommons.g | 10 +++++----- parsers/PLSQL_DMLParser.g | 7 ++++++- parsers/TestPLSQL_DML.testsuite | 7 ++++++- parsers/no-ast/PLSQLCommons.g | 10 +++++----- parsers/no-ast/PLSQL_DMLParser.g | 9 +++++++-- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/parsers/PLSQLCommons.g b/parsers/PLSQLCommons.g index 9fd86b4..8321ec8 100644 --- a/parsers/PLSQLCommons.g +++ b/parsers/PLSQLCommons.g @@ -511,11 +511,11 @@ concatenation_op | VERTICAL_BAR VERTICAL_BAR ; -//multiset_op -// : multiset_key -// ( except_key | intersect_key | union_key ) -// ( all_key | distinct_key )? -// ; +multiset_op + : multiset_key + ( except_key | intersect_key | union_key ) + ( all_key | distinct_key )? + ; outer_join_sign : LEFT_PAREN PLUS_SIGN RIGHT_PAREN diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index eddae20..ca968fa 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -979,7 +979,7 @@ interval_expression ; model_expression - : (unary_expression -> unary_expression) + : (multiset_expression -> multiset_expression) (LEFT_BRACKET model_expression_element RIGHT_BRACKET -> ^(MODEL_EXPRESSION[$LEFT_BRACKET] $model_expression model_expression_element))? ; @@ -1021,6 +1021,11 @@ multi_column_for_loop -> ^(FOR_MULTI_COLUMN[$for_key.start] column_name+ ^(in_key subquery? expression_list*)) ; +multiset_expression + : unary_expression + ( multiset_op^ unary_expression )* + ; + unary_expression options { diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index ba3a0bf..e935541 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -104,8 +104,10 @@ cast_multiset05.sql OK cast_multiset06.sql OK cast_multiset07.sql OK cast_multiset08.sql OK -//!! FAILs ATM cast_multiset09.sql OK cast_multiset10.sql OK +cast_multiset13.sql OK +cast_multiset14.sql OK +cast_multiset15.sql OK case_when01.sql OK case_when02.sql OK case_when03.sql OK @@ -602,6 +604,9 @@ update_statement: where department_id = 100 returning salary into :bnd1>> OK condition18.sql OK +cast_multiset09.sql OK +cast_multiset11.sql OK +cast_multiset12.sql OK merge_statement: merge01.sql OK diff --git a/parsers/no-ast/PLSQLCommons.g b/parsers/no-ast/PLSQLCommons.g index de14513..9e1b747 100644 --- a/parsers/no-ast/PLSQLCommons.g +++ b/parsers/no-ast/PLSQLCommons.g @@ -406,11 +406,11 @@ concatenation_op | VERTICAL_BAR VERTICAL_BAR ; -// multiset_op -// : multiset_key -// ( except_key | intersect_key | union_key ) -// ( all_key | distinct_key )? -// ; + multiset_op + : multiset_key + ( except_key | intersect_key | union_key ) + ( all_key | distinct_key )? + ; outer_join_sign : LEFT_PAREN PLUS_SIGN RIGHT_PAREN diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index 0bac50d..cf2a2d3 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -709,7 +709,7 @@ equality_expression | empty_key | of_key type_key? LEFT_PAREN only_key? type_spec (COMMA type_spec)* RIGHT_PAREN ) - )* + )? ; @@ -790,7 +790,7 @@ interval_expression ; model_expression - : unary_expression + : multiset_expression (LEFT_BRACKET model_expression_element RIGHT_BRACKET)? ; @@ -826,6 +826,11 @@ multi_column_for_loop RIGHT_PAREN ; +multiset_expression + : unary_expression + ( multiset_op unary_expression )* + ; + unary_expression options { From ed0ea4c7f433205723815bee62492eda1435e230 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Nov 2012 18:10:00 +0100 Subject: [PATCH 12/43] fix COLLECT function 11gR2 feature, thx to oracle-developer.net --- parsers/PLSQL_DMLParser.g | 2 +- parsers/TestPLSQL_DML.testsuite | 22 ++++++++++++++++++++++ parsers/no-ast/PLSQL_DMLParser.g | 2 +- tests/cast_multiset16.sql | 6 ++++++ tests/cast_multiset17.sql | 5 +++++ tests/cast_multiset18.sql | 7 +++++++ tests/cast_multiset19.sql | 7 +++++++ tests/cast_multiset20.sql | 5 +++++ tests/cast_multiset21.sql | 7 +++++++ tests/cast_multiset22.sql | 7 +++++++ tests/cast_multiset23.sql | 7 +++++++ tests/cast_multiset24.sql | 9 +++++++++ tests/cast_multiset25.sql | 8 ++++++++ tests/cast_multiset26.sql | 8 ++++++++ tests/cast_multiset27.sql | 10 ++++++++++ tests/cast_multiset28.sql | 8 ++++++++ tests/cast_multiset29.sql | 5 +++++ tests/cast_multiset30.sql | 6 ++++++ tests/cast_multiset31.sql | 14 ++++++++++++++ tests/cast_multiset32.sql | 8 ++++++++ tests/cast_multiset33.sql | 7 +++++++ tests/cast_multiset34.sql | 8 ++++++++ tests/cast_multiset35.sql | 9 +++++++++ tests/cast_multiset36.sql | 10 ++++++++++ tests/cast_multiset37.sql | 10 ++++++++++ 25 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 tests/cast_multiset16.sql create mode 100644 tests/cast_multiset17.sql create mode 100644 tests/cast_multiset18.sql create mode 100644 tests/cast_multiset19.sql create mode 100644 tests/cast_multiset20.sql create mode 100644 tests/cast_multiset21.sql create mode 100644 tests/cast_multiset22.sql create mode 100644 tests/cast_multiset23.sql create mode 100644 tests/cast_multiset24.sql create mode 100644 tests/cast_multiset25.sql create mode 100644 tests/cast_multiset26.sql create mode 100644 tests/cast_multiset27.sql create mode 100644 tests/cast_multiset28.sql create mode 100644 tests/cast_multiset29.sql create mode 100644 tests/cast_multiset30.sql create mode 100644 tests/cast_multiset31.sql create mode 100644 tests/cast_multiset32.sql create mode 100644 tests/cast_multiset33.sql create mode 100644 tests/cast_multiset34.sql create mode 100644 tests/cast_multiset35.sql create mode 100644 tests/cast_multiset36.sql create mode 100644 tests/cast_multiset37.sql diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index ca968fa..4463094 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -1128,7 +1128,7 @@ standard_function RIGHT_PAREN! over_clause? | (cast_key^|xmlcast_key^) LEFT_PAREN! - ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => (multiset_key! LEFT_PAREN! subquery RIGHT_PAREN!) + ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => (multiset_key! LEFT_PAREN! subquery order_by_clause? RIGHT_PAREN!) (as_key! type_spec)? | concatenation_wrapper as_key! type_spec ) diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index e935541..3cb09d6 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -108,6 +108,28 @@ cast_multiset10.sql OK cast_multiset13.sql OK cast_multiset14.sql OK cast_multiset15.sql OK +cast_multiset16.sql OK +cast_multiset17.sql OK +cast_multiset18.sql OK +cast_multiset19.sql OK +cast_multiset20.sql OK +cast_multiset21.sql OK +cast_multiset22.sql OK +cast_multiset23.sql OK +cast_multiset24.sql OK +cast_multiset25.sql OK +cast_multiset26.sql OK +cast_multiset27.sql OK +cast_multiset28.sql OK +cast_multiset29.sql OK +cast_multiset30.sql OK +cast_multiset31.sql OK +cast_multiset32.sql OK +cast_multiset33.sql OK +cast_multiset34.sql OK +cast_multiset35.sql OK +cast_multiset36.sql OK +cast_multiset37.sql OK case_when01.sql OK case_when02.sql OK case_when03.sql OK diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index cf2a2d3..14d0e47 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -927,7 +927,7 @@ standard_function RIGHT_PAREN over_clause? | (cast_key|xmlcast_key) LEFT_PAREN - ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => multiset_key LEFT_PAREN subquery RIGHT_PAREN + ( (multiset_key LEFT_PAREN+ (select_key|with_key)) => multiset_key LEFT_PAREN subquery order_by_clause? RIGHT_PAREN (as_key type_spec)? | concatenation_wrapper as_key type_spec ) diff --git a/tests/cast_multiset16.sql b/tests/cast_multiset16.sql new file mode 100644 index 0000000..848cda5 --- /dev/null +++ b/tests/cast_multiset16.sql @@ -0,0 +1,6 @@ +select deptno + , collect(ename) as emps + from emp + group by + deptno + \ No newline at end of file diff --git a/tests/cast_multiset17.sql b/tests/cast_multiset17.sql new file mode 100644 index 0000000..1b1c6d0 --- /dev/null +++ b/tests/cast_multiset17.sql @@ -0,0 +1,5 @@ +select deptno + , cast(collect(ename) as varchar2_ntt) as emps + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset18.sql b/tests/cast_multiset18.sql new file mode 100644 index 0000000..cfe41df --- /dev/null +++ b/tests/cast_multiset18.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + collect(ename order by ename) + as varchar2_ntt) as ordered_emps + from emp + group by + deptno diff --git a/tests/cast_multiset19.sql b/tests/cast_multiset19.sql new file mode 100644 index 0000000..97b764d --- /dev/null +++ b/tests/cast_multiset19.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + collect(ename order by hiredate) + as varchar2_ntt) as ordered_emps + from emp + group by + deptno diff --git a/tests/cast_multiset20.sql b/tests/cast_multiset20.sql new file mode 100644 index 0000000..40d4ee9 --- /dev/null +++ b/tests/cast_multiset20.sql @@ -0,0 +1,5 @@ +select deptno + , cast(collect(job) as varchar2_ntt) as jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset21.sql b/tests/cast_multiset21.sql new file mode 100644 index 0000000..3f4c7a2 --- /dev/null +++ b/tests/cast_multiset21.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + collect(distinct job) + as varchar2_ntt) as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset22.sql b/tests/cast_multiset22.sql new file mode 100644 index 0000000..9e9712a --- /dev/null +++ b/tests/cast_multiset22.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + collect(unique job) + as varchar2_ntt) as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset23.sql b/tests/cast_multiset23.sql new file mode 100644 index 0000000..48b9d4d --- /dev/null +++ b/tests/cast_multiset23.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + collect(all job) + as varchar2_ntt) as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset24.sql b/tests/cast_multiset24.sql new file mode 100644 index 0000000..9054111 --- /dev/null +++ b/tests/cast_multiset24.sql @@ -0,0 +1,9 @@ +select deptno + , cast( + collect( + distinct job + order by job + ) as varchar2_ntt) as distinct_ordered_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset25.sql b/tests/cast_multiset25.sql new file mode 100644 index 0000000..38a017f --- /dev/null +++ b/tests/cast_multiset25.sql @@ -0,0 +1,8 @@ +select deptno + , cast( + collect( + empsal_ot(ename, sal) + ) as empsal_ntt) as empsals + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset26.sql b/tests/cast_multiset26.sql new file mode 100644 index 0000000..61bae8f --- /dev/null +++ b/tests/cast_multiset26.sql @@ -0,0 +1,8 @@ +select deptno + , cast( + collect( + empsal_ot(ename, sal) order by sal + ) as empsal_ntt) as empsals + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset27.sql b/tests/cast_multiset27.sql new file mode 100644 index 0000000..01705a3 --- /dev/null +++ b/tests/cast_multiset27.sql @@ -0,0 +1,10 @@ +select deptno + , cast( + collect( + empsal_ot(ename, sal) + order by empsal_ot(ename, sal) + ) as empsal_ntt) as empsals + from emp + group by + deptno + diff --git a/tests/cast_multiset28.sql b/tests/cast_multiset28.sql new file mode 100644 index 0000000..86dd3cc --- /dev/null +++ b/tests/cast_multiset28.sql @@ -0,0 +1,8 @@ +select deptno + , cast( + collect( + distinct empsal_ot(ename, sal) + ) as empsal_ntt) as empsals + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset29.sql b/tests/cast_multiset29.sql new file mode 100644 index 0000000..5a3f19e --- /dev/null +++ b/tests/cast_multiset29.sql @@ -0,0 +1,5 @@ +select cast( + collect( + distinct empsal_ot(ename, sal) + ) as empsal_ntt) as empsals + from emp \ No newline at end of file diff --git a/tests/cast_multiset30.sql b/tests/cast_multiset30.sql new file mode 100644 index 0000000..9cc97fa --- /dev/null +++ b/tests/cast_multiset30.sql @@ -0,0 +1,6 @@ +select cast( + collect( + distinct empsal_ot(ename, sal) + ) as empsal_ntt) as empsals + from emp + \ No newline at end of file diff --git a/tests/cast_multiset31.sql b/tests/cast_multiset31.sql new file mode 100644 index 0000000..6b253fb --- /dev/null +++ b/tests/cast_multiset31.sql @@ -0,0 +1,14 @@ +select e.deptno + , cast( + multiset( + select e2.ename + from emp e2 + where e2.deptno = e.deptno + order by + e2.hiredate + ) as varchar2_ntt) as ordered_emps + from emp e + group by + e.deptno + order by + e.deptno \ No newline at end of file diff --git a/tests/cast_multiset32.sql b/tests/cast_multiset32.sql new file mode 100644 index 0000000..88fe053 --- /dev/null +++ b/tests/cast_multiset32.sql @@ -0,0 +1,8 @@ +select deptno + , set( + cast( + collect(job) + as varchar2_ntt)) as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset33.sql b/tests/cast_multiset33.sql new file mode 100644 index 0000000..7df97a9 --- /dev/null +++ b/tests/cast_multiset33.sql @@ -0,0 +1,7 @@ +select deptno + , cast( + set(collect(job)) + as varchar2_ntt) as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset34.sql b/tests/cast_multiset34.sql new file mode 100644 index 0000000..41769aa --- /dev/null +++ b/tests/cast_multiset34.sql @@ -0,0 +1,8 @@ +select deptno + , cast( + collect(job) + as varchar2_ntt + ) multiset union distinct varchar2_ntt() as distinct_jobs + from emp + group by + deptno \ No newline at end of file diff --git a/tests/cast_multiset35.sql b/tests/cast_multiset35.sql new file mode 100644 index 0000000..a3983c8 --- /dev/null +++ b/tests/cast_multiset35.sql @@ -0,0 +1,9 @@ +select owner + , object_type + , cast( + collect(distinct object_name) + as varchar2_ntt) as object_names + from all_objects + group by + owner + , object_type \ No newline at end of file diff --git a/tests/cast_multiset36.sql b/tests/cast_multiset36.sql new file mode 100644 index 0000000..76b56b9 --- /dev/null +++ b/tests/cast_multiset36.sql @@ -0,0 +1,10 @@ +select owner + , object_type + , set( + cast( + collect(object_name) + as varchar2_ntt)) as object_names + from all_objects + group by + owner + , object_type \ No newline at end of file diff --git a/tests/cast_multiset37.sql b/tests/cast_multiset37.sql new file mode 100644 index 0000000..c8e7cd0 --- /dev/null +++ b/tests/cast_multiset37.sql @@ -0,0 +1,10 @@ +select owner + , object_type + , cast( + collect(object_name) + as varchar2_ntt + ) multiset union distinct varchar2_ntt() as object_names + from all_objects + group by + owner + , object_type From 5afebec1c69cafaa429aeece15c67fd09022481d Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Nov 2012 18:22:30 +0100 Subject: [PATCH 13/43] CLUSTER_SET function - see datawarehousing guide --- tests/cluster_set01.sql | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/cluster_set01.sql diff --git a/tests/cluster_set01.sql b/tests/cluster_set01.sql new file mode 100644 index 0000000..5e49785 --- /dev/null +++ b/tests/cluster_set01.sql @@ -0,0 +1,35 @@ +with +clus_tab as ( +select id, + a.attribute_name aname, + a.conditional_operator op, + nvl(a.attribute_str_value, + round(a.attribute_num_value),4)) val, + a.attribute_support support, + a.attribute_confidence confidence + from table(dbms_data_mining.get_model_details_km('km_sh_clus_sample')) t, + table(t.rule.antecedent) a + where a.attribute_confidence > 0.55 +), +clust as ( +select id, + cast(collect(cattr(aname, op, to_char(val), support, confidence)) + as cattrs) cl_attrs + from clus_tab +group by id +), +custclus as ( +select t.cust_id, s.cluster_id, s.probability + from (select cust_id, cluster_set(km_sh_clus_sample, null, 0.2 using *) pset + from mining_data_apply_v + where cust_id = 101362) t, + table(t.pset) s +) +select a.probability prob, a.cluster_id cl_id, + b.attr, b.op, b.val, b.supp, b.conf + from custclus a, + (select t.id, c.* + from clust t, + table(t.cl_attrs) c) b + where a.cluster_id = b.id +order by prob desc, cl_id asc, conf desc, attr asc, val asc From 436ef5b569b94adf8c4ffdcd3c030a3c6ca53815 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Nov 2012 18:31:35 +0100 Subject: [PATCH 14/43] syntax error in Oracle docs --- tests/cluster_set01.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/cluster_set01.sql b/tests/cluster_set01.sql index 5e49785..dd06e45 100644 --- a/tests/cluster_set01.sql +++ b/tests/cluster_set01.sql @@ -3,8 +3,7 @@ clus_tab as ( select id, a.attribute_name aname, a.conditional_operator op, - nvl(a.attribute_str_value, - round(a.attribute_num_value),4)) val, + nvl(a.attribute_str_value, round(a.attribute_num_value),4) val, a.attribute_support support, a.attribute_confidence confidence from table(dbms_data_mining.get_model_details_km('km_sh_clus_sample')) t, From 889aa67034d181b3428c02d9a7f8e9153a9fac4d Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Nov 2012 18:35:04 +0100 Subject: [PATCH 15/43] PREDICTION function --- tests/function07.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/function07.sql diff --git a/tests/function07.sql b/tests/function07.sql new file mode 100644 index 0000000..82169ce --- /dev/null +++ b/tests/function07.sql @@ -0,0 +1,7 @@ +select cust_gender, count(*) as cnt, round(avg(age)) as avg_age + from mining_data_apply_v + where prediction(dt_sh_clas_sample cost model + using cust_marital_status, education, household_size) = 1 + group by cust_gender + order by cust_gender + \ No newline at end of file From 086d89da0e3f31aeb81270113b8dff0d2eeb9bc7 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Wed, 21 Nov 2012 14:18:12 +0100 Subject: [PATCH 16/43] more tests added --- tests/cast_multiset38.sql | 4 ++++ tests/cast_multiset39.sql | 4 ++++ tests/cast_multiset40.sql | 4 ++++ tests/cast_multiset41.sql | 4 ++++ tests/cast_multiset42.sql | 6 ++++++ 5 files changed, 22 insertions(+) create mode 100644 tests/cast_multiset38.sql create mode 100644 tests/cast_multiset39.sql create mode 100644 tests/cast_multiset40.sql create mode 100644 tests/cast_multiset41.sql create mode 100644 tests/cast_multiset42.sql diff --git a/tests/cast_multiset38.sql b/tests/cast_multiset38.sql new file mode 100644 index 0000000..6f00721 --- /dev/null +++ b/tests/cast_multiset38.sql @@ -0,0 +1,4 @@ +select * + from table( varchar2_ntt('a','b','c') + multiset union distinct + varchar2_ntt('b','c','d') ) \ No newline at end of file diff --git a/tests/cast_multiset39.sql b/tests/cast_multiset39.sql new file mode 100644 index 0000000..d38c1b2 --- /dev/null +++ b/tests/cast_multiset39.sql @@ -0,0 +1,4 @@ +select varchar2_ntt('a','b','c') + multiset except + varchar2_ntt('b','c','d') as multiset_except + from dual \ No newline at end of file diff --git a/tests/cast_multiset40.sql b/tests/cast_multiset40.sql new file mode 100644 index 0000000..f3bb077 --- /dev/null +++ b/tests/cast_multiset40.sql @@ -0,0 +1,4 @@ +select cast( + powermultiset( + varchar2_ntt('a','b','c')) as varchar2_ntts) as pwrmltset + from dual \ No newline at end of file diff --git a/tests/cast_multiset41.sql b/tests/cast_multiset41.sql new file mode 100644 index 0000000..70e247d --- /dev/null +++ b/tests/cast_multiset41.sql @@ -0,0 +1,4 @@ +select * + from table( + powermultiset_by_cardinality( + varchar2_ntt('a','b','c','d','d'), 3)) \ No newline at end of file diff --git a/tests/cast_multiset42.sql b/tests/cast_multiset42.sql new file mode 100644 index 0000000..308bc17 --- /dev/null +++ b/tests/cast_multiset42.sql @@ -0,0 +1,6 @@ +select * + from table( + set( complex_ntt(complex_ot('data', 'more data', 1), + complex_ot('data', 'some data', 2), + complex_ot('data', 'dupe data', 3), + complex_ot('data', 'dupe data', 3)) )) \ No newline at end of file From 83c059e29ac2b66243a157105e346f21b622f059 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Thu, 10 Jan 2013 10:26:38 +0100 Subject: [PATCH 17/43] =?UTF-8?q?CONNECT=5FBY=5FROOT=E2=80=82unary=20opera?= =?UTF-8?q?tor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/connect_by06.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/connect_by06.sql diff --git a/tests/connect_by06.sql b/tests/connect_by06.sql new file mode 100644 index 0000000..fbe3b0c --- /dev/null +++ b/tests/connect_by06.sql @@ -0,0 +1,7 @@ +select last_name "Employee", connect_by_root last_name "Manager", + level-1 "Pathlen", sys_connect_by_path(last_name, '/') "Path" + from employees + where level > 1 and department_id = 110 + connect by prior employee_id = manager_id + order by "Employee", "Manager", "Pathlen", "Path" + \ No newline at end of file From 259f26e4e2b94e25f290784cda3f380a36be5943 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 8 Mar 2013 09:44:09 +0100 Subject: [PATCH 18/43] new unit test files 11gR2 listagg --- tests/analytic_query08.sql | 4 ++++ tests/analytic_query09.sql | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/analytic_query08.sql create mode 100644 tests/analytic_query09.sql diff --git a/tests/analytic_query08.sql b/tests/analytic_query08.sql new file mode 100644 index 0000000..a270029 --- /dev/null +++ b/tests/analytic_query08.sql @@ -0,0 +1,4 @@ +select manager_id, last_name, hire_date, + count(*) over (partition by manager_id order by hire_date + range numtodsinterval(100, 'day') preceding) as t_count + from employees \ No newline at end of file diff --git a/tests/analytic_query09.sql b/tests/analytic_query09.sql new file mode 100644 index 0000000..bd38cc4 --- /dev/null +++ b/tests/analytic_query09.sql @@ -0,0 +1,13 @@ +select + listagg(column_value, ',') within group (order by column_value) +from + table( + cast( + multiset( + select 'one' from dual + union all + select 'two' from dual + ) as t_str + ) + ) + \ No newline at end of file From c7f809e54a75a6f6830469f77e292fef705ef8ce Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 8 Mar 2013 09:47:00 +0100 Subject: [PATCH 19/43] collect operator --- tests/cast_multiset43.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/cast_multiset43.sql diff --git a/tests/cast_multiset43.sql b/tests/cast_multiset43.sql new file mode 100644 index 0000000..df01107 --- /dev/null +++ b/tests/cast_multiset43.sql @@ -0,0 +1,9 @@ +select deptno +, avg(sal) avg_sal +, cast + ( collect(ename) + as ename_type + ) enames +from emp +group +by deptno From ef803283b1b5f93cdd8550405e731d4619fee2ff Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Thu, 14 Mar 2013 13:50:43 +0100 Subject: [PATCH 20/43] Fix for some number formats --- parsers/PLSQLLexer.g | 2 +- tests/numbers01.sql | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/parsers/PLSQLLexer.g b/parsers/PLSQLLexer.g index 6fef6dd..a75e3c8 100644 --- a/parsers/PLSQLLexer.g +++ b/parsers/PLSQLLexer.g @@ -159,7 +159,7 @@ PERIOD EXACT_NUM_LIT : ( UNSIGNED_INTEGER - ( '.' UNSIGNED_INTEGER + ( '.' UNSIGNED_INTEGER? | {$type = UNSIGNED_INTEGER;} ) ( ('E' | 'e') ('+' | '-')? UNSIGNED_INTEGER {$type = APPROXIMATE_NUM_LIT;} )? | '.' UNSIGNED_INTEGER ( ('E' | 'e') ('+' | '-')? UNSIGNED_INTEGER {$type = APPROXIMATE_NUM_LIT;} )? diff --git a/tests/numbers01.sql b/tests/numbers01.sql index 2991e12..3987650 100644 --- a/tests/numbers01.sql +++ b/tests/numbers01.sql @@ -7,8 +7,18 @@ select 25 , +6.34F , 0.5d , -1D +, 1. +, .5 , (sysdate -1d) -- here we substract "one" in decimal format , sysdate -1m -- here we substract "one" and "m" is column's alias , sysdate -1dm +, 1.-+.5 +, 1.+.5 +, 1.+.5D +, 1.+.5DM +, 1.D +, 1.M +, .5M +, .5DM from dual From 226f35eb11bbd7483d84abf56f1a560c23b855ea Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Sat, 22 Jun 2013 00:38:21 +0200 Subject: [PATCH 21/43] Fix typo in test case --- tests/groupby09.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/groupby09.sql b/tests/groupby09.sql index ad28d77..e67b35e 100644 --- a/tests/groupby09.sql +++ b/tests/groupby09.sql @@ -7,4 +7,3 @@ from dimension_tab group by cube (fact_1_id, fact_2_id) having grouping(fact_1_id) = 1 or grouping(fact_2_id) = 1 order by grouping(fact_1_id), grouping(fact_2_id) -l \ No newline at end of file From 55a499696339124f9e28b92919a73a2fa0c0768f Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 24 Jun 2013 00:05:35 +0200 Subject: [PATCH 22/43] Ported to ANTLR 3.5 --- lexer-parser/pom.xml | 5 ++--- parsers/PLSQLLexer.g | 2 +- pom.xml | 9 +++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lexer-parser/pom.xml b/lexer-parser/pom.xml index a779190..104aeba 100644 --- a/lexer-parser/pom.xml +++ b/lexer-parser/pom.xml @@ -53,14 +53,14 @@ java - -Xmx1g + -Xmx768m -classpath org.antlr.Tool -o ${project.build.directory}/generated-sources/antlr3/br/com/porcelli/parser/plsql/ - -Xmultithreaded + -lib ${project.basedir}/src/main/antlr3/br/com/porcelli/parser/plsql/imports/ ${project.basedir}/src/main/antlr3/br/com/porcelli/parser/plsql/PLSQLLexer.g @@ -73,7 +73,6 @@ org.antlr maven-gunit-plugin - 3.2 maven-gunit-plugin diff --git a/parsers/PLSQLLexer.g b/parsers/PLSQLLexer.g index a75e3c8..75ab071 100644 --- a/parsers/PLSQLLexer.g +++ b/parsers/PLSQLLexer.g @@ -76,7 +76,7 @@ import java.util.LinkedList; state.tokenStartLine = input.getLine(); state.text = null; if (input.LA(1) == CharStream.EOF) { - return Token.EOF_TOKEN; + return getEOFToken(); } try { int m = input.mark(); diff --git a/pom.xml b/pom.xml index f399ffd..0d733fb 100644 --- a/pom.xml +++ b/pom.xml @@ -40,12 +40,12 @@ org.antlr antlr - 3.3 + 3.5 org.antlr antlr-runtime - 3.3 + 3.5 @@ -62,6 +62,11 @@ + + org.antlr + maven-gunit-plugin + 3.5 + org.apache.maven.plugins maven-compiler-plugin From 93a12a12d107d8b3b789b42f9bfbe6f55a8ecbf8 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 24 Jun 2013 18:24:18 +0200 Subject: [PATCH 23/43] Lexer for notation fix --- parsers/PLSQLLexer.g | 9 +++++++-- parsers/TestPLSQLParser.testsuite | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/parsers/PLSQLLexer.g b/parsers/PLSQLLexer.g index 75ab071..a700b3f 100644 --- a/parsers/PLSQLLexer.g +++ b/parsers/PLSQLLexer.g @@ -116,8 +116,12 @@ FOR_NOTATION {state.type = UNSIGNED_INTEGER; emit(); advanceInput();} '..' {state.type = DOUBLE_PERIOD; emit(); advanceInput();} - UNSIGNED_INTEGER - {state.type = UNSIGNED_INTEGER; emit(); advanceInput(); $channel=HIDDEN;} + ( UNSIGNED_INTEGER + {state.type = UNSIGNED_INTEGER; emit(); advanceInput(); } + | REGULAR_ID + {state.type = REGULAR_ID; emit(); advanceInput(); } + )? + { $channel=HIDDEN; } ; //{ Rule #358 - subtoken typecast in , it also incorporates @@ -228,6 +232,7 @@ RIGHT_PAREN : ')' ; +// Not allowed in SQL, but in PL/SQL(ADA) yes DOUBLE_ASTERISK : '**' ; diff --git a/parsers/TestPLSQLParser.testsuite b/parsers/TestPLSQLParser.testsuite index e7f0efe..77df2c5 100644 --- a/parsers/TestPLSQLParser.testsuite +++ b/parsers/TestPLSQLParser.testsuite @@ -698,6 +698,14 @@ end loop>> OK end loop; end loop outer_loop>> OK +<> OK + forall_statement: <> OK From 84e210d60b74a94794960a3561d2cbe99764328e Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 1 Jul 2013 19:33:03 +0200 Subject: [PATCH 24/43] loop end with label --- tests/loop02.sql | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/loop02.sql diff --git a/tests/loop02.sql b/tests/loop02.sql new file mode 100644 index 0000000..bcaf924 --- /dev/null +++ b/tests/loop02.sql @@ -0,0 +1,13 @@ +BEGIN + <> + FOR i IN 1..3 LOOP + <> + FOR i IN 1..3 LOOP + IF outer_loop.i = 2 THEN + DBMS_OUTPUT.PUT_LINE + ( 'outer: ' || TO_CHAR(outer_loop.i) || ' inner: ' + || TO_CHAR(inner_loop.i)); + END IF; + END LOOP inner_loop; + END LOOP outer_loop; +END; \ No newline at end of file From 6fb726e13879ffc1c9cf435b568b583664eec173 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 29 Jul 2013 12:49:49 +0200 Subject: [PATCH 25/43] undocumented "opverlaps" operator - not implemented yet --- tests/interval05.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/interval05.sql diff --git a/tests/interval05.sql b/tests/interval05.sql new file mode 100644 index 0000000..e379aad --- /dev/null +++ b/tests/interval05.sql @@ -0,0 +1,2 @@ +-- see metalink note 1056382.1 +select 'yes' from dual where (sysdate-5,sysdate) overlaps (sysdate-2,sysdate-1) From 81358acc942aabe3aa24f6850ba9810807f0a7f2 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Aug 2013 12:27:13 +0200 Subject: [PATCH 26/43] Some tests added --- tests/analytic_query10.sql | 12 ++++++++++++ tests/datetime06.sql | 1 + tests/model_clause06.sql | 11 +++++++++++ tests/model_clause07.sql | 12 ++++++++++++ tests/model_clause08.sql | 12 ++++++++++++ tests/model_clause09.sql | 16 ++++++++++++++++ tests/model_clause10.sql | 17 +++++++++++++++++ tests/model_clause11.sql | 10 ++++++++++ tests/model_clause12.sql | 18 ++++++++++++++++++ tests/model_clause13.sql | 22 ++++++++++++++++++++++ tests/model_clause14.sql | 8 ++++++++ tests/numbers02.sql | 11 +++++++++++ tests/query_factoring12.sql | 2 ++ tests/query_factoring13.sql | 14 ++++++++++++++ tests/query_factoring14.sql | 14 ++++++++++++++ tests/set01.sql | 6 ++++++ tests/set02.sql | 2 ++ 17 files changed, 188 insertions(+) create mode 100644 tests/analytic_query10.sql create mode 100644 tests/datetime06.sql create mode 100644 tests/model_clause06.sql create mode 100644 tests/model_clause07.sql create mode 100644 tests/model_clause08.sql create mode 100644 tests/model_clause09.sql create mode 100644 tests/model_clause10.sql create mode 100644 tests/model_clause11.sql create mode 100644 tests/model_clause12.sql create mode 100644 tests/model_clause13.sql create mode 100644 tests/model_clause14.sql create mode 100644 tests/numbers02.sql create mode 100644 tests/query_factoring12.sql create mode 100644 tests/query_factoring13.sql create mode 100644 tests/query_factoring14.sql create mode 100644 tests/set01.sql create mode 100644 tests/set02.sql diff --git a/tests/analytic_query10.sql b/tests/analytic_query10.sql new file mode 100644 index 0000000..2fd86c3 --- /dev/null +++ b/tests/analytic_query10.sql @@ -0,0 +1,12 @@ +SELECT STALENESS, + OSIZE, OBJ#, + TYPE#, + ROW_NUMBER() OVER (PARTITION BY BO# ORDER BY STALENESS, OSIZE, OBJ#), + CASE WHEN ROW_NUMBER() OVER (PARTITION BY BO# ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 64 ELSE 0 END + + CASE WHEN ROW_NUMBER() OVER (PARTITION BY (SELECT TCP0.BO# FROM TABCOMPART$ TCP0 WHERE TCP0.OBJ#=ST0.BO#) ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 32 + ELSE 0 END AFLAGS, + 0 STATUS, + :B5 SID, + :B4 SERIAL#, PART#, BO#, LOC_STALE_PCT +FROM +A \ No newline at end of file diff --git a/tests/datetime06.sql b/tests/datetime06.sql new file mode 100644 index 0000000..c157eed --- /dev/null +++ b/tests/datetime06.sql @@ -0,0 +1 @@ +select * from dual where sysdate > date '2013-04-10' diff --git a/tests/model_clause06.sql b/tests/model_clause06.sql new file mode 100644 index 0000000..37f0d19 --- /dev/null +++ b/tests/model_clause06.sql @@ -0,0 +1,11 @@ +select + key , + dummy +from + t +where + key = 1 +model + dimension by ( key ) + measures ( ( select dummy from dual ) as dummy ) + rules ( ) diff --git a/tests/model_clause07.sql b/tests/model_clause07.sql new file mode 100644 index 0000000..36225b0 --- /dev/null +++ b/tests/model_clause07.sql @@ -0,0 +1,12 @@ +select + group_2 , + num_val , + m_1 +from + t +model unique single reference + dimension by ( group_2 ) + measures ( num_val, 0 as m_1 ) + rules ( m_1[any] = 10 ) +order by + group_2 diff --git a/tests/model_clause08.sql b/tests/model_clause08.sql new file mode 100644 index 0000000..9cb5a45 --- /dev/null +++ b/tests/model_clause08.sql @@ -0,0 +1,12 @@ +select + key , + num_val , + m_1 +from + t +model + dimension by ( key ) + measures ( num_val, 0 as m_1 ) + rules ( m_1[ num_val[1]/100 ] = 10 ) +order by + key diff --git a/tests/model_clause09.sql b/tests/model_clause09.sql new file mode 100644 index 0000000..202994b --- /dev/null +++ b/tests/model_clause09.sql @@ -0,0 +1,16 @@ +select + key , + num_val , + m_1 +from + t +model + dimension by ( key ) + measures ( num_val, 0 as m_1 ) + rules + ( m_1[ 1 ] = num_val[ 1 ] * 10 , -- literal + m_1[ 2 ] = num_val[ 1 + 1 ] * 100 , -- expression + m_1[ 3 ] = num_val[ key=3 ] * 1000 -- condition + ) +order by + key diff --git a/tests/model_clause10.sql b/tests/model_clause10.sql new file mode 100644 index 0000000..131bc16 --- /dev/null +++ b/tests/model_clause10.sql @@ -0,0 +1,17 @@ +select + key , + num_val , + m_1 +from + t +model + dimension by ( key ) + measures ( num_val, 0 as m_1 ) + rules + ( m_1[ 1 ] = num_val[ 1 ] * 10 , + m_1[ 2 ] = to_number( to_char( sysdate, 'YYYYMMDD' ) ), + m_1[ 3 ] = dbms_utility.get_time , + m_1[ 4 ] = :bind_var + ) +order by + key diff --git a/tests/model_clause11.sql b/tests/model_clause11.sql new file mode 100644 index 0000000..d1aa6dc --- /dev/null +++ b/tests/model_clause11.sql @@ -0,0 +1,10 @@ +select bio, rtrim (str_new, ';') new_str + from db_temp +model + partition by (rownum rn) +dimension by (0 dim) + measures (bio, bio || ';' str_new) + rules + iterate (1000) until (str_new[0] = previous (str_new[0])) + (str_new [0] = + regexp_replace (str_new[0], '(^|;)([^;]+;)(.*?;)?\2+', '\1\2\3')); diff --git a/tests/model_clause12.sql b/tests/model_clause12.sql new file mode 100644 index 0000000..544d500 --- /dev/null +++ b/tests/model_clause12.sql @@ -0,0 +1,18 @@ +select organisation, +level1, level2, level3, level4 from +( select 'org_name' as organisation, level as org_level, ename +from emp connect by prior empno = mgr +start with ename = 'king') +model +return updated rows +partition by +(organisation) +dimension by (rownum rn) +measures (lpad(' ',10) level1, +lpad(' ',10) level2, lpad(' ',10) level3, +lpad(' ',10) level4, org_level, ename) +rules update +( level1[any] = case when org_level[cv()] = 1 then ename [cv()] end, +level2[any] = case when org_level[cv()] = 2 then ename [cv()] end, +level3[any] = case when org_level[cv()] = 3 then ename [cv()] end, +level4[any] = case when org_level[cv()] = 4 then ename [cv()] end ) diff --git a/tests/model_clause13.sql b/tests/model_clause13.sql new file mode 100644 index 0000000..08d155c --- /dev/null +++ b/tests/model_clause13.sql @@ -0,0 +1,22 @@ +-- http://oracle101.blogspot.de/2008/08/oracle-model-clause.html +select organisation, +level1, nvl(level2,level1) as level2, nvl(level3,nvl(level2,level1)) as level3, +nvl(level4,nvl(level3,nvl(level2,level1))) as level4 from ( +select organisation, last_value(level1 ignore nulls) over (order by rownum) as +level1 , last_value(level2 ignore nulls) over (order by rownum) as level2 , +decode(level4,null,level3,last_value(level3 ignore nulls) over (order by +rownum)) as level3, level4 from ( select organisation, level1 ,level2,level3,level4 from ( select 'org_name' as organisation, level as +org_level, ename from emp connect by prior empno = mgr start with ename = 'king') +model +return updated rows +partition by (organisation) +dimension by (rownum rn) +measures (lpad(' ',10) level1, lpad(' ',10) +level2, lpad(' ',10) level3,lpad(' ',10) level4, org_level, ename) +rules +update +( level1[any] = case when org_level[cv()] = 1 then ename [cv()] end, +level2[any] = case when org_level[cv()] = 2 then ename [cv()] end, +level3[any] = case when org_level[cv()] = 3 then ename [cv()] end, +level4[any] = case when org_level[cv()] = 4 then ename [cv()] end +))) diff --git a/tests/model_clause14.sql b/tests/model_clause14.sql new file mode 100644 index 0000000..523c8a6 --- /dev/null +++ b/tests/model_clause14.sql @@ -0,0 +1,8 @@ +-- http://www.adp-gmbh.ch/ora/sql/model_clause/ex_generate_dates.html +select dt from (select trunc(sysdate) dt from dual) +model + dimension by (0 d) + measures (dt) + rules iterate(9) ( + dt[ iteration_number+1 ] = dt[ iteration_number ]+1 + ) diff --git a/tests/numbers02.sql b/tests/numbers02.sql new file mode 100644 index 0000000..0640581 --- /dev/null +++ b/tests/numbers02.sql @@ -0,0 +1,11 @@ +select 25 +, 1.-+.5 +, 1.+.5 +, 1.+.5D +, 1.+.5DM +, 1.D +, 1.M +, .5M +, .5DM +from dual + diff --git a/tests/query_factoring12.sql b/tests/query_factoring12.sql new file mode 100644 index 0000000..00bd06f --- /dev/null +++ b/tests/query_factoring12.sql @@ -0,0 +1,2 @@ +with days as (select (select trunc(sysdate, 'MONTH') from dual) + rownum -1 as d from dual connect by rownum < 31) +select d from days where (trunc(d) - trunc(d,'IW') +1 ) not in (6,7) and d <= last_day(sysdate) \ No newline at end of file diff --git a/tests/query_factoring13.sql b/tests/query_factoring13.sql new file mode 100644 index 0000000..068f9f6 --- /dev/null +++ b/tests/query_factoring13.sql @@ -0,0 +1,14 @@ +with dup_hiredate (eid, emp_last, mgr_id, reportlevel, hire_date, job_id) as ( + select employee_id, last_name, manager_id, 0 reportlevel, hire_date, job_id + from employees + where manager_id is null + union all + select e.employee_id, e.last_name, e.manager_id, + r.reportlevel+1 reportlevel, e.hire_date, e.job_id + from dup_hiredate r, employees e + where r.eid = e.manager_id) +search depth first by hire_date set order1 +cycle hire_date set is_cycle to 'y' default 'n' +select lpad(' ',2*reportlevel)||emp_last emp_name, eid, mgr_id, hire_date, job_id, is_cycle +from dup_hiredate +order by order1 diff --git a/tests/query_factoring14.sql b/tests/query_factoring14.sql new file mode 100644 index 0000000..ca646e1 --- /dev/null +++ b/tests/query_factoring14.sql @@ -0,0 +1,14 @@ +with emp_count (eid, emp_last, mgr_id, mgrlevel, salary, cnt_employees) as ( + select employee_id, last_name, manager_id, 0 mgrlevel, salary, 0 cnt_employees + from employees + union all + select e.employee_id, e.last_name, e.manager_id, r.mgrlevel+1 mgrlevel, e.salary, 1 + cnt_employees + from emp_count r, employees e + where e.employee_id = r.mgr_id) +search depth first by emp_last set order1 +select emp_last, eid, mgr_id, salary, sum(cnt_employees), max(mgrlevel) mgrlevel +from emp_count +group by emp_last, eid, mgr_id, salary +having max(mgrlevel) > 0 +order by mgr_id nulls first, emp_last diff --git a/tests/set01.sql b/tests/set01.sql new file mode 100644 index 0000000..b370b47 --- /dev/null +++ b/tests/set01.sql @@ -0,0 +1,6 @@ +select nt + , set(nt) as nt_set + from ( + select varchar2_ntt('a','b','c','c') as nt + from dual + ) \ No newline at end of file diff --git a/tests/set02.sql b/tests/set02.sql new file mode 100644 index 0000000..fee2c77 --- /dev/null +++ b/tests/set02.sql @@ -0,0 +1,2 @@ +select nt.column_value as distinct_element + from table(set(varchar2_ntt('a','b','c','c'))) nt \ No newline at end of file From 9371601ea5810d5221eba3fb18f32735c03fc9f0 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 20 Aug 2013 12:53:42 +0200 Subject: [PATCH 27/43] Model test added --- tests/model_clause15.sql | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/model_clause15.sql diff --git a/tests/model_clause15.sql b/tests/model_clause15.sql new file mode 100644 index 0000000..7357a87 --- /dev/null +++ b/tests/model_clause15.sql @@ -0,0 +1,21 @@ +-- http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8912311513313 +select + name, to_char(dt,'DD-MM-YYYY') dt, amt, cum_amt + from ( + select name, trunc(dt,'MM') dt, sum(amt) amt + from c + group by name, trunc(dt,'MM') + ) + model + partition by (name) + dimension by (dt) + measures(amt, cast(null as number) cum_amt) + ignore nav + rules sequential order( + amt[for dt from to_date('01-01-2002','DD-MM-YYYY') + to to_date('01-12-2002','DD-MM-YYYY') + increment numtoyminterval(1,'MONTH') ] = amt[cv(dt)], + cum_amt[any] = sum(amt)[dt <= cv(dt)] + ) + order by name, dt + From a9fb689b914344251d4550ef7a1ebdebf43d741b Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 27 Aug 2013 12:53:57 +0200 Subject: [PATCH 28/43] model test --- tests/model_clause16.sql | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/model_clause16.sql diff --git a/tests/model_clause16.sql b/tests/model_clause16.sql new file mode 100644 index 0000000..01b5dd1 --- /dev/null +++ b/tests/model_clause16.sql @@ -0,0 +1,30 @@ +select a, b, d, c, dt, p, pp, tech_pp, tech_p +from +( +select a, b, d, c, dt, p, pp, odr from ( +select spf.*, nvl(a, ddr_a) as a, b, d, + rank() over + ( + partition by nvl(a, d_a), c, b, dt + order by inp, spf.rowid asc + ) as odr + from t_pp spf + join t_a sa on (spf.a_id = sa.a_id) + where spf.dt between to_date('2001-01-01', 'RRRR-MM.DD') and to_date('2001-01-31', 'RRRR-MM-DD') +) + where odr = 1 + and c = '1234' +) + model + partition by (a, b, d, c) + dimension by (dt) + measures(pp, cast(null as number) tech_pp, p, cast(null as number) tech_p) + --ignore nav + rules sequential order( + tech_pp[ for dt from to_date('2001-01-01','RRRR-MM-DD') to to_date('2001-01-31','RRRR-MM-DD') + increment numtodsinterval(1,'DAY')] = nvl(pp[cv(dt)], tech_pp[cv(dt)-1]) + , + tech_p[ for dt from to_date('2001-01-01','RRRR-MM-DD') to to_date('2001-01-31','RRRR-MM-DD') + increment numtodsinterval(1,'DAY')] = nvl(p[cv(dt)], tech_p[cv(dt)-1]) + ) + From 36f132d5e041b1198671c5616722fac5a246c9dd Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Fri, 27 Sep 2013 15:29:00 +0200 Subject: [PATCH 29/43] various insert statements --- tests/insert01.sql | 6 ++++++ tests/insert02.sql | 2 ++ tests/insert03.sql | 15 +++++++++++++++ tests/insert04.sql | 6 ++++++ tests/insert05.sql | 9 +++++++++ tests/insert06.sql | 14 ++++++++++++++ tests/insert07.sql | 12 ++++++++++++ tests/insert08.sql | 6 ++++++ tests/insert09.sql | 5 +++++ tests/insert10.sql | 5 +++++ tests/insert11.sql | 6 ++++++ tests/insert12.sql | 6 ++++++ 12 files changed, 92 insertions(+) create mode 100644 tests/insert01.sql create mode 100644 tests/insert02.sql create mode 100644 tests/insert03.sql create mode 100644 tests/insert04.sql create mode 100644 tests/insert05.sql create mode 100644 tests/insert06.sql create mode 100644 tests/insert07.sql create mode 100644 tests/insert08.sql create mode 100644 tests/insert09.sql create mode 100644 tests/insert10.sql create mode 100644 tests/insert11.sql create mode 100644 tests/insert12.sql diff --git a/tests/insert01.sql b/tests/insert01.sql new file mode 100644 index 0000000..fa035f9 --- /dev/null +++ b/tests/insert01.sql @@ -0,0 +1,6 @@ +insert + when mod( object_id, 2 ) = 1 then + into t1 ( x, y ) values ( s.nextval, object_id ) + when mod( object_id, 2 ) = 0 then + into t2 ( x, y ) values ( s.nextval, created ) +select object_id, created from all_objects diff --git a/tests/insert02.sql b/tests/insert02.sql new file mode 100644 index 0000000..7c561e5 --- /dev/null +++ b/tests/insert02.sql @@ -0,0 +1,2 @@ +-- insert pl/sql recond +insert into t values trec diff --git a/tests/insert03.sql b/tests/insert03.sql new file mode 100644 index 0000000..6f6d626 --- /dev/null +++ b/tests/insert03.sql @@ -0,0 +1,15 @@ +-- insert when +insert +when (deptno=10) then + into emp_10 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +when (deptno=20) then + into emp_20 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +when (deptno=30) then + into emp_30 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +else + into leftover (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +select * from emp diff --git a/tests/insert04.sql b/tests/insert04.sql new file mode 100644 index 0000000..001a9eb --- /dev/null +++ b/tests/insert04.sql @@ -0,0 +1,6 @@ +-- insert all +insert all +into ap_cust values (customer_id, program_id, delivered_date) +into ap_orders values (order_date, program_id) +select program_id, delivered_date, customer_id, order_date +from airplanes diff --git a/tests/insert05.sql b/tests/insert05.sql new file mode 100644 index 0000000..2c136e3 --- /dev/null +++ b/tests/insert05.sql @@ -0,0 +1,9 @@ +-- insert all +insert all +into t (pid, fname, lname) +values (1, 'dan', 'morgan') +into t (pid, fname, lname) +values (2, 'jeremiah', 'wilton') +into t (pid, fname, lname) +values (3, 'helen', 'lofstrom') +select * from dual diff --git a/tests/insert06.sql b/tests/insert06.sql new file mode 100644 index 0000000..e42048f --- /dev/null +++ b/tests/insert06.sql @@ -0,0 +1,14 @@ +insert all +when (deptno=10) then + into emp_10 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +when (deptno=20) then + into emp_20 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +when (deptno<=30) then + into emp_30 (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +else + into leftover (empno,ename,job,mgr,sal,deptno) + values (empno,ename,job,mgr,sal,deptno) +select * from emp diff --git a/tests/insert07.sql b/tests/insert07.sql new file mode 100644 index 0000000..3b7f5af --- /dev/null +++ b/tests/insert07.sql @@ -0,0 +1,12 @@ +insert first +when customer_id < 'i' then + into cust_ah + values (customer_id, program_id, delivered_date) +when customer_id < 'q' then + into cust_ip + values (customer_id, program_id, delivered_date) +when customer_id > 'pzzz' then + into cust_qz + values (customer_id, program_id, delivered_date) +select program_id, delivered_date, customer_id, order_date +from airplanes diff --git a/tests/insert08.sql b/tests/insert08.sql new file mode 100644 index 0000000..01cc8ac --- /dev/null +++ b/tests/insert08.sql @@ -0,0 +1,6 @@ +-- without check option +insert into ( +select deptno, dname, loc +from dept +where deptno < 30) +values (98, 'travel', 'seattle') diff --git a/tests/insert09.sql b/tests/insert09.sql new file mode 100644 index 0000000..c8e2035 --- /dev/null +++ b/tests/insert09.sql @@ -0,0 +1,5 @@ +insert into ( +select deptno, dname, loc +from dept +where deptno < 30 with check option) +values (99, 'travel', 'seattle') diff --git a/tests/insert10.sql b/tests/insert10.sql new file mode 100644 index 0000000..ff5fb5b --- /dev/null +++ b/tests/insert10.sql @@ -0,0 +1,5 @@ +insert into ( + select empno, ename, job, sal, deptno + from emp) + values + (1, 'morgan', 'dba', '1', 40) diff --git a/tests/insert11.sql b/tests/insert11.sql new file mode 100644 index 0000000..0e3047d --- /dev/null +++ b/tests/insert11.sql @@ -0,0 +1,6 @@ + insert into emp + (empno, ename) + values + (seq_emp.nextval, 'morgan') + returning empno + into x diff --git a/tests/insert12.sql b/tests/insert12.sql new file mode 100644 index 0000000..afdff6d --- /dev/null +++ b/tests/insert12.sql @@ -0,0 +1,6 @@ + insert into emp + (empno, ename) + values + (seq_emp.nextval, 'morgan') + returning rowid + into r From c48c9f410be25588a147392f503b69b156a2b564 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 12 Nov 2013 14:21:22 +0100 Subject: [PATCH 30/43] connect by ... order by siblings ... --- tests/connect_by07.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/connect_by07.sql diff --git a/tests/connect_by07.sql b/tests/connect_by07.sql new file mode 100644 index 0000000..382ff58 --- /dev/null +++ b/tests/connect_by07.sql @@ -0,0 +1,5 @@ +select t.*, connect_by_root id +from test t +start with t.id = 1 +connect by prior t.id = t.parent_id +order siblings by t.some_text From 374900d638f3b7ad7d2dd57bda2f81f9ddd48606 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Wed, 30 Jul 2014 01:50:10 +0200 Subject: [PATCH 31/43] pivot_in_clause - segfault fix --- parsers/PLSQL_DMLParser.g | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 4463094..ea4ab2b 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -383,7 +383,7 @@ pivot_in_clause : in_key LEFT_PAREN ( (select_key)=> subquery {mode = 1;} - | (any_key)=> any_key (COMMA any_key)* {mode = 1;} + | (any_key)=> any_key (COMMA any_key)* {mode = 2;} | pivot_in_clause_element (COMMA pivot_in_clause_element)* ) RIGHT_PAREN From 9e22b72e46f5a5b0b25a0ab58b4f5e1350f2a817 Mon Sep 17 00:00:00 2001 From: ibre5041 Date: Wed, 30 Jul 2014 11:42:55 +0200 Subject: [PATCH 32/43] fix unpivot_in_elements - as is mandatory --- parsers/PLSQL_DMLParser.g | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index ea4ab2b..9d95d8c 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -427,7 +427,7 @@ unpivot_in_elements : ( column_name | LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN ) - ( as_key? + ( as_key ( constant | (LEFT_PAREN)=> LEFT_PAREN constant (COMMA constant)* RIGHT_PAREN ) From ce77729108c8ab2a04572a10af7129ef53825b6e Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Sat, 2 Aug 2014 00:18:47 +0200 Subject: [PATCH 33/43] avoid warning "Semantic predicates were present but were hidden by actions" --- parsers/PLSQL_DMLParser.g | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 9d95d8c..5962d2f 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -593,10 +593,10 @@ update_statement // ${mode == 1}? ^(set_key column_based_update_set_clause+) -> ^(set_key ^(value_key id ^(EXPR expression))) From 6825cbacdf5f05839665d77836698388d0db6f38 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Sat, 2 Aug 2014 12:03:50 +0200 Subject: [PATCH 34/43] align AST version with non-AST version --- parsers/PLSQL_DMLParser.g | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 5962d2f..688f4fe 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -877,7 +877,7 @@ equality_expression -> {isNegated}? ^(IS_NOT_OF_TYPE $equality_expression type_spec+) -> ^(IS_OF_TYPE $equality_expression type_spec+) ) - )* + )? ; From 50d96a706037e21844d228e06a61570536ec3c00 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Sun, 3 Aug 2014 23:44:12 +0200 Subject: [PATCH 35/43] Fix for analytic functions - sync with not-AST version --- parsers/PLSQL_DMLParser.g | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 688f4fe..b37501a 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -1120,8 +1120,8 @@ quantified_expression ; standard_function - : stantard_function_enabling_over^ function_argument over_clause? - | stantard_function_enabling_using^ function_argument using_clause? + : stantard_function_enabling_over^ function_argument_analytic over_clause? + | stantard_function_enabling_using^ function_argument_modeling using_clause? | count_key^ LEFT_PAREN! ( ASTERISK | (distinct_key|unique_key|all_key)? concatenation_wrapper ) @@ -1151,12 +1151,7 @@ standard_function LEFT_PAREN! REGULAR_ID from_key! concatenation_wrapper RIGHT_PAREN! - | (first_value_key^|last_value_key^) - LEFT_PAREN! - concatenation_wrapper (ignore_key! nulls_key)? - RIGHT_PAREN! over_clause - | (first_value_key^|last_value_key^) - function_argument_analytic + | (first_value_key^|last_value_key^) function_argument_analytic respect_or_ignore_nulls? over_clause | stantard_function_pedictions^ LEFT_PAREN! From 5e1a793e9854dbb5c586705fe0c8fde4023cb57f Mon Sep 17 00:00:00 2001 From: ibre5041 Date: Wed, 6 Aug 2014 12:50:24 +0200 Subject: [PATCH 36/43] Fix for the test insert02.sql (insert pl/sql record into table) insert into i values trec; --- parsers/PLSQL_DMLParser.g | 2 +- parsers/TestPLSQL_DML.testsuite | 12 ++++++++++++ parsers/no-ast/PLSQL_DMLParser.g | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index b37501a..6dc0818 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -669,7 +669,7 @@ insert_into_clause ; values_clause - : values_key^ expression_list + : values_key^ (expression_list | record_name) ; // $> diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index 3cb09d6..94e001a 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -571,6 +571,18 @@ insert_statement: into large_orders values(oid, ottl, sid, cid) select o.* from orders o>> OK +insert01.sql OK +insert02.sql OK +insert03.sql OK +insert04.sql OK +insert05.sql OK +insert06.sql OK +insert07.sql OK +insert08.sql OK +insert09.sql OK +insert10.sql OK +insert11.sql OK +insert12.sql OK delete_statement: < From 0b1fb2559cfa3bd95219a2c2a49f937b13252b70 Mon Sep 17 00:00:00 2001 From: ibre5041 Date: Wed, 6 Aug 2014 14:35:58 +0200 Subject: [PATCH 37/43] Fix for modeling clause - model can also be followed by "unique" and "return" - rules clause can be empty --- parsers/PLSQLLexer.g | 17 +++++++++++------ parsers/PLSQL_DMLParser.g | 8 ++++---- parsers/TestPLSQL_DML.testsuite | 11 +++++++++++ parsers/no-ast/PLSQL_DMLParser.g | 4 ++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/parsers/PLSQLLexer.g b/parsers/PLSQLLexer.g index a700b3f..8a8b8a2 100644 --- a/parsers/PLSQLLexer.g +++ b/parsers/PLSQLLexer.g @@ -546,7 +546,7 @@ SQL92_RESERVED_EXCEPTION advanceInput(); $type = Token.INVALID_TOKEN_TYPE; - int markModel = input.mark(); + int markException = input.mark(); // Now loop over next Tokens in the input and eventually set Token's type to REGULAR_ID @@ -554,7 +554,7 @@ SQL92_RESERVED_EXCEPTION // nextToken either returns NULL => then the next token is put into the queue tokenBuffer // or it returns Token.EOF, then nothing is put into the queue Token t1 = super.nextToken(); - { // This "if" handles the situation when the "model" is the last text in the input. + { // This "if" handles the situation when the "exception" is the last text in the input. if( t1 != null && t1.getType() == Token.EOF) { $e.setType(REGULAR_ID); @@ -584,7 +584,7 @@ SQL92_RESERVED_EXCEPTION } // while true } // else if( t1 != null && t1.getType() == Token.EOF) } - input.rewind(markModel); + input.rewind(markException); } ; @@ -835,7 +835,7 @@ PLSQL_NON_RESERVED_USING PLSQL_NON_RESERVED_MODEL : m='model' { - // "model" is a keyword if and only if it is followed by ("main"|"partition"|"dimension") + // "model" is a keyword if and only if it is followed by ("main"|"partition"|"dimension"|"unique"|"return") // otherwise it is a identifier(REGULAR_ID). // This wodoo implements something like context sensitive lexer. // Here we've matched the word "model". Then the Token is created and en-queued in tokenBuffer @@ -872,10 +872,15 @@ PLSQL_NON_RESERVED_MODEL t1 = super.nextToken(); if( t1 == null) { t1 = tokenBuffer.pollLast(); }; continue; } - - if( t1.getType() != REGULAR_ID || // is something other than ("main"|"partition"|"dimension") + + if( t1.getType() == SQL92_RESERVED_UNIQUE) + { + break; + } + if( t1.getType() != REGULAR_ID || // is something other than ("main"|"partition"|"dimension"|"return") ( !t1.getText().equalsIgnoreCase("main") && !t1.getText().equalsIgnoreCase("partition") && + !t1.getText().equalsIgnoreCase("return") && !t1.getText().equalsIgnoreCase("dimension") )) { diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 6dc0818..21e843f 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -522,13 +522,13 @@ model_column_list ; model_column - : expression table_alias? - -> ^(MODEL_COLUMN table_alias? ^(EXPR expression)) + : expression column_alias? + -> ^(MODEL_COLUMN column_alias? ^(EXPR expression)) ; model_rules_clause - : model_rules_part? LEFT_PAREN model_rules_element (COMMA model_rules_element)* RIGHT_PAREN - -> ^(MODEL_RULES model_rules_element+ model_rules_part?) + : model_rules_part? LEFT_PAREN (model_rules_element (COMMA model_rules_element)*)? RIGHT_PAREN + -> ^(MODEL_RULES model_rules_element* model_rules_part?) ; model_rules_part diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index 94e001a..3a4d275 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -151,6 +151,17 @@ model_clause02.sql OK model_clause03.sql OK model_clause04.sql OK model_clause05.sql OK +model_clause06.sql OK +model_clause07.sql OK +model_clause08.sql OK +model_clause09.sql OK +model_clause10.sql OK +model_clause11.sql OK +model_clause12.sql OK +model_clause13.sql OK +model_clause14.sql OK +model_clause15.sql OK +model_clause16.sql OK union01.sql OK union02.sql OK union03.sql OK diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index dbe3cd2..a6b34c1 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -404,11 +404,11 @@ model_column_list ; model_column - : expression table_alias? + : expression column_alias? ; model_rules_clause - : model_rules_part? LEFT_PAREN model_rules_element (COMMA model_rules_element)* RIGHT_PAREN + : model_rules_part? LEFT_PAREN (model_rules_element (COMMA model_rules_element)*)? RIGHT_PAREN ; model_rules_part From cfe43371bcf7ee5d07a7087ebb58bc93a8f554c6 Mon Sep 17 00:00:00 2001 From: ibre5041 Date: Thu, 14 Aug 2014 19:09:35 +0200 Subject: [PATCH 38/43] Fixes for group by clause - group by set migth be empty: select 1 from t group by () - having clause might be present even if there is no "GROUP" "BY" select 1 from t where 1=0 having 1=1 Plus this patch changes list of child nodes in select_statement (from_clause is no more the 1st child) but it respects the order of clauses in select statement --- parsers/PLSQL_DMLParser.g | 26 ++++++++++++++++++-------- parsers/TestPLSQL_DML.testsuite | 20 ++++++++++++++++++++ parsers/no-ast/PLSQL_DMLParser.g | 15 ++++++++++----- tests/groupby24.sql | 5 +++++ tests/groupby25.sql | 1 + tests/groupby26.sql | 1 + tests/groupby27.sql | 1 + 7 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 tests/groupby24.sql create mode 100644 tests/groupby25.sql create mode 100644 tests/groupby26.sql create mode 100644 tests/groupby27.sql diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index 21e843f..bcc450b 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -45,6 +45,7 @@ tokens { PIVOT_IN_ELEMENT; UNPIVOT_IN_ELEMENT; HIERARCHICAL; + GROUP_BY_CLAUSE; GROUP_BY_ELEMENT; GROUPIN_SET; MAIN_MODEL; @@ -267,10 +268,10 @@ query_block hierarchical_query_clause? group_by_clause? model_clause? - -> {mode == 1}? ^(select_key from_clause distinct_key? unique_key? all_key? ASTERISK - into_clause? where_clause? hierarchical_query_clause? group_by_clause? model_clause?) - -> ^(select_key from_clause distinct_key? unique_key? all_key? ^(SELECT_LIST selected_element+) - into_clause? where_clause? hierarchical_query_clause? group_by_clause? model_clause?) + -> {mode == 1}? ^(select_key distinct_key? unique_key? all_key? ASTERISK + into_clause? from_clause where_clause? hierarchical_query_clause? group_by_clause? model_clause?) + -> ^(select_key distinct_key? unique_key? all_key? ^(SELECT_LIST selected_element+) + into_clause? from_clause where_clause? hierarchical_query_clause? group_by_clause? model_clause?) ; selected_element @@ -448,10 +449,19 @@ start_part ; group_by_clause - : (group_key) => group_key by_key group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* having_clause? - -> ^(group_key ^(GROUP_BY_ELEMENT group_by_elements)+ having_clause?) - | (having_key) => having_clause (group_key by_key group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)*)? - -> ^(group_key having_clause ^(GROUP_BY_ELEMENT group_by_elements)+) + : (group_key) => group_key by_key + (LEFT_PAREN RIGHT_PAREN + | group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* + ) + having_clause? + -> ^(GROUP_BY_CLAUSE[$group_key.start] ^(group_key ^(GROUP_BY_ELEMENT group_by_elements)*) having_clause?) + | (having_key) => having_clause + (group_key by_key + (LEFT_PAREN RIGHT_PAREN + | group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* + ) + )? + -> ^(GROUP_BY_CLAUSE[$having_key.start] having_clause ^(group_key ^(GROUP_BY_ELEMENT group_by_elements)*)?) ; group_by_elements diff --git a/parsers/TestPLSQL_DML.testsuite b/parsers/TestPLSQL_DML.testsuite index 3a4d275..2e11f28 100644 --- a/parsers/TestPLSQL_DML.testsuite +++ b/parsers/TestPLSQL_DML.testsuite @@ -184,6 +184,26 @@ groupby04.sql OK groupby05.sql OK groupby06.sql OK groupby07.sql OK +groupby08.sql OK +groupby09.sql OK +groupby10.sql OK +groupby11.sql OK +groupby12.sql OK +groupby13.sql OK +groupby14.sql OK +groupby15.sql OK +groupby16.sql OK +groupby17.sql OK +groupby18.sql OK +groupby19.sql OK +groupby20.sql OK +groupby21.sql OK +groupby22.sql OK +groupby23.sql OK +groupby24.sql OK +groupby25.sql OK +groupby26.sql OK +groupby27.sql OK order_by01.sql OK order_by02.sql OK order_by03.sql OK diff --git a/parsers/no-ast/PLSQL_DMLParser.g b/parsers/no-ast/PLSQL_DMLParser.g index a6b34c1..fee30b2 100644 --- a/parsers/no-ast/PLSQL_DMLParser.g +++ b/parsers/no-ast/PLSQL_DMLParser.g @@ -334,12 +334,17 @@ start_part ; group_by_clause - : (group_key) => group_key by_key group_by_elements - ((COMMA group_by_elements)=> COMMA group_by_elements)* - having_clause? + : (group_key) => group_key by_key + (LEFT_PAREN RIGHT_PAREN + | group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* + ) + having_clause? | (having_key) => having_clause - (group_key by_key group_by_elements - ((COMMA group_by_elements)=> COMMA group_by_elements)*)? + (group_key by_key + (LEFT_PAREN RIGHT_PAREN + | group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* + ) + )? ; group_by_elements diff --git a/tests/groupby24.sql b/tests/groupby24.sql new file mode 100644 index 0000000..facb478 --- /dev/null +++ b/tests/groupby24.sql @@ -0,0 +1,5 @@ +-- having clause without explicit group by +-- If TE does not immediately contain a group by clause, then “GROUP BY ()” is implicit. +select max(empid), min(marks) +from employee +having max(empid_id)>100 diff --git a/tests/groupby25.sql b/tests/groupby25.sql new file mode 100644 index 0000000..512c770 --- /dev/null +++ b/tests/groupby25.sql @@ -0,0 +1 @@ +select 1 from r group by () having 1=1 diff --git a/tests/groupby26.sql b/tests/groupby26.sql new file mode 100644 index 0000000..8383328 --- /dev/null +++ b/tests/groupby26.sql @@ -0,0 +1 @@ +select 1 as t from tmp where 1=0 having 1=1 diff --git a/tests/groupby27.sql b/tests/groupby27.sql new file mode 100644 index 0000000..c32ec79 --- /dev/null +++ b/tests/groupby27.sql @@ -0,0 +1 @@ +select count(1), max(n1) from t8 group by n1+1, n2+2 From 88476f6bc1014ff7fcc91f458e8f94b35e846d87 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Sat, 27 Sep 2014 03:07:40 +0200 Subject: [PATCH 39/43] 11g triger body --- tests/trigger01.sql | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/trigger01.sql diff --git a/tests/trigger01.sql b/tests/trigger01.sql new file mode 100644 index 0000000..ff86e68 --- /dev/null +++ b/tests/trigger01.sql @@ -0,0 +1,44 @@ +CREATE OR REPLACE TRIGGER employees_update + FOR UPDATE ON employees + COMPOUND TRIGGER + + TYPE employeeNumberRec IS RECORD + (oldEmployeeNumber employees.employeeNumber%TYPE + ,newEmployeeNumber employees.employeeNumber%TYPE); + TYPE employeeNumbersTbl IS TABLE OF employeeNumberRec; + g_employeeNumbers employeeNumbersTbl; + +BEFORE STATEMENT +IS +BEGIN + -- Reset the internal employees table + g_employeeNumbers := employeeNumbersTbl(); +END BEFORE STATEMENT; + +AFTER EACH ROW +IS +BEGIN + -- Store the updated employees + IF :new.employeeNumber <> :old.employeeNumber THEN + g_employeeNumbers.EXTEND; + g_employeeNumbers(g_employeeNumbers.LAST).oldEmployeeNumber := :old.employeeNumber; + g_employeeNumbers(g_employeeNumbers.LAST).newEmployeeNumber := :new.employeeNumber; + END IF; +END AFTER EACH ROW; + +AFTER STATEMENT +IS +BEGIN + -- Now update the child tables + FORALL l_index IN 1..g_employeeNumbers.COUNT + UPDATE employees + SET assignTo = g_employeeNumbers(l_index).newEmployeeNumber + WHERE assignTo = g_employeeNumbers(l_index).oldEmployeeNumber; + FORALL l_index IN 1..g_employeeNumbers.COUNT + UPDATE customers + SET salesRepEmployeeNumber = g_employeeNumbers(l_index).newEmployeeNumber + WHERE salesRepEmployeeNumber = g_employeeNumbers(l_index).oldEmployeeNumber; +END AFTER STATEMENT; + +END; + From 604ed48b350616120e0bd85441775cd4fbe694f7 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Tue, 23 Dec 2014 23:39:28 +0100 Subject: [PATCH 40/43] block must start either with DECLARE or BEGIN --- parsers/PLSQLParser.g | 2 +- parsers/no-ast/PLSQLParser.g | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parsers/PLSQLParser.g b/parsers/PLSQLParser.g index 6e1bfd0..5bcdd3b 100644 --- a/parsers/PLSQLParser.g +++ b/parsers/PLSQLParser.g @@ -1246,7 +1246,7 @@ exception_handler // $> block - : (declare_key? declare_spec+)? + : (declare_key declare_spec+)? body -> ^(BLOCK declare_spec* body) ; diff --git a/parsers/no-ast/PLSQLParser.g b/parsers/no-ast/PLSQLParser.g index cbaf2a5..52c67f8 100644 --- a/parsers/no-ast/PLSQLParser.g +++ b/parsers/no-ast/PLSQLParser.g @@ -965,7 +965,7 @@ trigger_block ; block - : declare_key? declare_spec+ + : (declare_key declare_spec+)? body ; From 6a08b05c9d43674948c36e9b8d4e03c069074752 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Wed, 24 Dec 2014 11:02:30 +0100 Subject: [PATCH 41/43] compilation fix for AST grammar --- parsers/PLSQL_DMLParser.g | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsers/PLSQL_DMLParser.g b/parsers/PLSQL_DMLParser.g index bcc450b..8bfe87a 100644 --- a/parsers/PLSQL_DMLParser.g +++ b/parsers/PLSQL_DMLParser.g @@ -461,7 +461,7 @@ group_by_clause | group_by_elements ((COMMA group_by_elements)=> COMMA group_by_elements)* ) )? - -> ^(GROUP_BY_CLAUSE[$having_key.start] having_clause ^(group_key ^(GROUP_BY_ELEMENT group_by_elements)*)?) + -> ^(GROUP_BY_CLAUSE[$having_clause.start] having_clause ^(group_key ^(GROUP_BY_ELEMENT group_by_elements)*)?) ; group_by_elements From 31c1eef9654c21f2031a110724526ec37fd7e0ac Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 25 Jun 2018 20:40:44 +0200 Subject: [PATCH 42/43] 12c features --- tests/crossapply01.sql | 7 +++++++ tests/crossapply02.sql | 4 ++++ tests/crossapply03.sql | 7 +++++++ tests/crossapply04.sql | 4 ++++ tests/lateral01.sql | 6 ++++++ 5 files changed, 28 insertions(+) create mode 100644 tests/crossapply01.sql create mode 100644 tests/crossapply02.sql create mode 100644 tests/crossapply03.sql create mode 100644 tests/crossapply04.sql create mode 100644 tests/lateral01.sql diff --git a/tests/crossapply01.sql b/tests/crossapply01.sql new file mode 100644 index 0000000..9171108 --- /dev/null +++ b/tests/crossapply01.sql @@ -0,0 +1,7 @@ +SELECT department_name, employee_id, employee_name +FROM departments d +CROSS APPLY (SELECT employee_id, employee_name +FROM employees e +WHERE salary >= 2000 +AND e.department_id = d.department_id) +ORDER BY 1, 2, 3 diff --git a/tests/crossapply02.sql b/tests/crossapply02.sql new file mode 100644 index 0000000..1f3cb77 --- /dev/null +++ b/tests/crossapply02.sql @@ -0,0 +1,4 @@ +SELECT department_name, b.* +FROM departments d +CROSS APPLY (TABLE(get_tab(d.department_id))) b +ORDER BY 1, 2 diff --git a/tests/crossapply03.sql b/tests/crossapply03.sql new file mode 100644 index 0000000..74df747 --- /dev/null +++ b/tests/crossapply03.sql @@ -0,0 +1,7 @@ +SELECT department_name, employee_id, employee_name +FROM departments d +OUTER APPLY (SELECT employee_id, employee_name +FROM employees e +WHERE salary >= 2000 +AND e.department_id = d.department_id) +ORDER BY 1, 2, 3 diff --git a/tests/crossapply04.sql b/tests/crossapply04.sql new file mode 100644 index 0000000..ecaefb5 --- /dev/null +++ b/tests/crossapply04.sql @@ -0,0 +1,4 @@ +SELECT department_name, b.* +FROM departments d +OUTER APPLY (TABLE(get_tab(d.department_id))) b +ORDER BY 1, 2 diff --git a/tests/lateral01.sql b/tests/lateral01.sql new file mode 100644 index 0000000..c2ad362 --- /dev/null +++ b/tests/lateral01.sql @@ -0,0 +1,6 @@ +SELECT department_name, employee_name +FROM departments d, +LATERAL (SELECT employee_name +FROM employees e +WHERE e.department_id = d.department_id) +ORDER BY 1, 2 From bc49fd437e24febbab1d6232aee0e82bbda5c1a1 Mon Sep 17 00:00:00 2001 From: Ivan Brezina Date: Mon, 25 Jun 2018 20:41:53 +0200 Subject: [PATCH 43/43] some more tests --- tests/merge05.sql | 13 +++++++++++++ tests/union14.sql | 14 ++++++++++++++ tests/xmltable03.sql | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 tests/merge05.sql create mode 100644 tests/union14.sql create mode 100644 tests/xmltable03.sql diff --git a/tests/merge05.sql b/tests/merge05.sql new file mode 100644 index 0000000..1a53180 --- /dev/null +++ b/tests/merge05.sql @@ -0,0 +1,13 @@ +MERGE +/*+ dynamic_sampling(ST 4) dynamic_sampling_est_cdn(ST) */ +INTO STATS_TARGET$ ST +USING +( +SELECT STALENESS, OSIZE, OBJ#, TYPE#, CASE WHEN STALENESS > .5 THEN 128 ELSE 0 END + AFLAGS AFLAGS, STATUS, SID, SERIAL#, PART#, BO# FROM ( SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(T.FLAGS,16), 16, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(T.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(T.ROWCNT, (T.ROWCNT + M.INSERTS - M.DELETES)))) / (T.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, CASE WHEN T.FILE# = 0 THEN DBMS_STATS_INTERNAL.GET_TABLE_BLOCK_COUNT(U.NAME, O.NAME, NULL, NULL) WHEN S.TYPE# = 5 THEN DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(T.TS#, T.FILE#, T.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), O.DATAOBJ#, S.BLOCKS) ELSE NULL END * NVL(TS.BLOCKSIZE, :B4 ) OSIZE, O.OBJ# OBJ#, O.TYPE# TYPE#, 32 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, NULL PART#, NULL BO# FROM SYS.SEG$ S, SYS.TS$ TS, SYS.USER$ U, SYS.OBJ$ O, SYS.TAB$ T, SYS.MON_MODS_ALL$ M WHERE :B1 IS NOT NULL AND O.TYPE# = 2 AND T.OBJ# = O.OBJ# AND O.OWNER# = U.USER# AND M.OBJ#(+) = T.OBJ# AND T.FILE# = S.FILE#(+) AND T.BLOCK# = S.BLOCK#(+) AND T.TS# = S.TS#(+) AND TS.TS#(+) = S.TS# AND BITAND(T.TRIGFLAG,67108864) != 67108864 AND BITAND(T.PROPERTY,64+512) = 0 AND BITAND(T.FLAGS,536870912) != 536870912 AND BITAND(T.FLAGS,2097152) != 2097152 AND BITAND(O.FLAGS, 128) != 128 AND BITAND(T.PROPERTY,2147483648) = 0 AND (BITAND(T.PROPERTY,4194304) != 4194304 AND BITAND(T.PROPERTY,8388608) != 8388608) AND NOT (BITAND(O.FLAGS, 16) = 16 AND (O.NAME LIKE 'DR$%' OR O.NAME LIKE 'DR#%')) AND NOT (U.NAME = 'SYS' AND O.NAME = 'SUMDELTA$') AND (U.NAME,O.NAME) NOT IN (SELECT /*+ unnest */ * FROM (SELECT MOWNER,LOG FROM MLOG$ UNION ALL SELECT MOWNER,TEMP_LOG FROM MLOG$ WHERE TEMP_LOG IS NOT NULL)) AND ((BITAND(T.FLAGS,16) = 16 AND ((BITAND(M.FLAGS,5) != 0) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * T.ROWCNT)))) OR (BITAND(T.FLAGS,16) != 16)) UNION ALL SELECT STALENESS, OSIZE, OBJ#, TYPE#, CASE WHEN ROW_NUMBER() OVER (PARTITION BY BO# ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 32 ELSE 0 END + 64 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, PART#, BO# FROM ( SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(T.FLAGS,2), 2, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(T.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(T.ROWCNT, (T.ROWCNT + M.INSERTS - M.DELETES)))) / (T.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(T.TS#, T.FILE#, T.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), O.DATAOBJ#, S.BLOCKS) * TS.BLOCKSIZE OSIZE, O.OBJ# OBJ#, O.TYPE# TYPE#, T.PART# PART#, T.BO# BO# FROM SYS.SEG$ S, SYS.TS$ TS, SYS.OBJ$ O, SYS.TABPART$ T, SYS.TAB$ TAB, SYS.OBJ$ OT, SYS.MON_MODS_ALL$ M WHERE O.TYPE# = 19 AND S.TYPE# = 5 AND T.OBJ# = O.OBJ# AND TAB.OBJ# = T.BO# AND M.OBJ#(+) = T.OBJ# AND T.FILE# = S.FILE# AND T.BLOCK# = S.BLOCK# AND T.TS# = S.TS# AND TS.TS# = S.TS# AND BITAND(TAB.TRIGFLAG,67108864) != 67108864 AND BITAND(TAB.PROPERTY,512) != 512 AND BITAND(TAB.FLAGS,536870912) != 536870912 AND BITAND(T.FLAGS,2097152) != 2097152 AND BITAND(T.FLAGS, 32) != 32 AND TAB.OBJ# = OT.OBJ# AND BITAND(OT.FLAGS,128) != 128 AND NOT (BITAND(O.FLAGS, 16) = 16 AND (O.NAME LIKE 'DR$%' OR O.NAME LIKE 'DR#%')) AND ((BITAND(T.FLAGS,2) = 2 AND ((BITAND(M.FLAGS,5) != 0) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * T.ROWCNT)))) OR (BITAND(T.FLAGS,2) != 2)) UNION ALL SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(T.FLAGS,2), 2, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(T.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(T.ROWCNT, (T.ROWCNT + M.INSERTS - M.DELETES)))) / (T.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, DBMS_STATS_INTERNAL.GET_TABLE_BLOCK_COUNT(U.NAME,O.NAME, O.SUBNAME,NULL) * :B4 OSIZE, O.OBJ# OBJ#, O.TYPE# TYPE#, T.PART# PART#, T.BO# BO# FROM SYS.OBJ$ O, SYS.USER$ U, SYS.TABCOMPART$ T, SYS.TAB$ TAB, SYS.OBJ$ OT, SYS.MON_MODS_ALL$ M WHERE O.TYPE# = 19 AND T.OBJ# = O.OBJ# AND O.OWNER# = U.USER# AND TAB.OBJ# = T.BO# AND M.OBJ#(+) = T.OBJ# AND BITAND(TAB.TRIGFLAG,67108864) != 67108864 AND BITAND(T.FLAGS, 32) != 32 AND TAB.OBJ# = OT.OBJ# AND BITAND(OT.FLAGS,128) != 128 AND NOT (BITAND(O.FLAGS, 16) = 16 AND (O.NAME LIKE 'DR$%' OR O.NAME LIKE 'DR#%')) AND ((BITAND(T.FLAGS,2) = 2 AND ((BITAND(M.FLAGS,5) != 0) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * T.ROWCNT)))) OR (BITAND(T.FLAGS,2) != 2)) ) WHERE :B5 IS NOT NULL UNION ALL SELECT STALENESS, OSIZE, OBJ#, TYPE#, CASE WHEN ROW_NUMBER() OVER (PARTITION BY BO# ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 64 ELSE 0 END + CASE WHEN ROW_NUMBER() OVER (PARTITION BY (SELECT TCP0.BO# FROM TABCOMPART$ TCP0 WHERE TCP0.OBJ#=ST0.BO#) ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 32 ELSE 0 END AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, PART#, BO# FROM (SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(T.FLAGS,2), 2, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(T.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(T.ROWCNT, (T.ROWCNT + M.INSERTS - M.DELETES)))) / (T.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(T.TS#, T.FILE#, T.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), O.DATAOBJ#, S.BLOCKS) * TS.BLOCKSIZE OSIZE, O.OBJ# OBJ#, O.TYPE# TYPE#, T.SUBPART# PART#, T.POBJ# BO# FROM SYS.SEG$ S, SYS.TS$ TS, SYS.OBJ$ O, SYS.TABSUBPART$ T, SYS.TABCOMPART$ TCP, SYS.TAB$ TAB, SYS.OBJ$ OT, SYS.MON_MODS_ALL$ M, SYS.PARTOBJ$ PO WHERE O.TYPE# = 34 AND S.TYPE# = 5 AND T.OBJ# = O.OBJ# AND M.OBJ#(+) = T.OBJ# AND T.FILE# = S.FILE# AND T.BLOCK# = S.BLOCK# AND T.TS# = S.TS# AND TS.TS# = S.TS# AND TCP.OBJ# = T.POBJ# AND TCP.BO# = TAB.OBJ# AND PO.OBJ# = TAB.OBJ# AND ((:B7 IS NOT NULL AND BITAND(PO.SPARE2, 255) = 2) OR (:B6 IS NOT NULL AND BITAND(PO.SPARE2, 255) NOT IN (0, 2))) AND BITAND(TAB.TRIGFLAG,67108864) != 67108864 AND TAB.OBJ# = OT.OBJ# AND BITAND(OT.FLAGS,128) != 128 AND NOT (BITAND(O.FLAGS, 16) = 16 AND (O.NAME LIKE 'DR$%' OR O.NAME LIKE 'DR#%')) AND BITAND(TCP.FLAGS, 32) != 32 AND ((BITAND(T.FLAGS,2) = 2 AND ((BITAND(M.FLAGS,5) != 0) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * T.ROWCNT)))) OR (BITAND(T.FLAGS,2) != 2))) ST0 UNION ALL SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(I.FLAGS,2), 2, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(CM.TRUNC, 1, GREATEST(CM.ROWCNT, CM.INSERTS), CM.TOT_MODS/(CM.ROWCNT + 0.01))))), 0.01)), 1), -100.0) STALENESS, DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(I.TS#, I.FILE#, I.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), O.DATAOBJ#, S.BLOCKS) * TS.BLOCKSIZE OSIZE, O.OBJ# OBJ#, O.TYPE# TYPE#, 32 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, NULL PART#, I.BO# BO# FROM SYS.SEG$ S, SYS.TS$ TS, SYS.OBJ$ O, SYS.IND$ I, (SELECT BOBJ#, SUM(BITAND(T.TRIGFLAG, 67108864)/67108864) LOCKED, SUM(BITAND(M.FLAGS,1))/COUNT(M.FLAGS) TRUNC, SUM(M.INSERTS+M.DELETES) TOT_MODS, SUM(M.INSERTS) INSERTS, SUM(T.ROWCNT) ROWCNT FROM MON_MODS_ALL$ M, TAB$ T WHERE M.OBJ#(+) = T.OBJ# AND T.CLUCOLS IS NOT NULL GROUP BY BOBJ#) CM WHERE (:B8 IS NOT NULL) AND O.TYPE# = 1 AND S.TYPE# = 6 AND I.TYPE# = 3 AND I.OBJ# = O.OBJ# AND I.BO# = CM.BOBJ#(+) AND I.FILE# = S.FILE# AND I.BLOCK# = S.BLOCK# AND I.TS# = S.TS# AND TS.TS# = S.TS# AND BITAND(O.FLAGS, 128) != 128 AND (BITAND(I.FLAGS, 2) = 0 OR (BITAND(I.FLAGS, 2) != 0 AND (CM.TRUNC > 0 OR CM.TOT_MODS > .1 * CM.ROWCNT))) AND CM.LOCKED = 0 AND BITAND(I.FLAGS,1+8+16+1024+4096) = 0 UNION ALL SELECT /*+ no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ DECODE(BITAND(T.FLAGS,16), 16, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(T.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(T.ROWCNT, (T.ROWCNT + M.INSERTS - M.DELETES)))) / (T.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, CASE WHEN I.FILE# = 0 THEN DBMS_STATS_INTERNAL.GET_INDEX_BLOCK_COUNT(U.NAME, OI.NAME, NULL, NULL) WHEN S.TYPE# = 6 THEN DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(I.TS#, I.FILE#, I.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), I.DATAOBJ#, S.BLOCKS) ELSE NULL END * NVL(TS.BLOCKSIZE, :B4 ) OSIZE, OT.OBJ# OBJ#, OT.TYPE# TYPE#, 32 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, NULL PART#, NULL BO# FROM SYS.USER$ U, SYS.OBJ$ OT, SYS.IND$ I, SYS.SEG$ S, SYS.MON_MODS_ALL$ M, SYS.TS$ TS, SYS.TAB$ T, SYS.OBJ$ OI WHERE :B1 IS NOT NULL AND I.TYPE# = 4 AND I.BO# = OT.OBJ# AND BITAND(OT.FLAGS,128) != 128 AND OT.OWNER# = U.USER# AND M.OBJ#(+) = OT.OBJ# AND I.FILE# = S.FILE#(+) AND I.BLOCK# = S.BLOCK#(+) AND I.TS# = S.TS#(+) AND TS.TS#(+) = S.TS# AND T.OBJ# = OT.OBJ# AND I.OBJ# = OI.OBJ# AND NOT (BITAND(OT.FLAGS, 16) = 16 AND (OT.NAME LIKE 'DR$%' OR OT.NAME LIKE 'DR#%')) AND BITAND(T.TRIGFLAG, 67108864) != 67108864 AND ((BITAND(T.FLAGS,16) = 16 AND ((BITAND(M.FLAGS,1) = 1) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * T.ROWCNT)))) OR (BITAND(M.FLAGS, 4) = 4) OR (BITAND(T.FLAGS,16) != 16)) UNION ALL SELECT /*+ leading(i t) no_expand dynamic_sampling(4) dynamic_sampling_est_cdn */ STALENESS, OSIZE, OBJ#, TYPE#, CASE WHEN ROW_NUMBER() OVER (PARTITION BY BO# ORDER BY STALENESS, OSIZE, OBJ#) = 1 THEN 32 ELSE 0 END + 64 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, PART#, BO# FROM (SELECT DECODE(BITAND(TP.FLAGS,2), 2, ROUND( LOG(0.01, NVL( LEAST( 100, GREATEST( 0.01, (DECODE(BITAND(M.FLAGS, 1), 1, GREATEST(TP.ROWCNT, M.INSERTS), LEAST((M.INSERTS + M.DELETES + M.UPDATES), GREATEST(TP.ROWCNT, (TP.ROWCNT + M.INSERTS - M.DELETES)))) / (TP.ROWCNT + 0.01)))), 0.01)), 1), -100.0) STALENESS, DBMS_SPACE_ADMIN.SEGMENT_NUMBER_BLOCKS(IP.TS#, IP.FILE#, IP.BLOCK#, S.TYPE#, S.CACHEHINT, NVL(S.SPARE1,0), IP.DATAOBJ#, S.BLOCKS) * TS.BLOCKSIZE OSIZE, OT.OBJ# OBJ#, OT.TYPE# TYPE#, TP.PART# PART#, TP.BO# BO# FROM SYS.USER$ U, SYS.OBJ$ OT, SYS.IND$ I, SYS.INDPART$ IP, SYS.TABPART$ TP, SYS.SEG$ S, SYS.MON_MODS_ALL$ M, SYS.TS$ TS, SYS.TAB$ T WHERE I.TYPE# = 4 AND S.TYPE# = 6 AND OT.OWNER# = U.USER# AND I.OBJ# = IP.BO# AND IP.PART# = TP.PART# AND TP.OBJ# = OT.OBJ# AND I.BO# = TP.BO# AND BITAND(OT.FLAGS,128) != 128 AND M.OBJ#(+) = OT.OBJ# AND IP.FILE# = S.FILE# AND IP.BLOCK# = S.BLOCK# AND IP.TS# = S.TS# AND TS.TS# = S.TS# AND I.BO# = T.OBJ# AND NOT (BITAND(OT.FLAGS, 16) = 16 AND (OT.NAME LIKE 'DR$%' OR OT.NAME LIKE 'DR#%')) AND BITAND(T.TRIGFLAG,67108864) != 67108864 AND BITAND(TP.FLAGS, 32) != 32 AND ((BITAND(TP.FLAGS,2) = 2 AND ((BITAND(M.FLAGS,1) = 1) OR ((M.INSERTS + M.UPDATES + M.DELETES) > (.1 * TP.ROWCNT)))) OR (BITAND(M.FLAGS, 4) = 4) OR (BITAND(TP.FLAGS,2) != 2))) WHERE :B5 IS NOT NULL UNION ALL SELECT /*+ ordered */ -99 STALENESS, 100*:B4 OSIZE, I.OBJ# OBJ#, 1 TYPE#, 32 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, NULL PART#, I.BO# BO# FROM SYS.IND$ I, SYS.TAB$ T, SYS.OBJ$ O, USER$ U WHERE (:B8 IS NOT NULL) AND :B1 IS NOT NULL AND BITAND(I.PROPERTY,32) != 32 AND BITAND(I.PROPERTY,64) != 64 AND BITAND(I.FLAGS,2) != 2 AND I.BO# = T.OBJ# AND BITAND(T.TRIGFLAG, 67108864) != 67108864 AND BITAND(T.FLAGS, 16) = 16 AND I.OBJ# = O.OBJ# AND I.TYPE# != 4 AND I.TYPE# != 8 AND BITAND(I.FLAGS,1+8+16+1024+4096) = 0 AND BITAND(O.FLAGS, 128) != 128 AND O.OWNER# = U.USER# AND NOT (U.NAME = 'SYS' AND O.NAME = 'I_SUMDELTA$') UNION ALL SELECT /*+ ordered */ -99 STALENESS, 100*:B4 OSIZE, I.OBJ# OBJ#, 20 TYPE#, 64 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, I.PART# PART#, I.BO# BO# FROM (SELECT OBJ#, BO#, PART#, FLAGS FROM SYS.INDPART$ WHERE BITAND(FLAGS,2) != 2 UNION ALL SELECT OBJ#, BO#, PART#, FLAGS FROM SYS.INDCOMPART$ WHERE BITAND(FLAGS,2) != 2 ) I, SYS.IND$ IND, SYS.TAB$ T, SYS.OBJ$ OI WHERE (:B8 IS NOT NULL) AND :B5 IS NOT NULL AND I.BO# = IND.OBJ# AND IND.TYPE# != 4 AND IND.TYPE# != 8 AND BITAND(IND.FLAGS,1+8+16+1024+4096) = 0 AND IND.BO# = T.OBJ# AND BITAND(T.TRIGFLAG, 67108864) != 67108864 AND IND.OBJ# = OI.OBJ# AND BITAND(OI.FLAGS, 128) != 128 UNION ALL SELECT /*+ ordered */ -99 STALENESS, 100*:B4 OSIZE, I.OBJ# OBJ#, 35 TYPE#, 0 AFLAGS, 0 STATUS, :B3 SID, :B2 SERIAL#, I.SUBPART# PART#, I.POBJ# BO# FROM SYS.INDSUBPART$ I, SYS.INDCOMPART$ ICP, SYS.IND$ IND, SYS.TAB$ T, SYS.PARTOBJ$ PO, SYS.OBJ$ OI WHERE (:B8 IS NOT NULL) AND BITAND(I.FLAGS,2) != 2 AND I.POBJ# = ICP.OBJ# AND ICP.BO# = IND.OBJ# AND IND.TYPE# != 4 AND IND.TYPE# != 8 AND BITAND(IND.FLAGS,1+8+16+1024+4096) = 0 AND IND.BO# = T.OBJ# AND BITAND(T.TRIGFLAG, 67108864) != 67108864 AND IND.OBJ# = PO.OBJ# AND ((:B7 IS NOT NULL AND BITAND(PO.SPARE2, 255) = 2) OR (:B6 IS NOT NULL AND BITAND(PO.SPARE2, 255) NOT IN (0, 2))) AND IND.OBJ# = OI.OBJ# AND BITAND(OI.FLAGS, 128) != 128 ) WHERE OSIZE IS NOT NULL +) +NEW ON (ST.OBJ# = NEW.OBJ#) +WHEN MATCHED THEN +UPDATE SET ST.STALENESS = CASE WHEN BITAND(ST.FLAGS,7) > 1 THEN GREATEST(NEW.STALENESS,-0.5) + ROUND(BITAND(ST.FLAGS,7)*0.15,1) ELSE NEW.STALENESS END, ST.OSIZE = NEW.OSIZE * DECODE(BITAND(ST.FLAGS,7), 0, 1, 2), ST.FLAGS = ST.FLAGS - BITAND(ST.FLAGS, 32+64+128) + NEW.AFLAGS, ST.STATUS = 0, ST.TYPE# = NEW.TYPE#, ST.PART# = NEW.PART#, ST.BO# = NEW.BO#, ST.SID = NEW.SID, ST.SERIAL# = NEW.SERIAL# +WHEN NOT MATCHED THEN +INSERT (ST.STALENESS, ST.OSIZE, ST.OBJ#, ST.TYPE#, ST.FLAGS, ST.STATUS, ST.SID, ST.SERIAL#, ST.PART#, ST.BO#) +VALUES (NEW.STALENESS, NEW.OSIZE, NEW.OBJ#, NEW.TYPE#, NEW.AFLAGS, NEW.STATUS, :B3 , :B2 , NEW.PART#, NEW.BO#) \ No newline at end of file diff --git a/tests/union14.sql b/tests/union14.sql new file mode 100644 index 0000000..a697a08 --- /dev/null +++ b/tests/union14.sql @@ -0,0 +1,14 @@ +select +( + ( + select 'y' from dual + where exists ( select 1 from dual where 1 = 0 ) + ) + union + ( + select 'n' from dual + where not exists ( select 1 from dual where 1 = 0 ) + ) +) +as yes_no +from dual diff --git a/tests/xmltable03.sql b/tests/xmltable03.sql new file mode 100644 index 0000000..8447eb7 --- /dev/null +++ b/tests/xmltable03.sql @@ -0,0 +1,2 @@ +select xmlelement("other_attrs", x).getClobVal() other +from f