diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-06-15 20:56:52 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-06-15 20:56:52 +0000 |
commit | 23347231a53bc373710db71559a194d87f60a7cb (patch) | |
tree | 04c6e8af0afb299a0a112da5c92124a377d1abb3 /src/backend/parser | |
parent | 839fcc9fd09452c406b67fb2e1af87d55d0ad4e2 (diff) | |
download | postgresql-23347231a53bc373710db71559a194d87f60a7cb.tar.gz postgresql-23347231a53bc373710db71559a194d87f60a7cb.zip |
Tweak the API for per-datatype typmodin functions so that they are passed
an array of strings rather than an array of integers, and allow any simple
constant or identifier to be used in typmods; for example
create table foo (f1 widget(42,'23skidoo',point));
Of course the typmodin function has still got to pack this info into a
non-negative int32 for storage, but it's still a useful improvement in
flexibility, especially considering that you can do nearly anything if you
are willing to keep the info in a side table. We can get away with this
change since we have not yet released a version providing user-definable
typmods. Per discussion.
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_type.c | 51 |
2 files changed, 41 insertions, 14 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index da3afda8fb3..8ec562c5e31 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.593 2007/06/11 22:22:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.594 2007/06/15 20:56:49 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -6695,7 +6695,7 @@ ConstTypename: * by the standard, including qualified names. We also allow type modifiers. * To avoid parsing conflicts against function invocations, the modifiers * have to be shown as expr_list here, but parse analysis will only accept - * integer constants for them. + * constants for them. */ GenericType: type_function_name opt_type_modifiers diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index d3198f0496a..f86dd43d548 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.90 2007/05/11 17:57:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.91 2007/06/15 20:56:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -289,28 +289,55 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename, parser_errposition(pstate, typename->location))); /* - * Convert the list of (raw grammar output) expressions to an integer - * array. Currently, we only allow simple integer constants, though - * possibly this could be extended. + * Convert the list of raw-grammar-output expressions to a cstring array. + * Currently, we allow simple numeric constants, string literals, and + * identifiers; possibly this list could be extended. */ datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum)); n = 0; foreach(l, typename->typmods) { - A_Const *ac = (A_Const *) lfirst(l); + Node *tm = (Node *) lfirst(l); + char *cstr = NULL; - if (!IsA(ac, A_Const) || - !IsA(&ac->val, Integer)) + if (IsA(tm, A_Const)) + { + A_Const *ac = (A_Const *) tm; + + /* + * The grammar hands back some integers with ::int4 attached, + * so allow a cast decoration if it's an Integer value, but + * not otherwise. + */ + if (IsA(&ac->val, Integer)) + { + cstr = (char *) palloc(32); + snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); + } + else if (ac->typename == NULL) /* no casts allowed */ + { + /* otherwise we can just use the str field directly. */ + cstr = ac->val.val.str; + } + } + else if (IsA(tm, ColumnRef)) + { + ColumnRef *cr = (ColumnRef *) tm; + + if (list_length(cr->fields) == 1) + cstr = strVal(linitial(cr->fields)); + } + if (!cstr) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("type modifiers must be integer constants"), + errmsg("type modifiers must be simple constants or identifiers"), parser_errposition(pstate, typename->location))); - datums[n++] = Int32GetDatum(ac->val.val.ival); + datums[n++] = CStringGetDatum(cstr); } - /* hardwired knowledge about int4's representation details here */ - arrtypmod = construct_array(datums, n, INT4OID, - sizeof(int4), true, 'i'); + /* hardwired knowledge about cstring's representation details here */ + arrtypmod = construct_array(datums, n, CSTRINGOID, + -2, false, 'c'); result = DatumGetInt32(OidFunctionCall1(typmodin, PointerGetDatum(arrtypmod))); |