Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions plsql/PlSqlLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,7 @@ PARTITION_LIST: 'PARTITION_LIST';
PARTITION: 'PARTITION';
PARTITION_RANGE: 'PARTITION_RANGE';
PARTITIONS: 'PARTITIONS';
PARTITIONSET: 'PARTITIONSET';
PARTNUMINST: 'PART$NUM$INST';
PASSING: 'PASSING';
PASSWORD_GRACE_TIME: 'PASSWORD_GRACE_TIME';
Expand Down Expand Up @@ -2303,9 +2304,7 @@ ORACLE_DATAPUMP: 'ORACLE_DATAPUMP';
ORACLE_HDFS: 'ORACLE_HDFS';
ORACLE_HIVE: 'ORACLE_HIVE';
ORACLE_LOADER: 'ORACLE_LOADER';
SHA2_512_Q: '"SHA2_512"';
SHARDED: 'SHARDED';
V1_Q: '"V1"';

ISOLATE: 'ISOLATE';
ROOT: 'ROOT';
Expand Down
93 changes: 81 additions & 12 deletions plsql/PlSqlParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -3295,7 +3295,7 @@ create_table
| IMMUTABLE? BLOCKCHAIN
| IMMUTABLE
)?
TABLE (schema_name PERIOD)? table_name
TABLE (IF NOT EXISTS)? (schema_name PERIOD)? table_name
(SHARING EQUALS_OP (METADATA | EXTENDED? DATA | NONE))?
(relational_table | object_table | xmltype_table)
(MEMOPTIMIZE FOR READ)?
Expand Down Expand Up @@ -3395,19 +3395,19 @@ immutable_table_no_delete_clause
;

blockchain_table_clauses
: blockchain_drop_table_clause blockchain_row_retention_clause blockchain_hash_and_data_format_clause
: blockchain_drop_table_clause? blockchain_row_retention_clause? blockchain_hash_and_data_format_clause
;

blockchain_drop_table_clause
: NO DROP (UNTIL numeric DAYS IDLE)?
;

blockchain_row_retention_clause
: NO DELETE (LOCKED? | UNTIL numeric DAYS AFTER INSERT LOCKED?)
: NO DELETE (LOCKED? | UNTIL numeric DAYS (IDLE | AFTER INSERT) LOCKED?)
Comment thread
h3n4l marked this conversation as resolved.
;

blockchain_hash_and_data_format_clause
: HASHING USING SHA2_512_Q VERSION V1_Q
: HASHING USING (CHAR_STRING | DELIMITED_ID) VERSION (CHAR_STRING | DELIMITED_ID)
;

collation_name
Expand Down Expand Up @@ -3512,6 +3512,9 @@ table_partitioning_clauses
| composite_hash_partitions
| reference_partitioning
| system_partitioning
| consistent_hash_partitions
| consistent_hash_with_subpartitions
| partitionset_clauses
;

range_partitions
Expand All @@ -3521,7 +3524,8 @@ range_partitions
;

list_partitions
: PARTITION BY LIST LEFT_PAREN column_name RIGHT_PAREN
: PARTITION BY LIST LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
AUTOMATIC?
LEFT_PAREN PARTITION partition_name? list_values_clause table_partition_description (COMMA PARTITION partition_name? list_values_clause table_partition_description )* RIGHT_PAREN
;

Expand Down Expand Up @@ -3553,7 +3557,8 @@ composite_range_partitions
;

composite_list_partitions
: PARTITION BY LIST LEFT_PAREN column_name RIGHT_PAREN
: PARTITION BY LIST LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
AUTOMATIC?
(subpartition_by_range | subpartition_by_list | subpartition_by_hash)
LEFT_PAREN list_partition_desc (COMMA list_partition_desc)* RIGHT_PAREN
;
Expand All @@ -3578,6 +3583,51 @@ system_partitioning
(PARTITIONS UNSIGNED_INTEGER | reference_partition_desc (COMMA reference_partition_desc)*)?
;

consistent_hash_partitions
: PARTITION BY CONSISTENT HASH LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
PARTITIONS AUTO
;

consistent_hash_with_subpartitions
: PARTITION BY CONSISTENT HASH LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
PARTITIONS AUTO
SUBPARTITION BY
( RANGE LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
| LIST LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
)
SUBPARTITIONS AUTO
;

partitionset_clauses
: PARTITION BY PARTITIONSET (range_partitionset_clause | list_partitionset_clause)
;

range_partitionset_clause
: RANGE LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
LEFT_PAREN range_partitionset_desc (COMMA range_partitionset_desc)* RIGHT_PAREN
;

