Print out error position for CREATE DOMAIN
authorMichael Paquier <michael@paquier.xyz>
Mon, 16 Dec 2024 05:52:11 +0000 (14:52 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 16 Dec 2024 05:52:11 +0000 (14:52 +0900)
This is simply done by pushing down the ParseState available in
ProcessUtility() to DefineDomain(), giving more information about the
position of an error when running a CREATE DOMAIN query.

Most of the queries impacted by this change have been added previously
in 0172b4c9449e.

Author: Kirill Reshke, Jian He
Reviewed-by: Álvaro Herrera, Tom Lane, Michael Paquier
Discussion: https://postgr.es/m/CALdSSPhqfvKbDwqJaY=yEePi_aq61GmMpW88i6ZH7CMG_2Z4Cg@mail.gmail.com

src/backend/commands/typecmds.c
src/backend/tcop/utility.c
src/include/commands/typecmds.h
src/test/regress/expected/collate.icu.utf8.out
src/test/regress/expected/collate.linux.utf8.out
src/test/regress/expected/collate.out
src/test/regress/expected/collate.windows.win1252.out
src/test/regress/expected/domain.out

index da591c0922b490475002469290d3bf34ff22cc74..6127313956033e2800068c96013814f45a1593c9 100644 (file)
@@ -694,7 +694,7 @@ RemoveTypeById(Oid typeOid)
  *     Registers a new domain.
  */
 ObjectAddress
-DefineDomain(CreateDomainStmt *stmt)
+DefineDomain(ParseState *pstate, CreateDomainStmt *stmt)
 {
    char       *domainName;
    char       *domainArrayName;
@@ -761,7 +761,7 @@ DefineDomain(CreateDomainStmt *stmt)
    /*
     * Look up the base type.
     */
-   typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
+   typeTup = typenameType(pstate, stmt->typeName, &basetypeMod);
    baseType = (Form_pg_type) GETSTRUCT(typeTup);
    basetypeoid = baseType->oid;
 
@@ -783,7 +783,8 @@ DefineDomain(CreateDomainStmt *stmt)
        ereport(ERROR,
                (errcode(ERRCODE_DATATYPE_MISMATCH),
                 errmsg("\"%s\" is not a valid base type for a domain",
-                       TypeNameToString(stmt->typeName))));
+                       TypeNameToString(stmt->typeName)),
+                parser_errposition(pstate, stmt->typeName->location)));
 
    aclresult = object_aclcheck(TypeRelationId, basetypeoid, GetUserId(), ACL_USAGE);
    if (aclresult != ACLCHECK_OK)
@@ -809,7 +810,8 @@ DefineDomain(CreateDomainStmt *stmt)
        ereport(ERROR,
                (errcode(ERRCODE_DATATYPE_MISMATCH),
                 errmsg("collations are not supported by type %s",
-                       format_type_be(basetypeoid))));
+                       format_type_be(basetypeoid)),
+                parser_errposition(pstate, stmt->typeName->location)));
 
    /* passed by value */
    byValue = baseType->typbyval;
