Skip to content

Commit 4aad1ac

Browse files
committed
Extend CREATE TABLE Functionality
Partitioning, Table Access Methods and WITH Clause
1 parent 87b3c73 commit 4aad1ac

File tree

6 files changed

+234
-24
lines changed

6 files changed

+234
-24
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ src/include/parser/cypher_kwlist_d.h: src/include/parser/cypher_kwlist.h $(GEN_K
126126

127127
src/include/parser/cypher_gram_def.h: src/backend/parser/cypher_gram.c
128128

129-
src/backend/parser/cypher_gram.c: BISONFLAGS += --defines=src/include/parser/cypher_gram_def.h -Wconflicts-sr -Wcounterexamples
129+
src/backend/parser/cypher_gram.c: BISONFLAGS += --defines=src/include/parser/cypher_gram_def.h
130130

131131
src/backend/parser/cypher_parser.o: src/backend/parser/cypher_gram.c
132132
src/backend/parser/cypher_keywords.o: src/backend/parser/cypher_gram.c

regress/expected/new_cypher.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ MATCH (n) RETURN *;
101101
CREATE TABLE tst (i text);
102102
CREATE TABLE tst3 () INHERITS (tst);
103103
CREATE TEMPORARY TABLE tst2 (i text);
104+
CREATE TABLE tst4 (i text) PARTITION BY LIST (i);
105+
CREATE TABLE tst5 (i text) PARTITION BY LIST (i COLLATE de_DE);
106+
CREATE TABLE tst6 (i text) PARTITION BY LIST (i COLLATE de_DE text_ops);
107+
CREATE TABLE tst7 (i text) USING heap;
108+
CREATE TABLE tst8 (i text) WITH (fillfactor=70);
104109
DROP GRAPH new_cypher CASCADE;
105110
NOTICE: drop cascades to 2 other objects
106111
DETAIL: drop cascades to table new_cypher._ag_label_vertex

regress/sql/new_cypher.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,11 @@ CREATE TABLE tst (i text);
5656
CREATE TABLE tst3 () INHERITS (tst);
5757
CREATE TEMPORARY TABLE tst2 (i text);
5858

59+
CREATE TABLE tst4 (i text) PARTITION BY LIST (i);
60+
CREATE TABLE tst5 (i text) PARTITION BY LIST (i COLLATE de_DE);
61+
CREATE TABLE tst6 (i text) PARTITION BY LIST (i COLLATE de_DE text_ops);
62+
CREATE TABLE tst7 (i text) USING heap;
63+
CREATE TABLE tst8 (i text) WITH (fillfactor=70);
64+
5965
DROP GRAPH new_cypher CASCADE;
6066
DROP GRAPH new_cypher_2 CASCADE;

src/backend/parser/cypher_gram.y

Lines changed: 216 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%{
22
/*
3-
* Copyright (C) 2023 PostGraphDB
3+
* Copyright (C) 2023-2024 PostGraphDB
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU Affero General Public License as
@@ -15,9 +15,6 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*
18-
* For PostgreSQL Database Management System:
19-
* (formerly known as Postgres, then as Postgres95)
20-
*
2118
* Portions Copyright (c) 2020-2023, Apache Software Foundation
2219
* Portions Copyright (c) 2019-2020, Bitnine Global
2320
*/
@@ -33,6 +30,7 @@
3330
#include "nodes/value.h"
3431
#include "parser/parser.h"
3532

33+
3634
#include "nodes/ag_nodes.h"
3735
#include "nodes/cypher_nodes.h"
3836
#include "parser/ag_scanner.h"
@@ -75,6 +73,10 @@
7573
struct DefElem *defelt;
7674
struct RangeVar *range;
7775
struct TypeName *typnam;
76+
struct PartitionElem *partelem;
77+
struct PartitionSpec *partspec;
78+
struct PartitionBoundSpec *partboundspec;
79+
struct Value *value;
7880
}
7981

8082
%token <integer> INTEGER
@@ -91,7 +93,7 @@
9193
/* keywords in alphabetical order */
9294
%token <keyword> ALL AND ANY AS ASC ASCENDING
9395
BETWEEN BY
94-
CALL CASE CASCADE COALESCE CONTAINS CREATE CUBE CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP
96+
CALL CASE CASCADE COALESCE COLLATE CONTAINS CREATE CUBE CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP
9597
DATE DECADE DELETE DESC DESCENDING DETACH DISTINCT DROP
9698
ELSE END_P ENDS EXCEPT EXCLUDE EXISTS EXTENSION EXTRACT
9799
GLOBAL GRAPH GROUP GROUPS GROUPING
@@ -181,12 +183,17 @@
181183
%type <string> all_op
182184
/* names */
183185
%type <string> property_key_name var_name var_name_opt label_name
184-
%type <string> symbolic_name schema_name temporal_cast attr_name
186+
%type <string> symbolic_name schema_name temporal_cast attr_name table_access_method_clause
185187
%type <keyword> reserved_keyword safe_keywords conflicted_keywords
186188
%type <list> func_name
187189
TableElementList OptTableElementList OptInherit
190+
reloptions
191+
OptWith
188192
qualified_name_list
189-
193+
reloption_list
194+
opt_collate
195+
any_name attrs opt_class
196+
%type <defelt> def_elem reloption_elem
190197
%type <string> Sconst
191198
%type <string> ColId ColLabel
192199
%type <string> NonReservedWord_or_Sconst name
@@ -195,7 +202,7 @@
195202

196203
%type <integer> OptTemp
197204

198-
%type <typnam> Typename SimpleTypename GenericType
205+
%type <typnam> Typename SimpleTypename GenericType func_type
199206

200207
%type <range> qualified_name
201208

@@ -205,6 +212,13 @@
205212
/*set operations*/
206213
%type <boolean> all_or_distinct
207214

215+
%type <integer> SignedIconst
216+
%type <node> def_arg
217+
%type <partspec> PartitionSpec OptPartitionSpec
218+
%type <partelem> part_elem
219+
%type <list> part_params
220+
%type <value> NumericOnly
221+
208222
/* precedence: lowest to highest */
209223
%left UNION INTERSECT EXCEPT
210224
%left OR
@@ -255,7 +269,8 @@ static Node *make_set_op(SetOperation op, bool all_or_distinct, List *larg, List
255269

256270
// comparison
257271
static bool is_A_Expr_a_comparison_operation(A_Expr *a);
258-
272+
static void
273+
doNegateFloat(Value *v);
259274
%}
260275
%%
261276

@@ -1018,8 +1033,8 @@ create:
10181033
$$ = (Node *) n;
10191034
}
10201035
| CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
1021-
OptInherit /*OptPartitionSpec table_access_method_clause OptWith
1022-
OnCommitOption OptTableSpace*/
1036+
OptInherit OptPartitionSpec table_access_method_clause OptWith
1037+
//OnCommitOption OptTableSpace
10231038
{
10241039
CreateStmt *n = makeNode(CreateStmt);
10251040
/*
@@ -1040,11 +1055,11 @@ create:
10401055
n->relation = $4;
10411056
n->tableElts = $6;
10421057
n->inhRelations = $8;
1043-
n->partspec = NULL;
1058+
n->partspec = $9;
10441059
n->ofTypename = NULL;
10451060
n->constraints = NIL;
1046-
n->accessMethod = NULL;
1047-
n->options = NULL;
1061+
n->accessMethod = $10;
1062+
n->options = $11;
10481063
n->oncommit = ONCOMMIT_NOOP;
10491064
n->tablespacename = NULL;
10501065
n->if_not_exists = false;
@@ -1054,9 +1069,182 @@ create:
10541069
;
10551070

10561071

1072+
/* WITHOUT OIDS is legacy only */
1073+
OptWith:
1074+
WITH reloptions { $$ = $2; }
1075+
/*| WITHOUT OIDS { $$ = NIL; }*/
1076+
| /*EMPTY*/ { $$ = NIL; }
1077+
;
1078+
reloptions:
1079+
'(' reloption_list ')' { $$ = $2; }
1080+
;
1081+
reloption_list:
1082+
reloption_elem { $$ = list_make1($1); }
1083+
| reloption_list ',' reloption_elem { $$ = lappend($1, $3); }
1084+
;
1085+
1086+
/* This should match def_elem and also allow qualified names */
1087+
reloption_elem:
1088+
ColLabel '=' def_arg
1089+
{
1090+
$$ = makeDefElem($1, (Node *) $3, @1);
1091+
}
1092+
| ColLabel
1093+
{
1094+
$$ = makeDefElem($1, NULL, @1);
1095+
}
1096+
| ColLabel '.' ColLabel '=' def_arg
1097+
{
1098+
$$ = makeDefElemExtended($1, $3, (Node *) $5,
1099+
DEFELEM_UNSPEC, @1);
1100+
}
1101+
| ColLabel '.' ColLabel
1102+
{
1103+
$$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC, @1);
1104+
}
1105+
;
1106+
1107+
NumericOnly:
1108+
DECIMAL { $$ = makeFloat($1); }
1109+
| '+' DECIMAL { $$ = makeFloat($2); }
1110+
| '-' DECIMAL
1111+
{
1112+
$$ = makeFloat($2);
1113+
doNegateFloat($$);
1114+
}
1115+
| SignedIconst { $$ = makeInteger($1); }
1116+
;
1117+
SignedIconst: Iconst { $$ = $1; }
1118+
| '+' Iconst { $$ = + $2; }
1119+
| '-' Iconst { $$ = - $2; }
1120+
;
1121+
Iconst: INTEGER { $$ = $1; };
1122+
/* Note: any simple identifier will be returned as a type name! */
1123+
def_arg: func_type { $$ = (Node *)$1; }
1124+
//| reserved_keyword { $$ = (Node *)makeString(pstrdup($1)); }
1125+
//| qual_all_Op { $$ = (Node *)$1; }
1126+
| NumericOnly { $$ = (Node *)$1; }
1127+
| Sconst { $$ = (Node *)makeString($1); }
1128+
//| NONE { $$ = (Node *)makeString(pstrdup($1)); }
1129+
;
1130+
10571131
OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; }
10581132
| /*EMPTY*/ { $$ = NIL; }
10591133
;
1134+
1135+
1136+
/* Optional partition key specification */
1137+
OptPartitionSpec: PartitionSpec { $$ = $1; }
1138+
| /*EMPTY*/ { $$ = NULL; }
1139+
;
1140+
1141+
PartitionSpec: PARTITION BY ColId '(' part_params ')'
1142+
{
1143+
PartitionSpec *n = makeNode(PartitionSpec);
1144+
1145+
n->strategy = $3;
1146+
n->partParams = $5;
1147+
n->location = @1;
1148+
1149+
$$ = n;
1150+
}
1151+
;
1152+
1153+
part_params: part_elem { $$ = list_make1($1); }
1154+
| part_params ',' part_elem { $$ = lappend($1, $3); }
1155+
;
1156+
1157+
opt_class: any_name { $$ = $1; }
1158+
| /*EMPTY*/ { $$ = NIL; }
1159+
;
1160+
1161+
part_elem: ColId opt_collate opt_class
1162+
{
1163+
PartitionElem *n = makeNode(PartitionElem);
1164+
1165+
n->name = $1;
1166+
n->expr = NULL;
1167+
n->collation = $2;
1168+
n->opclass = $3;
1169+
n->location = @1;
1170+
1171+
$$ = n;
1172+
}
1173+
/*| func_expr_windowless opt_collate opt_class
1174+
{
1175+
PartitionElem *n = makeNode(PartitionElem);
1176+
1177+
n->name = NULL;
1178+
n->expr = $1;
1179+
n->collation = $2;
1180+
n->opclass = $3;
1181+
n->location = @1;
1182+
$$ = n;
1183+
}
1184+
| '(' a_expr ')' opt_collate opt_class
1185+
{
1186+
PartitionElem *n = makeNode(PartitionElem);
1187+
1188+
n->name = NULL;
1189+
n->expr = $2;
1190+
n->collation = $4;
1191+
n->opclass = $5;
1192+
n->location = @1;
1193+
$$ = n;
1194+
}*/
1195+
;
1196+
1197+
1198+
/*
1199+
* We would like to make the %TYPE productions here be ColId attrs etc,
1200+
* but that causes reduce/reduce conflicts. type_function_name
1201+
* is next best choice.
1202+
*/
1203+
func_type: Typename { $$ = $1; }
1204+
/*| type_function_name attrs '%' TYPE_P
1205+
{
1206+
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
1207+
$$->pct_type = true;
1208+
$$->location = @1;
1209+
}
1210+
| SETOF type_function_name attrs '%' TYPE_P
1211+
{
1212+
$$ = makeTypeNameFromNameList(lcons(makeString($2), $3));
1213+
$$->pct_type = true;
1214+
$$->setof = true;
1215+
$$->location = @2;
1216+
}*/
1217+
;
1218+
1219+
def_elem: ColLabel '=' def_arg
1220+
{
1221+
$$ = makeDefElem($1, (Node *) $3, @1);
1222+
}
1223+
| ColLabel
1224+
{
1225+
$$ = makeDefElem($1, NULL, @1);
1226+
}
1227+
;
1228+
1229+
table_access_method_clause:
1230+
USING name { $$ = $2; }
1231+
| /*EMPTY*/ { $$ = NULL; }
1232+
;
1233+
1234+
any_name: ColId { $$ = list_make1(makeString($1)); }
1235+
| ColId attrs { $$ = lcons(makeString($1), $2); }
1236+
;
1237+
1238+
opt_collate: COLLATE any_name { $$ = $2; }
1239+
| /*EMPTY*/ { $$ = NIL; }
1240+
;
1241+
1242+
1243+
attrs: '.' attr_name
1244+
{ $$ = list_make1(makeString($2)); }
1245+
| attrs '.' attr_name
1246+
{ $$ = lappend($1, makeString($3)); }
1247+
;
10601248

10611249
/*
10621250
* Redundancy here is needed to avoid shift/reduce conflicts,
@@ -2799,7 +2987,7 @@ conflicted_keywords:
27992987
| FALSE_P { $$ = pnstrdup($1, 7); }
28002988
| NULL_P { $$ = pnstrdup($1, 6); }
28012989
| TRUE_P { $$ = pnstrdup($1, 6); }
2802-
| WITH { $$ = pnstrdup($1, 4); }
2990+
// | WITH { $$ = pnstrdup($1, 4); }
28032991
;
28042992

28052993
%%
@@ -3037,3 +3225,16 @@ static Node *make_set_op(SetOperation op, bool all_or_distinct, List *larg, List
30373225
return (Node *) n;
30383226
}
30393227

3228+
static void
3229+
doNegateFloat(Value *v)
3230+
{
3231+
char *oldval = v->val.str;
3232+
3233+
Assert(IsA(v, Float));
3234+
if (*oldval == '+')
3235+
oldval++;
3236+
if (*oldval == '-')
3237+
v->val.str = oldval+1; /* just strip the '-' */
3238+
else
3239+
v->val.str = psprintf("-%s", oldval);
3240+
}

0 commit comments

Comments
 (0)