]> granicus.if.org Git - postgresql/commitdiff
Setup cursor position for schema-qualified elements
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 18 Mar 2015 17:48:02 +0000 (14:48 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 18 Mar 2015 17:48:02 +0000 (14:48 -0300)
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

src/backend/parser/parse_func.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_type.c
src/backend/parser/parse_utilcmd.c
src/test/regress/expected/create_table.out

index 53bbaecac39e6319fe5af1dfe92b611a8684bc5e..1385776f6bd9cf73747fcea78ed97e487b6624d5 100644 (file)
@@ -93,6 +93,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
        Oid                     vatype;
        FuncDetailCode fdresult;
        char            aggkind = 0;
+       ParseCallbackState pcbstate;
 
        /*
         * If there's an aggregate filter, transform it using transformWhereClause
@@ -235,12 +236,18 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
         * type.  We'll fix up the variadic case below.  We may also have to deal
         * with default arguments.
         */
+
+       setup_parser_errposition_callback(&pcbstate, pstate, location);
+
        fdresult = func_get_detail(funcname, fargs, argnames, nargs,
                                                           actual_arg_types,
                                                           !func_variadic, true,
                                                           &funcid, &rettype, &retset,
                                                           &nvargs, &vatype,
                                                           &declared_arg_types, &argdefaults);
+
+       cancel_parser_errposition_callback(&pcbstate);
+
        if (fdresult == FUNCDETAIL_COERCION)
        {
                /*
index 10de97b772963605dea73e01453b3e8b6c42f381..553260c835be0794f19870ce64a3fa66bff038e0 100644 (file)
@@ -75,8 +75,9 @@ static const char *op_signature_string(List *op, char oprkind,
 static void op_error(ParseState *pstate, List *op, char oprkind,
                 Oid arg1, Oid arg2,
                 FuncDetailCode fdresult, int location);
-static bool make_oper_cache_key(OprCacheKey *key, List *opname,
-                                       Oid ltypeId, Oid rtypeId);
+static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
+                                       List *opname, Oid ltypeId, Oid rtypeId,
+                                       int location);
 static Oid     find_oper_cache_entry(OprCacheKey *key);
 static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
 static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
@@ -383,7 +384,8 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
        /*
         * Try to find the mapping in the lookaside cache.
         */
-       key_ok = make_oper_cache_key(&key, opname, ltypeId, rtypeId);
+       key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
+
        if (key_ok)
        {
                operOid = find_oper_cache_entry(&key);
@@ -529,7 +531,8 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
        /*
         * Try to find the mapping in the lookaside cache.
         */
-       key_ok = make_oper_cache_key(&key, op, arg, InvalidOid);
+       key_ok = make_oper_cache_key(pstate, &key, op, arg, InvalidOid, location);
+
        if (key_ok)
        {
                operOid = find_oper_cache_entry(&key);
@@ -607,7 +610,8 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
        /*
         * Try to find the mapping in the lookaside cache.
         */
-       key_ok = make_oper_cache_key(&key, op, InvalidOid, arg);
+       key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
+
        if (key_ok)
        {
                operOid = find_oper_cache_entry(&key);
@@ -1006,9 +1010,13 @@ static HTAB *OprCacheHash = NULL;
  *
  * Returns TRUE if successful, FALSE if the search_path overflowed
  * (hence no caching is possible).
+ *
+ * pstate/location are used only to report the error position; pass NULL/-1
+ * if not available.
  */
 static bool
-make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId)
+make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname,
+                                       Oid ltypeId, Oid rtypeId, int location)
 {
        char       *schemaname;
        char       *opername;
@@ -1026,8 +1034,12 @@ make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId)
 
        if (schemaname)
        {
+               ParseCallbackState pcbstate;
+
                /* search only in exact schema given */
+               setup_parser_errposition_callback(&pcbstate, pstate, location);
                key->search_path[0] = LookupExplicitNamespace(schemaname, false);
+               cancel_parser_errposition_callback(&pcbstate);
        }
        else
        {
index ca5fbed34f484f6a2e64030bc03e1b9adf9685e0..1ba6ca76f424ac22673708715211788a4d54ff86 100644 (file)
@@ -156,6 +156,9 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
                {
                        /* Look in specific schema only */
                        Oid                     namespaceId;
+                       ParseCallbackState pcbstate;
+
+                       setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
 
                        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
                        if (OidIsValid(namespaceId))
@@ -164,6 +167,8 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
                                                                                 ObjectIdGetDatum(namespaceId));
                        else
                                typoid = InvalidOid;
+
+                       cancel_parser_errposition_callback(&pcbstate);
                }
                else
                {
index 1e6da9cc40e397bed92a888a91c32b99b2fed003..1bbed9582c988e97692d9600f4822f3187725072 100644 (file)
@@ -149,6 +149,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
        ListCell   *elements;
        Oid                     namespaceid;
        Oid                     existing_relid;
+       ParseCallbackState pcbstate;
 
        /*
         * We must not scribble on the passed-in CreateStmt, so copy it.  (This is
@@ -156,15 +157,22 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
         */
        stmt = (CreateStmt *) copyObject(stmt);
 
+       /* Set up pstate */
+       pstate = make_parsestate(NULL);
+       pstate->p_sourcetext = queryString;
+
        /*
         * Look up the creation namespace.  This also checks permissions on the
         * target namespace, locks it against concurrent drops, checks for a
         * preexisting relation in that namespace with the same name, and updates
         * stmt->relation->relpersistence if the selected namespace is temporary.
         */
+       setup_parser_errposition_callback(&pcbstate, pstate,
+                                                                         stmt->relation->location);
        namespaceid =
                RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
                                                                                         &existing_relid);
+       cancel_parser_errposition_callback(&pcbstate);
 
        /*
         * If the relation already exists and the user specified "IF NOT EXISTS",
@@ -190,10 +198,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
                && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
                stmt->relation->schemaname = get_namespace_name(namespaceid);
 
-       /* Set up pstate and CreateStmtContext */
-       pstate = make_parsestate(NULL);
-       pstate->p_sourcetext = queryString;
-
+       /* Set up CreateStmtContext */
        cxt.pstate = pstate;
        if (IsA(stmt, CreateForeignTableStmt))
        {
index 35451d5af26774543a6b7ddbbbfa010fb9ba36e4..34b5fc113d09b06b5a084e710fe07daab35efd08 100644 (file)
@@ -212,11 +212,15 @@ INSERT INTO unlogged1 VALUES (42);
 CREATE UNLOGGED TABLE public.unlogged2 (a int primary key);            -- also OK
 CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key);   -- not OK
 ERROR:  only temporary relations may be created in temporary schemas
+LINE 1: CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key);
+                              ^
 CREATE TABLE pg_temp.implicitly_temp (a int primary key);              -- OK
 CREATE TEMP TABLE explicitly_temp (a int primary key);                 -- also OK
 CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key);             -- also OK
 CREATE TEMP TABLE public.temp_to_perm (a int primary key);             -- not OK
 ERROR:  cannot create temporary relation in non-temporary schema
+LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key);
+                          ^
 DROP TABLE unlogged1, public.unlogged2;
 CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';