@@ -879,18 +881,15 @@ DefineDomain(CreateDomainStmt *stmt)
                 */
                if (saw_default)
                    ereport(ERROR,
-                           (errcode(ERRCODE_SYNTAX_ERROR),
-                            errmsg("multiple default expressions")));
+                           errcode(ERRCODE_SYNTAX_ERROR),
+                           errmsg("multiple default expressions"),
+                           parser_errposition(pstate, constr->location));
                saw_default = true;
 
                if (constr->raw_expr)
                {
-                   ParseState *pstate;
                    Node       *defaultExpr;
 
-                   /* Create a dummy ParseState for transformExpr */
-                   pstate = make_parsestate(NULL);
-
                    /*
                     * Cook the constr->raw_expr into an expression. Note:
                     * name is strictly for error message
@@ -942,12 +941,14 @@ DefineDomain(CreateDomainStmt *stmt)
            case CONSTR_NOTNULL:
                if (nullDefined && !typNotNull)
                    ereport(ERROR,
-                           (errcode(ERRCODE_SYNTAX_ERROR),
-                            errmsg("conflicting NULL/NOT NULL constraints")));
+                           errcode(ERRCODE_SYNTAX_ERROR),
+                           errmsg("conflicting NULL/NOT NULL constraints"),
+                           parser_errposition(pstate, constr->location));
                if (constr->is_no_inherit)
                    ereport(ERROR,
                            errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                           errmsg("not-null constraints for domains cannot be marked NO INHERIT"));
+                           errmsg("not-null constraints for domains cannot be marked NO INHERIT"),
+                           parser_errposition(pstate, constr->location));
                typNotNull = true;
                nullDefined = true;
                break;
@@ -955,8 +956,9 @@ DefineDomain(CreateDomainStmt *stmt)
            case CONSTR_NULL:
                if (nullDefined && typNotNull)
                    ereport(ERROR,
-                           (errcode(ERRCODE_SYNTAX_ERROR),
-                            errmsg("conflicting NULL/NOT NULL constraints")));
+                           errcode(ERRCODE_SYNTAX_ERROR),
+                           errmsg("conflicting NULL/NOT NULL constraints"),
+                           parser_errposition(pstate, constr->location));
                typNotNull = false;
                nullDefined = true;
                break;
@@ -971,8 +973,10 @@ DefineDomain(CreateDomainStmt *stmt)
                 */
                if (constr->is_no_inherit)
                    ereport(ERROR,
-                           (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                            errmsg("check constraints for domains cannot be marked NO INHERIT")));
+                           errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                           errmsg("check constraints for domains cannot be marked NO INHERIT"),
+                           parser_errposition(pstate, constr->location));
+
                break;
 
                /*
@@ -980,26 +984,30 @@ DefineDomain(CreateDomainStmt *stmt)
                 */
            case CONSTR_UNIQUE:
                ereport(ERROR,
-                       (errcode(ERRCODE_SYNTAX_ERROR),
-                        errmsg("unique constraints not possible for domains")));
+                       errcode(ERRCODE_SYNTAX_ERROR),
+                       errmsg("unique constraints not possible for domains"),
+                       parser_errposition(pstate, constr->location));
                break;
 
            case CONSTR_PRIMARY:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
-                        errmsg("primary key constraints not possible for domains")));
+                        errmsg("primary key constraints not possible for domains"),
+                        parser_errposition(pstate, constr->location)));
                break;
 
            case CONSTR_EXCLUSION:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
-                        errmsg("exclusion constraints not possible for domains")));
+                        errmsg("exclusion constraints not possible for domains"),
+                        parser_errposition(pstate, constr->location)));
                break;
 
            case CONSTR_FOREIGN:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
-                        errmsg("foreign key constraints not possible for domains")));
+                        errmsg("foreign key constraints not possible for domains"),
+                        parser_errposition(pstate, constr->location)));
                break;
 
            case CONSTR_ATTR_DEFERRABLE:
@@ -1008,14 +1016,16 @@ DefineDomain(CreateDomainStmt *stmt)
            case CONSTR_ATTR_IMMEDIATE:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("specifying constraint deferrability not supported for domains")));
+                        errmsg("specifying constraint deferrability not supported for domains"),
+                        parser_errposition(pstate, constr->location)));
                break;
 
            case CONSTR_GENERATED:
            case CONSTR_IDENTITY:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("specifying GENERATED not supported for domains")));
+                        errmsg("specifying GENERATED not supported for domains"),
+                        parser_errposition(pstate, constr->location)));
                break;
 
                /* no default, to let compiler warn about missing case */
index f28bf37105964547d37dc691bb14ed9d5a0617a6..33dea5a781c72ccfc0d20184546ed06ea0d0d9b0 100644 (file)
@@ -1712,7 +1712,7 @@ ProcessUtilitySlow(ParseState *pstate,
                break;
 
            case T_CreateDomainStmt:
-               address = DefineDomain((CreateDomainStmt *) parsetree);
+               address = DefineDomain(pstate, (CreateDomainStmt *) parsetree);
                break;
 
            case T_CreateConversionStmt:
index e1b02927c4bab5352ff85ef5e19d7186b1d90676..cb30d1a2583918882b91cca4f07eba86383784f3 100644 (file)
@@ -23,7 +23,7 @@
 
 extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameters);
 extern void RemoveTypeById(Oid typeOid);
-extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
+extern ObjectAddress DefineDomain(ParseState *pstate, CreateDomainStmt *stmt);
 extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
 extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
 extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
index 6cbadafcfbf6581f5fe540f389b91785992174ee..d4f327636fd5fe01402e2ae99ccca3f1fb302231 100644 (file)
@@ -120,6 +120,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e...
 CREATE DOMAIN testdomain_sv AS text COLLATE "sv-x-icu";
 CREATE DOMAIN testdomain_i AS int COLLATE "sv-x-icu"; -- fails
 ERROR:  collations are not supported by type integer
+LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv-x-icu";
+                                      ^
 CREATE TABLE collate_test4 (
     a int,
     b testdomain_sv
index 01664f7c1b544db0d506071c0bab0e7efaf373b0..fbaab7cdf83306b1f9362bef96eb4a8e641ffb41 100644 (file)
@@ -122,6 +122,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e...
 CREATE DOMAIN testdomain_sv AS text COLLATE "sv_SE";
 CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; -- fails
 ERROR:  collations are not supported by type integer
+LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE";
+                                      ^
 CREATE TABLE collate_test4 (
     a int,
     b testdomain_sv
index 593a62263766699f2f037acc9ac684fbfbc13fca..bf72908fbd39b2e67415dfeb7551263b4179079b 100644 (file)
@@ -73,6 +73,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "P...
 CREATE DOMAIN testdomain_p AS text COLLATE "POSIX";
 CREATE DOMAIN testdomain_i AS int COLLATE "POSIX"; -- fail
 ERROR:  collations are not supported by type integer
+LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "POSIX";
+                                      ^
 CREATE TABLE collate_test4 (
     a int,
     b testdomain_p
index 31f794988b3c090923af6db2154018e463f39479..4644f56b31dc1f28c38b7fa45e1d8b6728f4c473 100644 (file)
@@ -124,6 +124,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e...
 CREATE DOMAIN testdomain_sv AS text COLLATE "sv_SE";
 CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; -- fails
 ERROR:  collations are not supported by type integer
+LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE";
+                                      ^
 CREATE TABLE collate_test4 (
     a int,
     b testdomain_sv
index d03ab128e48d1f9fae25cf6f2c888613d8761235..7a2a717aeaecfa618aead714ccc9465a8c7c56a5 100644 (file)
@@ -18,30 +18,56 @@ ERROR:  type "domaindroptest" does not exist
 -- some error cases
 create domain d_fail as no_such_type;
 ERROR:  type "no_such_type" does not exist
+LINE 1: create domain d_fail as no_such_type;
+                                ^
 create domain d_fail as int constraint cc REFERENCES this_table_not_exists(i);
 ERROR:  foreign key constraints not possible for domains
+LINE 1: create domain d_fail as int constraint cc REFERENCES this_ta...
+                                    ^
 create domain d_fail as int4 not null no inherit;
 ERROR:  not-null constraints for domains cannot be marked NO INHERIT
+LINE 1: create domain d_fail as int4 not null no inherit;
+                                     ^
 create domain d_fail as int4 not null null;
 ERROR:  conflicting NULL/NOT NULL constraints
+LINE 1: create domain d_fail as int4 not null null;
+                                              ^
 create domain d_fail as int4 not null default 3 default 3;
 ERROR:  multiple default expressions
+LINE 1: create domain d_fail as int4 not null default 3 default 3;
+                                                        ^
 create domain d_fail int4 DEFAULT 3 + 'h';
 ERROR:  invalid input syntax for type integer: "h"
+LINE 1: create domain d_fail int4 DEFAULT 3 + 'h';
+                                              ^
 create domain d_fail int4 collate "C";
 ERROR:  collations are not supported by type integer
+LINE 1: create domain d_fail int4 collate "C";
+                             ^
 create domain d_fail as anyelement;
 ERROR:  "anyelement" is not a valid base type for a domain
+LINE 1: create domain d_fail as anyelement;
+                                ^
 create domain d_fail as int4 unique;
 ERROR:  unique constraints not possible for domains
+LINE 1: create domain d_fail as int4 unique;
+                                     ^
 create domain d_fail as int4 PRIMARY key;
 ERROR:  primary key constraints not possible for domains
+LINE 1: create domain d_fail as int4 PRIMARY key;
+                                     ^
 create domain d_fail as int4 constraint cc generated by default as identity;
 ERROR:  specifying GENERATED not supported for domains
+LINE 1: create domain d_fail as int4 constraint cc generated by defa...
+                                     ^
 create domain d_fail as int4 constraint cc check (values > 1) no inherit;
 ERROR:  check constraints for domains cannot be marked NO INHERIT
+LINE 1: create domain d_fail as int4 constraint cc check (values > 1...
+                                     ^
 create domain d_fail as int4 constraint cc check (values > 1) deferrable;
 ERROR:  specifying constraint deferrability not supported for domains
+LINE 1: ...n d_fail as int4 constraint cc check (values > 1) deferrable...
+                                                             ^
 -- Test domain input.
 -- Note: the point of checking both INSERT and COPY FROM is that INSERT
 -- exercises CoerceToDomain while COPY exercises domain_in.