Skip to content

Commit 36ce6d4

Browse files
committed
Support subscripts on bare column names.
1 parent f9e2c7f commit 36ce6d4

File tree

1 file changed

+73
-116
lines changed

1 file changed

+73
-116
lines changed

src/backend/parser/parse_expr.c

Lines changed: 73 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.52 1999/07/16 04:59:32 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.53 1999/07/16 22:32:25 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -30,7 +30,10 @@
3030
#include "utils/builtins.h"
3131

3232
static Node *parser_typecast(Value *expr, TypeName *typename, int32 atttypmod);
33-
static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
33+
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
34+
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
35+
static Node *transformIndirection(ParseState *pstate, Node *basenode,
36+
List *indirection, int precedence);
3437

3538
/*
3639
* transformExpr -
@@ -51,45 +54,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
5154
{
5255
case T_Attr:
5356
{
54-
Attr *att = (Attr *) expr;
55-
Node *temp;
56-
57-
/* what if att.attrs == "*"? */
58-
temp = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,
59-
precedence);
60-
if (att->indirection != NIL)
61-
{
62-
List *idx = att->indirection;
63-
64-
while (idx != NIL)
65-
{
66-
A_Indices *ai = (A_Indices *) lfirst(idx);
67-
Node *lexpr = NULL,
68-
*uexpr;
69-
70-
uexpr = transformExpr(pstate, ai->uidx, precedence); /* must exists */
71-
if (exprType(uexpr) != INT4OID)
72-
elog(ERROR, "array index expressions must be int4's");
73-
if (ai->lidx != NULL)
74-
{
75-
lexpr = transformExpr(pstate, ai->lidx, precedence);
76-
if (exprType(lexpr) != INT4OID)
77-
elog(ERROR, "array index expressions must be int4's");
78-
}
79-
ai->lidx = lexpr;
80-
ai->uidx = uexpr;
81-
82-
/*
83-
* note we reuse the list of indices, make sure we
84-
* don't free them! Otherwise, make a new list
85-
* here
86-
*/
87-
idx = lnext(idx);
88-
}
89-
result = (Node *) make_array_ref(temp, att->indirection);
90-
}
91-
else
92-
result = temp;
57+
result = transformAttr(pstate, (Attr *) expr, precedence);
9358
break;
9459
}
9560
case T_A_Const:
@@ -106,12 +71,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
10671
case T_ParamNo:
10772
{
10873
ParamNo *pno = (ParamNo *) expr;
109-
Oid toid;
110-
int paramno;
74+
int paramno = pno->number;
75+
Oid toid = param_type(paramno);
11176
Param *param;
11277

113-
paramno = pno->number;
114-
toid = param_type(paramno);
11578
if (!OidIsValid(toid))
11679
elog(ERROR, "Parameter '$%d' is out of range", paramno);
11780
param = makeNode(Param);
@@ -120,40 +83,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
12083
param->paramname = "<unnamed>";
12184
param->paramtype = (Oid) toid;
12285
param->param_tlist = (List *) NULL;
123-
124-
if (pno->indirection != NIL)
125-
{
126-
List *idx = pno->indirection;
127-
128-
while (idx != NIL)
129-
{
130-
A_Indices *ai = (A_Indices *) lfirst(idx);
131-
Node *lexpr = NULL,
132-
*uexpr;
133-
134-
uexpr = transformExpr(pstate, ai->uidx, precedence); /* must exists */
135-
if (exprType(uexpr) != INT4OID)
136-
elog(ERROR, "array index expressions must be int4's");
137-
if (ai->lidx != NULL)
138-
{
139-
lexpr = transformExpr(pstate, ai->lidx, precedence);
140-
if (exprType(lexpr) != INT4OID)
141-
elog(ERROR, "array index expressions must be int4's");
142-
}
143-
ai->lidx = lexpr;
144-
ai->uidx = uexpr;
145-
146-
/*
147-
* note we reuse the list of indices, make sure we
148-
* don't free them! Otherwise, make a new list
149-
* here
150-
*/
151-
idx = lnext(idx);
152-
}
153-
result = (Node *) make_array_ref((Node *) param, pno->indirection);
154-
}
155-
else
156-
result = (Node *) param;
86+
result = transformIndirection(pstate, (Node *) param,
87+
pno->indirection, precedence);
15788
break;
15889
}
15990
case T_A_Expr:
@@ -247,12 +178,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
247178
}
248179
case T_Ident:
249180
{
250-
251-
/*
252-
* look for a column name or a relation name (the default
253-
* behavior)
254-
*/
255-
result = transformIdent(pstate, expr, precedence);
181+
result = transformIdent(pstate, (Ident *) expr, precedence);
256182
break;
257183
}
258184
case T_FuncCall:
@@ -544,48 +470,79 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
544470
}
545471

