Skip to content

Commit b8d226b

Browse files
committed
Setup cursor position for schema-qualified elements
This makes any errors thrown while looking up such schemas report the position of the error. Author: Ryan Kelly Reviewed by: Jeevan Chalke, Tom Lane
1 parent 0d83138 commit b8d226b

File tree

5 files changed

+43
-10
lines changed

5 files changed

+43
-10
lines changed

src/backend/parser/parse_func.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
9393
Oid vatype;
9494
FuncDetailCode fdresult;
9595
char aggkind = 0;
96+
ParseCallbackState pcbstate;
9697

9798
/*
9899
* If there's an aggregate filter, transform it using transformWhereClause
@@ -235,12 +236,18 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
235236
* type. We'll fix up the variadic case below. We may also have to deal
236237
* with default arguments.
237238
*/
239+
240+
setup_parser_errposition_callback(&pcbstate, pstate, location);
241+
238242
fdresult = func_get_detail(funcname, fargs, argnames, nargs,
239243
actual_arg_types,
240244
!func_variadic, true,
241245
&funcid, &rettype, &retset,
242246
&nvargs, &vatype,
243247
&declared_arg_types, &argdefaults);
248+
249+
cancel_parser_errposition_callback(&pcbstate);
250+
244251
if (fdresult == FUNCDETAIL_COERCION)
245252
{
246253
/*

src/backend/parser/parse_oper.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ static const char *op_signature_string(List *op, char oprkind,
7575
static void op_error(ParseState *pstate, List *op, char oprkind,
7676
Oid arg1, Oid arg2,
7777
FuncDetailCode fdresult, int location);
78-
static bool make_oper_cache_key(OprCacheKey *key, List *opname,
79-
Oid ltypeId, Oid rtypeId);
78+
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
79+
List *opname, Oid ltypeId, Oid rtypeId,
80+
int location);
8081
static Oid find_oper_cache_entry(OprCacheKey *key);
8182
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
8283
static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
@@ -383,7 +384,8 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
383384
/*
384385
* Try to find the mapping in the lookaside cache.
385386
*/
386-
key_ok = make_oper_cache_key(&key, opname, ltypeId, rtypeId);
387+
key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
388+
387389
if (key_ok)
388390
{
389391
operOid = find_oper_cache_entry(&key);
@@ -529,7 +531,8 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
529531
/*
530532
* Try to find the mapping in the lookaside cache.
531533
*/
532-
key_ok = make_oper_cache_key(&key, op, arg, InvalidOid);
534+
key_ok = make_oper_cache_key(pstate, &key, op, arg, InvalidOid, location);
535+
533536
if (key_ok)
534537
{
535538
operOid = find_oper_cache_entry(&key);
@@ -607,7 +610,8 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
607610
/*
608611
* Try to find the mapping in the lookaside cache.
609612
*/
610-
key_ok = make_oper_cache_key(&key, op, InvalidOid, arg);
613+
key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
614+
611615
if (key_ok)
612616
{
613617
operOid = find_oper_cache_entry(&key);
@@ -1006,9 +1010,13 @@ static HTAB *OprCacheHash = NULL;
10061010
*
10071011
* Returns TRUE if successful, FALSE if the search_path overflowed
10081012
* (hence no caching is possible).
1013+
*
1014+
* pstate/location are used only to report the error position; pass NULL/-1
1015+
* if not available.
10091016
*/
10101017
static bool
1011-
make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId)
1018+
make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname,
1019+
Oid ltypeId, Oid rtypeId, int location)
10121020
{
10131021
char *schemaname;
10141022
char *opername;
@@ -1026,8 +1034,12 @@ make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId)
10261034

10271035
if (schemaname)
10281036
{
1037+
ParseCallbackState pcbstate;
1038+
10291039
/* search only in exact schema given */
1040+
setup_parser_errposition_callback(&pcbstate, pstate, location);
10301041
key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1042+
cancel_parser_errposition_callback(&pcbstate);
10311043
}
10321044
else
10331045
{

src/backend/parser/parse_type.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
156156
{
157157
/* Look in specific schema only */
158158
Oid namespaceId;
159+
ParseCallbackState pcbstate;
160+
161+
setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
159162

160163
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
161164
if (OidIsValid(namespaceId))
@@ -164,6 +167,8 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
164167
ObjectIdGetDatum(namespaceId));
165168
else
166169
typoid = InvalidOid;
170+
171+
cancel_parser_errposition_callback(&pcbstate);
167172
}
168173
else
169174
{

src/backend/parser/parse_utilcmd.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,22 +149,30 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
149149
ListCell *elements;
150150
Oid namespaceid;
151151
Oid existing_relid;
152+
ParseCallbackState pcbstate;
152153

153154
/*
154155
* We must not scribble on the passed-in CreateStmt, so copy it. (This is
155156
* overkill, but easy.)
156157
*/
157158
stmt = (CreateStmt *) copyObject(stmt);
158159

160+
/* Set up pstate */
161+
pstate = make_parsestate(NULL);
162+
pstate->p_sourcetext = queryString;
163+
159164
/*
160165
* Look up the creation namespace. This also checks permissions on the
161166
* target namespace, locks it against concurrent drops, checks for a
162167
* preexisting relation in that namespace with the same name, and updates
163168
* stmt->relation->relpersistence if the selected namespace is temporary.
164169
*/
170+
setup_parser_errposition_callback(&pcbstate, pstate,
171+
stmt->relation->location);
165172
namespaceid =
166173
RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
167174
&existing_relid);
175+
cancel_parser_errposition_callback(&pcbstate);
168176

169177
/*
170178
* If the relation already exists and the user specified "IF NOT EXISTS",
@@ -190,10 +198,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
190198
&& stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
191199
stmt->relation->schemaname = get_namespace_name(namespaceid);
192200

193-
/* Set up pstate and CreateStmtContext */
194-
pstate = make_parsestate(NULL);
195-
pstate->p_sourcetext = queryString;
196-
201+
/* Set up CreateStmtContext */
197202
cxt.pstate = pstate;
198203
if (IsA(stmt, CreateForeignTableStmt))
199204
{

src/test/regress/expected/create_table.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,15 @@ INSERT INTO unlogged1 VALUES (42);
212212
CREATE UNLOGGED TABLE public.unlogged2 (a int primary key); -- also OK
213213
CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key); -- not OK
214214
ERROR: only temporary relations may be created in temporary schemas
215+
LINE 1: CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key);
216+
^
215217
CREATE TABLE pg_temp.implicitly_temp (a int primary key); -- OK
216218
CREATE TEMP TABLE explicitly_temp (a int primary key); -- also OK
217219
CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK
218220
CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
219221
ERROR: cannot create temporary relation in non-temporary schema
222+
LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key);
223+
^
220224
DROP TABLE unlogged1, public.unlogged2;
221225
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
222226
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy