Skip to content

Commit 6b0706a

Browse files
committed
Arrange for an explicit cast applied to an ARRAY[] constructor to be applied
directly to all the member expressions, instead of the previous implementation where the ARRAY[] constructor would infer a common element type and then we'd coerce the finished array after the fact. This has a number of benefits, one being that we can allow an empty ARRAY[] construct so long as its element type is specified by such a cast. Brendan Jurd, minor fixes by me.
1 parent 8759b79 commit 6b0706a

File tree

11 files changed

+311
-99
lines changed

11 files changed

+311
-99
lines changed

doc/src/sgml/syntax.sgml

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.121 2008/01/23 19:51:29 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.122 2008/03/20 21:42:47 tgl Exp $ -->
22

33
<chapter id="sql-syntax">
44
<title>SQL Syntax</title>
@@ -1305,7 +1305,7 @@ sqrt(2)
13051305

13061306
where <replaceable>aggregate_name</replaceable> is a previously
13071307
defined aggregate (possibly qualified with a schema name), and
1308-
<replaceable>expression</replaceable> is
1308+
<replaceable>expression</replaceable> is
13091309
any value expression that does not itself contain an aggregate
13101310
expression.
13111311
</para>
@@ -1335,7 +1335,7 @@ sqrt(2)
13351335
<para>
13361336
The predefined aggregate functions are described in <xref
13371337
linkend="functions-aggregate">. Other aggregate functions can be added
1338-
by the user.
1338+
by the user.
13391339
</para>
13401340

13411341
<para>
@@ -1495,9 +1495,9 @@ SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
14951495
<para>
14961496
An array constructor is an expression that builds an
14971497
array value from values for its member elements. A simple array
1498-
constructor
1498+
constructor
14991499
consists of the key word <literal>ARRAY</literal>, a left square bracket
1500-
<literal>[</>, one or more expressions (separated by commas) for the
1500+
<literal>[</>, a list of expressions (separated by commas) for the
15011501
array element values, and finally a right square bracket <literal>]</>.
15021502
For example:
15031503
<programlisting>
@@ -1507,9 +1507,22 @@ SELECT ARRAY[1,2,3+4];
15071507
{1,2,7}
15081508
(1 row)
15091509
</programlisting>
1510-
The array element type is the common type of the member expressions,
1510+
By default,
1511+
the array element type is the common type of the member expressions,
15111512
determined using the same rules as for <literal>UNION</> or
1512-
<literal>CASE</> constructs (see <xref linkend="typeconv-union-case">).
1513+
<literal>CASE</> constructs (see <xref linkend="typeconv-union-case">).
1514+
You can override this by explicitly casting the array constructor to the
1515+
desired type, for example:
1516+
<programlisting>
1517+
SELECT ARRAY[1,2,22.7]::integer[];
1518+
array
1519+
----------
1520+
{1,2,23}
1521+
(1 row)
1522+
</programlisting>
1523+
This has the same effect as casting each expression to the array
1524+
element type individually.
1525+
For more on casting, see <xref linkend="sql-syntax-type-casts">.
15131526
</para>
15141527

15151528
<para>
@@ -1534,6 +1547,8 @@ SELECT ARRAY[[1,2],[3,4]];
15341547

15351548
Since multidimensional arrays must be rectangular, inner constructors
15361549
at the same level must produce sub-arrays of identical dimensions.
1550+
Any cast applied to the outer <literal>ARRAY</> constructor propagates
1551+
automatically to all the inner constructors.
15371552
</para>
15381553

15391554
<para>
@@ -1553,6 +1568,19 @@ SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;
15531568
</programlisting>
15541569
</para>
15551570

1571+
<para>
1572+
You can construct an empty array, but since it's impossible to have an
1573+
array with no type, you must explicitly cast your empty array to the
1574+
desired type. For example:
1575+
<programlisting>
1576+
SELECT ARRAY[]::integer[];
1577+
array
1578+
-------
1579+
{}
1580+
(1 row)
1581+
</programlisting>
1582+
</para>
1583+
15561584
<para>
15571585
It is also possible to construct an array from the results of a
15581586
subquery. In this form, the array constructor is written with the

src/backend/nodes/copyfuncs.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.388 2008/02/07 20:19:47 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.389 2008/03/20 21:42:47 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1684,6 +1684,16 @@ _copyA_Indirection(A_Indirection *from)
16841684
return newnode;
16851685
}
16861686

1687+
static A_ArrayExpr *
1688+
_copyA_ArrayExpr(A_ArrayExpr *from)
1689+
{
1690+
A_ArrayExpr *newnode = makeNode(A_ArrayExpr);
1691+
1692+
COPY_NODE_FIELD(elements);
1693+
1694+
return newnode;
1695+
}
1696+
16871697
static ResTarget *
16881698
_copyResTarget(ResTarget *from)
16891699
{
@@ -3543,6 +3553,9 @@ copyObject(void *from)
35433553
case T_A_Indirection:
35443554
retval = _copyA_Indirection(from);
35453555
break;
3556+
case T_A_ArrayExpr:
3557+
retval = _copyA_ArrayExpr(from);
3558+
break;
35463559
case T_ResTarget:
35473560
retval = _copyResTarget(from);
35483561
break;

src/backend/nodes/equalfuncs.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.318 2008/02/07 20:19:47 tgl Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.319 2008/03/20 21:42:48 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -1729,6 +1729,14 @@ _equalA_Indirection(A_Indirection *a, A_Indirection *b)
17291729
return true;
17301730
}
17311731

1732+
static bool
1733+
_equalA_ArrayExpr(A_ArrayExpr *a, A_ArrayExpr *b)
1734+
{
1735+
COMPARE_NODE_FIELD(elements);
1736+
1737+
return true;
1738+
}
1739+
17321740
static bool
17331741
_equalResTarget(ResTarget *a, ResTarget *b)
17341742
{
@@ -2469,6 +2477,9 @@ equal(void *a, void *b)
24692477
case T_A_Indirection:
24702478
retval = _equalA_Indirection(a, b);
24712479
break;
2480+
case T_A_ArrayExpr:
2481+
retval = _equalA_ArrayExpr(a, b);
2482+
break;
24722483
case T_ResTarget:
24732484
retval = _equalResTarget(a, b);
24742485
break;

src/backend/nodes/outfuncs.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.322 2008/01/09 08:46:44 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.323 2008/03/20 21:42:48 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1971,6 +1971,14 @@ _outA_Indirection(StringInfo str, A_Indirection *node)
19711971
WRITE_NODE_FIELD(indirection);
19721972
}
19731973

1974+
static void
1975+
_outA_ArrayExpr(StringInfo str, A_ArrayExpr *node)
1976+
{
1977+
WRITE_NODE_TYPE("A_ARRAYEXPR");
1978+
1979+
WRITE_NODE_FIELD(elements);
1980+
}
1981+
19741982
static void
19751983
_outResTarget(StringInfo str, ResTarget *node)
19761984
{
@@ -2417,6 +2425,9 @@ _outNode(StringInfo str, void *obj)
24172425
case T_A_Indirection:
24182426
_outA_Indirection(str, obj);
24192427
break;
2428+
case T_A_ArrayExpr:
2429+
_outA_ArrayExpr(str, obj);
2430+
break;
24202431
case T_ResTarget:
24212432
_outResTarget(str, obj);
24222433
break;

src/backend/parser/gram.y

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.608 2008/03/19 18:38:30 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.609 2008/03/20 21:42:48 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -107,6 +107,7 @@ static void insertSelectOptions(SelectStmt *stmt,
107107
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
108108
static Node *doNegate(Node *n, int location);
109109
static void doNegateFloat(Value *v);
110+
static Node *makeAArrayExpr(List *elements);
110111
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args);
111112

112113
%}
@@ -8429,45 +8430,43 @@ expr_list: a_expr
84298430
}
84308431
;
84318432

8432-
extract_list:
8433-
extract_arg FROM a_expr
8434-
{
8435-
A_Const *n = makeNode(A_Const);
8436-
n->val.type = T_String;
8437-
n->val.val.str = $1;
8438-
$$ = list_make2((Node *) n, $3);
8439-
}
8440-
| /*EMPTY*/ { $$ = NIL; }
8441-
;
8442-
84438433
type_list: Typename { $$ = list_make1($1); }
84448434
| type_list ',' Typename { $$ = lappend($1, $3); }
84458435
;
84468436

8447-
array_expr_list: array_expr
8448-
{ $$ = list_make1($1); }
8449-
| array_expr_list ',' array_expr
8450-
{ $$ = lappend($1, $3); }
8451-
;
8452-
84538437
array_expr: '[' expr_list ']'
84548438
{
8455-
ArrayExpr *n = makeNode(ArrayExpr);
8456-
n->elements = $2;
8457-
$$ = (Node *)n;
8439+
$$ = makeAArrayExpr($2);
84588440
}
84598441
| '[' array_expr_list ']'
84608442
{
8461-
ArrayExpr *n = makeNode(ArrayExpr);
8462-
n->elements = $2;
8463-
$$ = (Node *)n;
8443+
$$ = makeAArrayExpr($2);
8444+
}
8445+
| '[' ']'
8446+
{
8447+
$$ = makeAArrayExpr(NIL);
8448+
}
8449+
;
8450+
8451+
array_expr_list: array_expr { $$ = list_make1($1); }
8452+
| array_expr_list ',' array_expr { $$ = lappend($1, $3); }
8453+
;
8454+
8455+
8456+
extract_list:
8457+
extract_arg FROM a_expr
8458+
{
8459+
A_Const *n = makeNode(A_Const);
8460+
n->val.type = T_String;
8461+
n->val.val.str = $1;
8462+
$$ = list_make2((Node *) n, $3);
84648463
}
8464+
| /*EMPTY*/ { $$ = NIL; }
84658465
;
84668466

84678467
/* Allow delimited string SCONST in extract_arg as an SQL extension.
84688468
* - thomas 2001-04-12
84698469
*/
8470-
84718470
extract_arg:
84728471
IDENT { $$ = $1; }
84738472
| YEAR_P { $$ = "year"; }
@@ -9502,13 +9501,6 @@ makeColumnRef(char *relname, List *indirection, int location)
95029501
static Node *
95039502
makeTypeCast(Node *arg, TypeName *typename)
95049503
{
9505-
/*
9506-
* Simply generate a TypeCast node.
9507-
*
9508-
* Earlier we would determine whether an A_Const would
9509-
* be acceptable, however Domains require coerce_type()
9510-
* to process them -- applying constraints as required.
9511-
*/
95129504
TypeCast *n = makeNode(TypeCast);
95139505
n->arg = arg;
95149506
n->typename = typename;
@@ -9582,7 +9574,7 @@ makeBoolAConst(bool state)
95829574
{
95839575
A_Const *n = makeNode(A_Const);
95849576
n->val.type = T_String;
9585-
n->val.val.str = (state? "t": "f");
9577+
n->val.val.str = (state ? "t" : "f");
95869578
n->typename = SystemTypeName("bool");
95879579
return n;
95889580
}
@@ -9763,15 +9755,6 @@ SystemTypeName(char *name)
97639755
makeString(name)));
97649756
}
97659757

9766-
/* parser_init()
9767-
* Initialize to parse one query string
9768-
*/
9769-
void
9770-
parser_init(void)
9771-
{
9772-
QueryIsRule = FALSE;
9773-
}
9774-
97759758
/* doNegate()
97769759
* Handle negation of a numeric constant.
97779760
*
@@ -9827,6 +9810,15 @@ doNegateFloat(Value *v)
98279810
}
98289811
}
98299812

9813+
static Node *
9814+
makeAArrayExpr(List *elements)
9815+
{
9816+
A_ArrayExpr *n = makeNode(A_ArrayExpr);
9817+
9818+
n->elements = elements;
9819+
return (Node *) n;
9820+
}
9821+
98309822
static Node *
98319823
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
98329824
{
@@ -9844,6 +9836,15 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
98449836
return (Node *) x;
98459837
}
98469838

9839+
/* parser_init()
9840+
* Initialize to parse one query string
9841+
*/
9842+
void
9843+
parser_init(void)
9844+
{
9845+
QueryIsRule = FALSE;
9846+
}
9847+
98479848
/*
98489849
* Must undefine base_yylex before including scan.c, since we want it
98499850
* to create the function base_yylex not filtered_base_yylex.

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