diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml index 4db8142afa..8491b7831a 100644 --- a/doc/src/sgml/ref/select.sgml +++ b/doc/src/sgml/ref/select.sgml @@ -44,7 +44,7 @@ SELECT [ ALL | DISTINCT [ ON ( expressionexpression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] - [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] + [ FETCH { FIRST | NEXT } [ count ] [ PERCENT ] { ROW | ROWS } ONLY ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ] where from_item can be one of: @@ -1397,7 +1397,7 @@ OFFSET start which PostgreSQL also supports. It is: OFFSET start { ROW | ROWS } -FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY +FETCH { FIRST | NEXT } [ count ] [ PERCENT ] { ROW | ROWS } ONLY In this syntax, the start or count value is required by @@ -1407,7 +1407,8 @@ FETCH { FIRST | NEXT } [ count ] { ambiguity. If count is omitted in a FETCH clause, it defaults to 1. - ROW + with PERCENT count specifies the maximum number of rows to return + in percentage.ROW and ROWS as well as FIRST and NEXT are noise words that don't influence the effects of these clauses. diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index bb28cf7d1d..8f1e937906 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -60,6 +60,24 @@ ExecLimit(PlanState *pstate) { case LIMIT_INITIAL: + if (node->limitOption == PERCENTAGE) + { + + /* + * Find the total number of row the plan will return. + */ + for (;;) + { + slot = ExecProcNode(outerPlan); + if (TupIsNull(slot)) + { + break; + } + node->total++; + } + ExecReScan(outerPlan); + } + /* * First call for this node, so compute limit/offset. (We can't do * this any earlier, because parameters from upper nodes will not @@ -283,11 +301,16 @@ recompute_limits(LimitState *node) } else { - node->count = DatumGetInt64(val); - if (node->count < 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE), - errmsg("LIMIT must not be negative"))); + if (node->limitOption == PERCENTAGE) + node->count = (DatumGetInt64(val) * node->total) / 100; + else + { + node->count = DatumGetInt64(val); + if (node->count < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE), + errmsg("LIMIT must not be negative"))); + } node->noCount = false; } } @@ -374,6 +397,8 @@ ExecInitLimit(Limit *node, EState *estate, int eflags) (PlanState *) limitstate); limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount, (PlanState *) limitstate); + limitstate->limitOption = node->limitOption; + limitstate->total = 0; /* * Initialize result slot and type. (XXX not actually used, but upper diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 7c8220cf65..ba3e086e24 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1139,6 +1139,7 @@ _copyLimit(const Limit *from) */ COPY_NODE_FIELD(limitOffset); COPY_NODE_FIELD(limitCount); + COPY_SCALAR_FIELD(limitOption); return newnode; } @@ -3024,6 +3025,7 @@ _copyQuery(const Query *from) COPY_NODE_FIELD(sortClause); COPY_NODE_FIELD(limitOffset); COPY_NODE_FIELD(limitCount); + COPY_SCALAR_FIELD(limitOption); COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(setOperations); COPY_NODE_FIELD(constraintDeps); @@ -3108,6 +3110,7 @@ _copySelectStmt(const SelectStmt *from) COPY_NODE_FIELD(sortClause); COPY_NODE_FIELD(limitOffset); COPY_NODE_FIELD(limitCount); + COPY_SCALAR_FIELD(limitOption); COPY_NODE_FIELD(lockingClause); COPY_NODE_FIELD(withClause); COPY_SCALAR_FIELD(op); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 378f2facb8..ba74fe9ffc 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -973,6 +973,7 @@ _equalQuery(const Query *a, const Query *b) COMPARE_NODE_FIELD(sortClause); COMPARE_NODE_FIELD(limitOffset); COMPARE_NODE_FIELD(limitCount); + COMPARE_SCALAR_FIELD(limitOption); COMPARE_NODE_FIELD(rowMarks); COMPARE_NODE_FIELD(setOperations); COMPARE_NODE_FIELD(constraintDeps); @@ -1047,6 +1048,7 @@ _equalSelectStmt(const SelectStmt *a, const SelectStmt *b) COMPARE_NODE_FIELD(sortClause); COMPARE_NODE_FIELD(limitOffset); COMPARE_NODE_FIELD(limitCount); + COMPARE_SCALAR_FIELD(limitOption); COMPARE_NODE_FIELD(lockingClause); COMPARE_NODE_FIELD(withClause); COMPARE_SCALAR_FIELD(op); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 6269f474d2..a3572c73d4 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -986,6 +986,7 @@ _outLimit(StringInfo str, const Limit *node) WRITE_NODE_FIELD(limitOffset); WRITE_NODE_FIELD(limitCount); + WRITE_ENUM_FIELD(limitOption, LimitOption); } static void @@ -2197,6 +2198,7 @@ _outLimitPath(StringInfo str, const LimitPath *node) WRITE_NODE_FIELD(subpath); WRITE_NODE_FIELD(limitOffset); WRITE_NODE_FIELD(limitCount); + WRITE_ENUM_FIELD(limitOption, LimitOption); } static void @@ -2785,6 +2787,7 @@ _outSelectStmt(StringInfo str, const SelectStmt *node) WRITE_NODE_FIELD(sortClause); WRITE_NODE_FIELD(limitOffset); WRITE_NODE_FIELD(limitCount); + WRITE_ENUM_FIELD(limitOption, LimitOption); WRITE_NODE_FIELD(lockingClause); WRITE_NODE_FIELD(withClause); WRITE_ENUM_FIELD(op, SetOperation); @@ -2995,6 +2998,7 @@ _outQuery(StringInfo str, const Query *node) WRITE_NODE_FIELD(sortClause); WRITE_NODE_FIELD(limitOffset); WRITE_NODE_FIELD(limitCount); + WRITE_ENUM_FIELD(limitOption, LimitOption); WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(setOperations); WRITE_NODE_FIELD(constraintDeps); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 3254524223..a10f989042 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -266,6 +266,7 @@ _readQuery(void) READ_NODE_FIELD(sortClause); READ_NODE_FIELD(limitOffset); READ_NODE_FIELD(limitCount); + READ_ENUM_FIELD(limitOption, LimitOption); READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(setOperations); READ_NODE_FIELD(constraintDeps); @@ -2286,6 +2287,7 @@ _readLimit(void) READ_NODE_FIELD(limitOffset); READ_NODE_FIELD(limitCount); + READ_ENUM_FIELD(limitOption, LimitOption); READ_DONE(); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index ae41c9efa0..e9df3ccda0 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2139,7 +2139,8 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path) plan = (Plan *) make_limit(plan, subparse->limitOffset, - subparse->limitCount); + subparse->limitCount, + subparse->limitOption); /* Must apply correct cost/width data to Limit node */ plan->startup_cost = mminfo->path->startup_cost; @@ -2444,7 +2445,8 @@ create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags) plan = make_limit(subplan, best_path->limitOffset, - best_path->limitCount); + best_path->limitCount, + best_path->limitOption); copy_generic_path_info(&plan->plan, (Path *) best_path); @@ -6446,7 +6448,7 @@ make_lockrows(Plan *lefttree, List *rowMarks, int epqParam) * Build a Limit plan node */ Limit * -make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount) +make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption) { Limit *node = makeNode(Limit); Plan *plan = &node->plan; @@ -6458,6 +6460,7 @@ make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount) node->limitOffset = limitOffset; node->limitCount = limitCount; + node->limitOption = limitOption; return node; } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 96bf0601a8..7322dfc90f 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -2166,6 +2166,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, path = (Path *) create_limit_path(root, final_rel, path, parse->limitOffset, parse->limitCount, + parse->limitOption, offset_est, count_est); } diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index c5aaaf5c22..0315e434b6 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -3412,6 +3412,7 @@ LimitPath * create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, + LimitOption limitOption, int64 offset_est, int64 count_est) { LimitPath *pathnode = makeNode(LimitPath); @@ -3433,6 +3434,7 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel, pathnode->subpath = subpath; pathnode->limitOffset = limitOffset; pathnode->limitCount = limitCount; + pathnode->limitOption = limitOption; /* * Adjust the output rows count and costs according to the offset/limit. diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index c601b6d40d..7c682c5c11 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -1301,6 +1301,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, stmt->limitCount, EXPR_KIND_LIMIT, "LIMIT"); + qry->limitOption = stmt->limitOption; /* transform window clauses after we have seen all window functions */ qry->windowClause = transformWindowDefinitions(pstate, @@ -1547,6 +1548,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, stmt->limitCount, EXPR_KIND_LIMIT, "LIMIT"); + qry->limitOption = stmt->limitOption; if (stmt->lockingClause) ereport(ERROR, @@ -1782,6 +1784,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, limitCount, EXPR_KIND_LIMIT, "LIMIT"); + qry->limitOption = stmt->limitOption; qry->rtable = pstate->p_rtable; qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 87f5e95827..424fcfd418 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -164,6 +164,7 @@ static List *makeOrderedSetArgs(List *directargs, List *orderedargs, static void insertSelectOptions(SelectStmt *stmt, List *sortClause, List *lockingClause, Node *limitOffset, Node *limitCount, + void *limitOption, WithClause *withClause, core_yyscan_t yyscanner); static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); @@ -387,7 +388,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); target_list opt_target_list insert_column_list set_target_list set_clause_list set_clause def_list operator_def_list indirection opt_indirection - reloption_list group_clause TriggerFuncArgs select_limit + reloption_list group_clause TriggerFuncArgs select_limit limit_clause opt_select_limit opclass_item_list opclass_drop_list opclass_purpose opt_opfamily transaction_mode_list_or_empty OptTableFuncElementList TableFuncElementList opt_type_modifiers @@ -449,7 +450,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); comment_type_any_name comment_type_name security_label_type_any_name security_label_type_name -%type fetch_args limit_clause select_limit_value +%type fetch_args select_limit_value offset_clause select_offset_value select_fetch_first_value I_or_F_const %type row_or_rows first_or_next @@ -662,7 +663,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER - PARALLEL PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POLICY + PARALLEL PARSER PARTIAL PARTITION PASSING PASSWORD PERCENT PLACING PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION @@ -11218,7 +11219,7 @@ select_no_parens: | select_clause sort_clause { insertSelectOptions((SelectStmt *) $1, $2, NIL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, yyscanner); $$ = $1; } @@ -11226,6 +11227,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $1, $2, $3, list_nth($4, 0), list_nth($4, 1), + (list_nth($4, 2)), NULL, yyscanner); $$ = $1; @@ -11234,6 +11236,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $1, $2, $4, list_nth($3, 0), list_nth($3, 1), + list_nth($3, 2), NULL, yyscanner); $$ = $1; @@ -11242,7 +11245,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $2, NULL, NIL, NULL, NULL, - $1, + NULL, $1, yyscanner); $$ = $2; } @@ -11250,7 +11253,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $2, $3, NIL, NULL, NULL, - $1, + NULL, $1, yyscanner); $$ = $2; } @@ -11258,6 +11261,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $2, $3, $4, list_nth($5, 0), list_nth($5, 1), + list_nth($5, 2), $1, yyscanner); $$ = $2; @@ -11266,6 +11270,7 @@ select_no_parens: { insertSelectOptions((SelectStmt *) $2, $3, $5, list_nth($4, 0), list_nth($4, 1), + list_nth($4, 2), $1, yyscanner); $$ = $2; @@ -11552,20 +11557,20 @@ sortby: a_expr USING qual_all_Op opt_nulls_order select_limit: - limit_clause offset_clause { $$ = list_make2($2, $1); } - | offset_clause limit_clause { $$ = list_make2($1, $2); } - | limit_clause { $$ = list_make2(NULL, $1); } - | offset_clause { $$ = list_make2($1, NULL); } + limit_clause offset_clause { $$ = list_make3($2, list_nth($1, 0), list_nth($1, 1)); } + | offset_clause limit_clause { $$ = list_make3($1, list_nth($2, 0), list_nth($2, 1)); } + | limit_clause { $$ = list_make3(NULL, list_nth($1, 0), list_nth($1, 1)); } + | offset_clause { $$ = list_make3($1, NULL, NULL); } ; opt_select_limit: select_limit { $$ = $1; } - | /* EMPTY */ { $$ = list_make2(NULL,NULL); } + | /* EMPTY */ { $$ = list_make3(NULL, NULL, NULL); } ; limit_clause: LIMIT select_limit_value - { $$ = $2; } + { $$ = list_make2($2, NULL); } | LIMIT select_limit_value ',' select_offset_value { /* Disabled because it was too confusing, bjm 2002-02-18 */ @@ -11583,9 +11588,11 @@ limit_clause: * we can see the ONLY token in the lookahead slot. */ | FETCH first_or_next select_fetch_first_value row_or_rows ONLY - { $$ = $3; } + { $$ = list_make2($3, makeString("EXACT_NUMBER")); } + | FETCH first_or_next select_fetch_first_value PERCENT row_or_rows ONLY + { $$ = list_make2($3, makeString("PERCENTAGE")); } | FETCH first_or_next row_or_rows ONLY - { $$ = makeIntConst(1, -1); } + { $$ = list_make2(makeIntConst(1, -1), NULL); } ; offset_clause: @@ -15453,6 +15460,7 @@ reserved_keyword: | ONLY | OR | ORDER + | PERCENT | PLACING | PRIMARY | REFERENCES @@ -15836,6 +15844,7 @@ static void insertSelectOptions(SelectStmt *stmt, List *sortClause, List *lockingClause, Node *limitOffset, Node *limitCount, + void *limitOption, WithClause *withClause, core_yyscan_t yyscanner) { @@ -15874,6 +15883,17 @@ insertSelectOptions(SelectStmt *stmt, parser_errposition(exprLocation(limitCount)))); stmt->limitCount = limitCount; } + if (limitOption) + { + if (stmt->limitOption) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple LIMIT options not allowed"))); + if (strcmp(strVal(limitOption), "PERCENTAGE") == 0) + stmt->limitOption = PERCENTAGE; + else + stmt->limitOption = EXACT_NUMBER; + } if (withClause) { if (stmt->withClause) diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 41fa2052a2..4350da1907 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -2219,8 +2219,10 @@ typedef struct LimitState PlanState ps; /* its first field is NodeTag */ ExprState *limitOffset; /* OFFSET parameter, or NULL if none */ ExprState *limitCount; /* COUNT parameter, or NULL if none */ + LimitOption limitOption; /* limit specification type */ int64 offset; /* current OFFSET value */ int64 count; /* current COUNT, if any */ + int64 total; /* total number of row outer node return */ bool noCount; /* if true, ignore count */ LimitStateCond lstate; /* state machine status, as above */ int64 position; /* 1-based index of last tuple returned */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 697d3d7a5f..3a4ca4b27e 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -811,4 +811,16 @@ typedef enum OnConflictAction ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */ } OnConflictAction; +/* + * LimitOption - + * LIMIT option of query + * + * This is needed in both parsenodes.h and plannodes.h, so put it here... + */ +typedef enum LimitOption +{ + EXACT_NUMBER, /* LIMIT in exact number of rows */ + PERCENTAGE /* LIMIT in percentage */ +} LimitOption; + #endif /* NODES_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 07ab1a3dde..58702f8afe 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -159,6 +159,7 @@ typedef struct Query Node *limitOffset; /* # of result tuples to skip (int8 expr) */ Node *limitCount; /* # of result tuples to return (int8 expr) */ + LimitOption limitOption; /* limit type */ List *rowMarks; /* a list of RowMarkClause's */ @@ -1560,6 +1561,7 @@ typedef struct SelectStmt List *sortClause; /* sort clause (a list of SortBy's) */ Node *limitOffset; /* # of result tuples to skip */ Node *limitCount; /* # of result tuples to return */ + LimitOption limitOption; /* limit type */ List *lockingClause; /* FOR UPDATE (list of LockingClause's) */ WithClause *withClause; /* WITH clause */ diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 7c2abbd03a..e2cc85789b 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -952,6 +952,7 @@ typedef struct Limit Plan plan; Node *limitOffset; /* OFFSET parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */ + LimitOption limitOption; /* LIMIT in percentage or exact number */ } Limit; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 41caf873fb..cb69a68777 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -1735,6 +1735,7 @@ typedef struct LimitPath Path *subpath; /* path representing input source */ Node *limitOffset; /* OFFSET parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */ + LimitOption limitOption; /* LIMIT in percentage or exact number */ } LimitPath; diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 7c5ff22650..17b62c7b8c 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -248,6 +248,7 @@ extern ModifyTablePath *create_modifytable_path(PlannerInfo *root, extern LimitPath *create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, + LimitOption limitOption, int64 offset_est, int64 count_est); extern Path *reparameterize_path(PlannerInfo *root, Path *path, diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index c8ab0280d2..4e1e3cebe2 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -64,7 +64,7 @@ extern Agg *make_agg(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree); -extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount); +extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption); /* * prototypes for plan/initsplan.c diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 23db40147b..150d51df8f 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -300,6 +300,7 @@ PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD) PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD) PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD) PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD) +PG_KEYWORD("percent", PERCENT, RESERVED_KEYWORD) PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD) PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD) PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD) diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 8927b21ba2..442b7622ea 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -79,7 +79,7 @@ CREATE TABLE student ( gpa float8 ) INHERITS (person); CREATE TABLE stud_emp ( - percent int4 + "percent" int4 ) INHERITS (emp, student); NOTICE: merging multiple inherited definitions of column "name" NOTICE: merging multiple inherited definitions of column "age" diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 81fa7658b0..81ec6e368d 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -92,7 +92,7 @@ CREATE TABLE student ( CREATE TABLE stud_emp ( - percent int4 + "percent" int4 ) INHERITS (emp, student);