range_partitionset_desc
: PARTITIONSET partitionset_name
VALUES LESS THAN LEFT_PAREN range_partition_value (COMMA range_partition_value)* RIGHT_PAREN
LEFT_PAREN range_partition_desc (COMMA range_partition_desc)* RIGHT_PAREN
;

list_partitionset_clause
: LIST LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN
LEFT_PAREN list_partitionset_desc (COMMA list_partitionset_desc)* RIGHT_PAREN
;

list_partitionset_desc
: PARTITIONSET partitionset_name
VALUES LEFT_PAREN (list_partition_value (COMMA list_partition_value)* | DEFAULT) RIGHT_PAREN
LEFT_PAREN list_partition_desc (COMMA list_partition_desc)* RIGHT_PAREN
;

partitionset_name
: identifier
;

range_partition_desc
: PARTITION partition_name? range_values_clause table_partition_description
( ( LEFT_PAREN ( range_subpartition_desc (COMMA range_subpartition_desc)*
Expand Down Expand Up @@ -3623,7 +3673,7 @@ subpartition_by_range
;

subpartition_by_list
: SUBPARTITION BY LIST LEFT_PAREN column_name RIGHT_PAREN subpartition_template?
: SUBPARTITION BY LIST LEFT_PAREN column_name (COMMA column_name)* RIGHT_PAREN subpartition_template?
;

subpartition_by_hash
Expand All @@ -3638,27 +3688,44 @@ subpartition_name
;

range_subpartition_desc
: SUBPARTITION subpartition_name? range_values_clause partitioning_storage_clause?
: SUBPARTITION subpartition_name? range_values_clause read_only_clause? indexing_clause? partitioning_storage_clause?
;

list_subpartition_desc
: SUBPARTITION subpartition_name? list_values_clause partitioning_storage_clause?
: SUBPARTITION subpartition_name? list_values_clause read_only_clause? indexing_clause? partitioning_storage_clause?
;

individual_hash_subparts
: SUBPARTITION subpartition_name? partitioning_storage_clause?
: SUBPARTITION subpartition_name? read_only_clause? indexing_clause? partitioning_storage_clause?
;

hash_subparts_by_quantity
: SUBPARTITIONS UNSIGNED_INTEGER (STORE IN LEFT_PAREN tablespace (COMMA tablespace)* RIGHT_PAREN )?
;

range_values_clause
: VALUES LESS THAN LEFT_PAREN literal (COMMA literal)* RIGHT_PAREN
: VALUES LESS THAN LEFT_PAREN range_partition_value (COMMA range_partition_value)* RIGHT_PAREN
;

range_partition_value
: expression
| MAXVALUE
;

list_values_clause
: VALUES LEFT_PAREN (literal (COMMA literal)* | TIMESTAMP literal (COMMA TIMESTAMP literal)* | DEFAULT) RIGHT_PAREN
: VALUES LEFT_PAREN (list_partition_value (COMMA list_partition_value)* | DEFAULT) RIGHT_PAREN
;

list_partition_value
: expression
| NULL_
| LEFT_PAREN list_partition_value_item (COMMA list_partition_value_item)* RIGHT_PAREN
Comment thread
h3n4l marked this conversation as resolved.
Outdated
;

list_partition_value_item
: expression
| NULL_
| DEFAULT
Comment thread
h3n4l marked this conversation as resolved.
Outdated
;

table_partition_description
Expand Down Expand Up @@ -5255,6 +5322,7 @@ column_definition
(DEFAULT (ON NULL_)? expression | identity_clause)?
(ENCRYPT encryption_spec)?
(inline_constraint+ | inline_ref_constraint)?
annotations_clause?
;

column_collation_name
Expand Down Expand Up @@ -9023,6 +9091,7 @@ non_reserved_keywords_pre12c
| PARTITION
| PARTITION_RANGE
| PARTITIONS
| PARTITIONSET
| PARTNUMINST
| PASSING
| PASSWORD_GRACE_TIME
Expand Down
127 changes: 127 additions & 0 deletions plsql/examples/create_table_grammar_gaps.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
-- Regression fixtures for CREATE TABLE grammar gaps closed against Oracle 19c docs.
-- Each block below previously failed to parse; see PR description for details.

--------------------------------------------------------------------------------
-- Tier 1: partition value clauses accept full expressions (fixes BYT-9302)
--------------------------------------------------------------------------------

-- DATE typed literal in RANGE bound with INTERVAL partitioning
CREATE TABLE gcp.lead_drop_mc_native_data (
txn_date DATE,
userid VARCHAR2(100),
custid VARCHAR2(100),
screenid VARCHAR2(500),
eventtime DATE,
status NUMBER
)
PARTITION BY RANGE (txn_date)
INTERVAL (NUMTODSINTERVAL(1,'DAY'))
(PARTITION p0 VALUES LESS THAN (DATE '2026-01-01'));

-- TIMESTAMP typed literal in RANGE bound
CREATE TABLE range_ts (d TIMESTAMP)
PARTITION BY RANGE (d)
(PARTITION p0 VALUES LESS THAN (TIMESTAMP '2026-01-01 00:00:00'));

-- Arithmetic expression in RANGE bound
CREATE TABLE range_expr (c NUMBER)
PARTITION BY RANGE (c)
(PARTITION p0 VALUES LESS THAN (10*10 + 5));

-- NULL in LIST values
CREATE TABLE list_null (c VARCHAR2(10))
PARTITION BY LIST (c)
(PARTITION p0 VALUES (NULL, 'a', 'b'));

-- Expression in LIST values
CREATE TABLE list_expr (c NUMBER)
PARTITION BY LIST (c)
(PARTITION p0 VALUES (1+2, 3*3));

-- Multi-column LIST partitioning with tuple form
CREATE TABLE list_multi_col (a NUMBER, b NUMBER)
PARTITION BY LIST (a, b)
(
PARTITION p0 VALUES ((1,2),(3,4)),
PARTITION p1 VALUES ((5,6))
);

--------------------------------------------------------------------------------
-- Tier 2: IF NOT EXISTS, LIST AUTOMATIC, blockchain flexibility
--------------------------------------------------------------------------------

-- IF NOT EXISTS on CREATE TABLE
CREATE TABLE IF NOT EXISTS t_ine (a NUMBER, b VARCHAR2(10));

-- AUTOMATIC list partitioning
CREATE TABLE list_auto (c NUMBER)
PARTITION BY LIST (c) AUTOMATIC
(PARTITION p0 VALUES (1));

-- Blockchain: new DAYS IDLE form on retention clause, with single-quoted algorithm/version
CREATE BLOCKCHAIN TABLE bc_idle (a NUMBER)
NO DROP UNTIL 0 DAYS IDLE
NO DELETE UNTIL 16 DAYS IDLE
HASHING USING 'SHA2_512' VERSION 'v1';

-- Blockchain: drop/retention clauses both omitted (only the hash clause is required)
CREATE BLOCKCHAIN TABLE bc_hash_only (a NUMBER)
HASHING USING "SHA2_512" VERSION "v1";

--------------------------------------------------------------------------------
-- Tier 3: CONSISTENT HASH and PARTITIONSET
--------------------------------------------------------------------------------

-- Consistent hash partitioning
CREATE TABLE ch_simple (a NUMBER)
PARTITION BY CONSISTENT HASH (a)
PARTITIONS AUTO;

-- Consistent hash with range sub-partitioning
CREATE TABLE ch_sub (a NUMBER, d DATE)
PARTITION BY CONSISTENT HASH (a)
PARTITIONS AUTO
SUBPARTITION BY RANGE (d)
SUBPARTITIONS AUTO;

-- Range partitionset
CREATE TABLE range_ps (a NUMBER, b NUMBER)
PARTITION BY PARTITIONSET RANGE (a)
(
PARTITIONSET ps1 VALUES LESS THAN (100)
(PARTITION p1 VALUES LESS THAN (10))
);

-- List partitionset
CREATE TABLE list_ps (a NUMBER, b NUMBER)
PARTITION BY PARTITIONSET LIST (a)
(
PARTITIONSET ps1 VALUES (1,2,3)
(PARTITION p1 VALUES (1))
);

--------------------------------------------------------------------------------
-- Tier 4: subpartition read_only / indexing clauses + column annotations
--------------------------------------------------------------------------------

-- read_only_clause on range_subpartition_desc (inside composite range partitioning)
CREATE TABLE comp_range_ro (a NUMBER, d DATE)
PARTITION BY RANGE (d)
SUBPARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (DATE '2026-01-01')
(SUBPARTITION sp0 VALUES LESS THAN (100) READ ONLY,
SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE) READ WRITE INDEXING OFF));

-- indexing_clause on individual_hash_subparts
CREATE TABLE comp_hash_idx (a NUMBER, b NUMBER)
PARTITION BY RANGE (a)
SUBPARTITION BY HASH (b)
(PARTITION p0 VALUES LESS THAN (100)
(SUBPARTITION sp0 INDEXING ON,
SUBPARTITION sp1 INDEXING OFF));

-- annotations_clause on column definition (Oracle 23c)
CREATE TABLE annotated_cols (
id NUMBER ANNOTATIONS (Display 'Identifier'),
name VARCHAR2(100) ANNOTATIONS (ADD Display 'Name', MaxLength '100')
);
Loading
Loading