546472
static Node *
547-
transformIdent(ParseState *pstate, Node *expr, int precedence)
473+
transformIndirection(ParseState *pstate, Node *basenode,
474+
List *indirection, int precedence)
548475
{
549-
Ident *ident = (Ident *) expr;
550-
RangeTblEntry *rte;
551-
Node *column_result,
552-
*relation_result,
553-
*result;
476+
List *idx;
554477

555-
column_result = relation_result = result = 0;
556-
/* try to find the ident as a column */
557-
if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
478+
if (indirection == NIL)
479+
return basenode;
480+
foreach (idx, indirection)
558481
{
559-
Attr *att = makeNode(Attr);
482+
A_Indices *ai = (A_Indices *) lfirst(idx);
483+
Node *lexpr = NULL,
484+
*uexpr;
560485

561-
/* we add the relation name for them */
562-
att->relname = rte->refname;
563-
att->attrs = lcons(makeString(ident->name), NIL);
564-
column_result = (Node *) ParseNestedFuncOrColumn(pstate, att,
565-
&pstate->p_last_resno, precedence);
486+
/* uidx is always present, but lidx might be null */
487+
if (ai->lidx != NULL)
488+
{
489+
lexpr = transformExpr(pstate, ai->lidx, precedence);
490+
if (exprType(lexpr) != INT4OID)
491+
elog(ERROR, "array index expressions must be int4's");
492+
}
493+
uexpr = transformExpr(pstate, ai->uidx, precedence);
494+
if (exprType(uexpr) != INT4OID)
495+
elog(ERROR, "array index expressions must be int4's");
496+
ai->lidx = lexpr;
497+
ai->uidx = uexpr;
498+
/*
499+
* note we reuse the list of A_Indices nodes, make sure
500+
* we don't free them! Otherwise, make a new list here
501+
*/
566502
}
503+
return (Node *) make_array_ref(basenode, indirection);
504+
}
505+
506+
static Node *
507+
transformAttr(ParseState *pstate, Attr *att, int precedence)
508+
{
509+
Node *basenode;
567510

568-
/* try to find the ident as a relation */
569-
if (refnameRangeTableEntry(pstate, ident->name) != NULL)
511+
/* what if att->attrs == "*"? */
512+
basenode = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,
513+
precedence);
514+
return transformIndirection(pstate, basenode,
515+
att->indirection, precedence);
516+
}
517+
518+
static Node *
519+
transformIdent(ParseState *pstate, Ident *ident, int precedence)
520+
{
521+
Node *result = NULL;
522+
RangeTblEntry *rte;
523+
524+
/* try to find the ident as a relation ... but not if subscripts appear */
525+
if (ident->indirection == NIL &&
526+
refnameRangeTableEntry(pstate, ident->name) != NULL)
570527
{
571528
ident->isRel = TRUE;
572-
relation_result = (Node *) ident;
529+
result = (Node *) ident;
573530
}
574531

575-
/* choose the right result based on the precedence */
576-
if (precedence == EXPR_COLUMN_FIRST)
532+
if (result == NULL || precedence == EXPR_COLUMN_FIRST)
577533
{
578-
if (column_result)
579-
result = column_result;
580-
else
581-
result = relation_result;
582-
}
583-
else
584-
{
585-
if (relation_result)
586-
result = relation_result;
587-
else
588-
result = column_result;
534+
/* try to find the ident as a column */
535+
if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
536+
{
537+
/* Convert it to a fully qualified Attr, and transform that */
538+
Attr *att = makeNode(Attr);
539+
540+
att->relname = rte->refname;
541+
att->paramNo = NULL;
542+
att->attrs = lcons(makeString(ident->name), NIL);
543+
att->indirection = ident->indirection;
544+
return transformAttr(pstate, att, precedence);
545+
}
589546
}
590547

591548
if (result == NULL)

0 commit comments

Comments
 (0)