@@ -105,12 +105,15 @@ typedef struct ImportQual
105105 List *table_names;
106106} ImportQual;
107107
108- /* Private struct for the result of opt_select_limit production */
108+ /* Private struct for the result of select_limit & limit_clause productions */
109109typedef struct SelectLimit
110110{
111111 Node *limitOffset;
112112 Node *limitCount;
113- LimitOption limitOption;
113+ LimitOption limitOption; /* indicates presence of WITH TIES */
114+ ParseLoc offsetLoc; /* location of OFFSET token, if present */
115+ ParseLoc countLoc; /* location of LIMIT/FETCH token, if present */
116+ ParseLoc optionLoc; /* location of WITH TIES, if present */
114117} SelectLimit;
115118
116119/* Private struct for the result of group_clause production */
@@ -195,7 +198,8 @@ static void SplitColQualList(List *qualList,
195198static void processCASbits (int cas_bits, int location, const char *constrType,
196199 bool *deferrable, bool *initdeferred, bool *not_valid,
197200 bool *no_inherit, core_yyscan_t yyscanner);
198- static PartitionStrategy parsePartitionStrategy (char *strategy);
201+ static PartitionStrategy parsePartitionStrategy (char *strategy, int location,
202+ core_yyscan_t yyscanner);
199203static void preprocess_pubobj_list (List *pubobjspec_list,
200204 core_yyscan_t yyscanner);
201205static Node *makeRecursiveViewSelect (char *relname, List *aliases, Node *query);
@@ -3145,11 +3149,13 @@ PartitionBoundSpec:
31453149 if (n->modulus == -1 )
31463150 ereport (ERROR,
31473151 (errcode(ERRCODE_SYNTAX_ERROR),
3148- errmsg(" modulus for hash partition must be specified" )));
3152+ errmsg(" modulus for hash partition must be specified" ),
3153+ parser_errposition(@3 )));
31493154 if (n->remainder == -1 )
31503155 ereport (ERROR,
31513156 (errcode(ERRCODE_SYNTAX_ERROR),
3152- errmsg(" remainder for hash partition must be specified" )));
3157+ errmsg(" remainder for hash partition must be specified" ),
3158+ parser_errposition(@3 )));
31533159
31543160 n->location = @3 ;
31553161
@@ -4528,7 +4534,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')'
45284534 {
45294535 PartitionSpec *n = makeNode(PartitionSpec);
45304536
4531- n->strategy = parsePartitionStrategy($3 );
4537+ n->strategy = parsePartitionStrategy($3 , @3 , yyscanner );
45324538 n->partParams = $5 ;
45334539 n->location = @1 ;
45344540
@@ -5962,7 +5968,8 @@ CreateTrigStmt:
59625968 if (n->replace) /* not supported, see CreateTrigger */
59635969 ereport (ERROR,
59645970 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5965- errmsg(" CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" )));
5971+ errmsg(" CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" ),
5972+ parser_errposition(@1 )));
59665973 n->isconstraint = true ;
59675974 n->trigname = $5 ;
59685975 n->relation = $9 ;
@@ -6247,7 +6254,8 @@ CreateAssertionStmt:
62476254 {
62486255 ereport (ERROR,
62496256 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6250- errmsg(" CREATE ASSERTION is not yet implemented" )));
6257+ errmsg(" CREATE ASSERTION is not yet implemented" ),
6258+ parser_errposition(@1 )));
62516259
62526260 $$ = NULL ;
62536261 }
@@ -13156,11 +13164,13 @@ select_limit:
1315613164 {
1315713165 $$ = $1 ;
1315813166 ($$ )->limitOffset = $2 ;
13167+ ($$ )->offsetLoc = @2 ;
1315913168 }
1316013169 | offset_clause limit_clause
1316113170 {
1316213171 $$ = $2 ;
1316313172 ($$ )->limitOffset = $1 ;
13173+ ($$ )->offsetLoc = @1 ;
1316413174 }
1316513175 | limit_clause
1316613176 {
@@ -13173,6 +13183,9 @@ select_limit:
1317313183 n->limitOffset = $1 ;
1317413184 n->limitCount = NULL ;
1317513185 n->limitOption = LIMIT_OPTION_COUNT;
13186+ n->offsetLoc = @1 ;
13187+ n->countLoc = -1 ;
13188+ n->optionLoc = -1 ;
1317613189 $$ = n;
1317713190 }
1317813191 ;
@@ -13190,6 +13203,9 @@ limit_clause:
1319013203 n->limitOffset = NULL ;
1319113204 n->limitCount = $2 ;
1319213205 n->limitOption = LIMIT_OPTION_COUNT;
13206+ n->offsetLoc = -1 ;
13207+ n->countLoc = @1 ;
13208+ n->optionLoc = -1 ;
1319313209 $$ = n;
1319413210 }
1319513211 | LIMIT select_limit_value ' ,' select_offset_value
@@ -13215,6 +13231,9 @@ limit_clause:
1321513231 n->limitOffset = NULL ;
1321613232 n->limitCount = $3 ;
1321713233 n->limitOption = LIMIT_OPTION_COUNT;
13234+ n->offsetLoc = -1 ;
13235+ n->countLoc = @1 ;
13236+ n->optionLoc = -1 ;
1321813237 $$ = n;
1321913238 }
1322013239 | FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES
@@ -13224,6 +13243,9 @@ limit_clause:
1322413243 n->limitOffset = NULL ;
1322513244 n->limitCount = $3 ;
1322613245 n->limitOption = LIMIT_OPTION_WITH_TIES;
13246+ n->offsetLoc = -1 ;
13247+ n->countLoc = @1 ;
13248+ n->optionLoc = @5 ;
1322713249 $$ = n;
1322813250 }
1322913251 | FETCH first_or_next row_or_rows ONLY
@@ -13233,6 +13255,9 @@ limit_clause:
1323313255 n->limitOffset = NULL ;
1323413256 n->limitCount = makeIntConst(1 , -1 );
1323513257 n->limitOption = LIMIT_OPTION_COUNT;
13258+ n->offsetLoc = -1 ;
13259+ n->countLoc = @1 ;
13260+ n->optionLoc = -1 ;
1323613261 $$ = n;
1323713262 }
1323813263 | FETCH first_or_next row_or_rows WITH TIES
@@ -13242,6 +13267,9 @@ limit_clause:
1324213267 n->limitOffset = NULL ;
1324313268 n->limitCount = makeIntConst(1 , -1 );
1324413269 n->limitOption = LIMIT_OPTION_WITH_TIES;
13270+ n->offsetLoc = -1 ;
13271+ n->countLoc = @1 ;
13272+ n->optionLoc = @4 ;
1324513273 $$ = n;
1324613274 }
1324713275 ;
@@ -16954,8 +16982,9 @@ json_format_clause:
1695416982 encoding = JS_ENC_UTF32;
1695516983 else
1695616984 ereport (ERROR,
16957- errcode (ERRCODE_INVALID_PARAMETER_VALUE),
16958- errmsg (" unrecognized JSON encoding: %s" , $4 ));
16985+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE),
16986+ errmsg (" unrecognized JSON encoding: %s" , $4 ),
16987+ parser_errposition (@4 )));
1695916988
1696016989 $$ = (Node *) makeJsonFormat (JS_FORMAT_JSON, encoding, @1 );
1696116990 }
@@ -17457,7 +17486,8 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list
1745717486 $9 ->limitOption == LIMIT_OPTION_WITH_TIES)
1745817487 ereport (ERROR,
1745917488 (errcode (ERRCODE_SYNTAX_ERROR),
17460- errmsg (" WITH TIES cannot be specified without ORDER BY clause" )));
17489+ errmsg (" WITH TIES cannot be specified without ORDER BY clause" ),
17490+ parser_errposition ($9 ->optionLoc )));
1746117491 n->limitOption = $9 ->limitOption ;
1746217492 }
1746317493 n->lockingClause = $10 ;
@@ -18962,7 +18992,7 @@ insertSelectOptions(SelectStmt *stmt,
1896218992 ereport(ERROR,
1896318993 (errcode(ERRCODE_SYNTAX_ERROR),
1896418994 errmsg("multiple OFFSET clauses not allowed"),
18965- parser_errposition(exprLocation( limitClause->limitOffset) )));
18995+ parser_errposition(limitClause->offsetLoc )));
1896618996 stmt->limitOffset = limitClause->limitOffset;
1896718997 }
1896818998 if (limitClause && limitClause->limitCount)
@@ -18971,19 +19001,18 @@ insertSelectOptions(SelectStmt *stmt,
1897119001 ereport(ERROR,
1897219002 (errcode(ERRCODE_SYNTAX_ERROR),
1897319003 errmsg("multiple LIMIT clauses not allowed"),
18974- parser_errposition(exprLocation( limitClause->limitCount) )));
19004+ parser_errposition(limitClause->countLoc )));
1897519005 stmt->limitCount = limitClause->limitCount;
1897619006 }
1897719007 if (limitClause)
1897819008 {
18979- if (stmt->limitOption)
18980- ereport(ERROR,
18981- (errcode(ERRCODE_SYNTAX_ERROR),
18982- errmsg("multiple limit options not allowed")));
19009+ /* If there was a conflict, we must have detected it above */
19010+ Assert(!stmt->limitOption);
1898319011 if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES)
1898419012 ereport(ERROR,
1898519013 (errcode(ERRCODE_SYNTAX_ERROR),
18986- errmsg("WITH TIES cannot be specified without ORDER BY clause")));
19014+ errmsg("WITH TIES cannot be specified without ORDER BY clause"),
19015+ parser_errposition(limitClause->optionLoc)));
1898719016 if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause)
1898819017 {
1898919018 ListCell *lc;
@@ -18996,7 +19025,8 @@ insertSelectOptions(SelectStmt *stmt,
1899619025 ereport(ERROR,
1899719026 (errcode(ERRCODE_SYNTAX_ERROR),
1899819027 errmsg("%s and %s options cannot be used together",
18999- "SKIP LOCKED", "WITH TIES")));
19028+ "SKIP LOCKED", "WITH TIES"),
19029+ parser_errposition(limitClause->optionLoc)));
1900019030 }
1900119031 }
1900219032 stmt->limitOption = limitClause->limitOption;
@@ -19425,7 +19455,7 @@ processCASbits(int cas_bits, int location, const char *constrType,
1942519455 * PartitionStrategy representation, or die trying.
1942619456 */
1942719457static PartitionStrategy
19428- parsePartitionStrategy(char *strategy)
19458+ parsePartitionStrategy(char *strategy, int location, core_yyscan_t yyscanner )
1942919459{
1943019460 if (pg_strcasecmp(strategy, "list") == 0)
1943119461 return PARTITION_STRATEGY_LIST;
@@ -19436,8 +19466,8 @@ parsePartitionStrategy(char *strategy)
1943619466
1943719467 ereport(ERROR,
1943819468 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
19439- errmsg("unrecognized partitioning strategy \"%s\"",
19440- strategy )));
19469+ errmsg("unrecognized partitioning strategy \"%s\"", strategy),
19470+ parser_errposition(location )));
1944119471 return PARTITION_STRATEGY_LIST; /* keep compiler quiet */
1944219472
1944319473}
0 commit comments