summaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2003-06-24 23:14:49 +0000
committerBruce Momjian <bruce@momjian.us>2003-06-24 23:14:49 +0000
commit46bf65148002f03a4775e6fbb2c4f758184062c5 (patch)
tree35508e7d4793489135efdbdff9b0fd2325c3b3e3 /src/backend/parser
parent50e53236aff06a6193059b5a92e60561645338ab (diff)
Array mega-patch.
Joe Conway
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y39
-rw-r--r--src/backend/parser/parse_coerce.c19
-rw-r--r--src/backend/parser/parse_expr.c34
-rw-r--r--src/backend/parser/parse_func.c3
-rw-r--r--src/backend/parser/parse_oper.c71
5 files changed, 154 insertions, 12 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f8958d58783..e4cf67eca36 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.417 2003/06/17 23:12:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.418 2003/06/24 23:14:43 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -5490,6 +5490,7 @@ r_expr: row IN_P select_with_parens
{
SubLink *n = makeNode(SubLink);
n->subLinkType = ANY_SUBLINK;
+ n->isExpr = false;
n->lefthand = $1;
n->operName = makeList1(makeString("="));
n->subselect = $3;
@@ -5500,6 +5501,7 @@ r_expr: row IN_P select_with_parens
/* Make an IN node */
SubLink *n = makeNode(SubLink);
n->subLinkType = ANY_SUBLINK;
+ n->isExpr = false;
n->lefthand = $1;
n->operName = makeList1(makeString("="));
n->subselect = $4;
@@ -5511,6 +5513,7 @@ r_expr: row IN_P select_with_parens
{
SubLink *n = makeNode(SubLink);
n->subLinkType = $3;
+ n->isExpr = false;
n->lefthand = $1;
n->operName = $2;
n->subselect = $4;
@@ -5521,6 +5524,7 @@ r_expr: row IN_P select_with_parens
{
SubLink *n = makeNode(SubLink);
n->subLinkType = MULTIEXPR_SUBLINK;
+ n->isExpr = false;
n->lefthand = $1;
n->operName = $2;
n->subselect = $3;
@@ -5904,6 +5908,7 @@ a_expr: c_expr { $$ = $1; }
{
SubLink *n = (SubLink *)$3;
n->subLinkType = ANY_SUBLINK;
+ n->isExpr = false;
n->lefthand = makeList1($1);
n->operName = makeList1(makeString("="));
$$ = (Node *)n;
@@ -5931,6 +5936,7 @@ a_expr: c_expr { $$ = $1; }
{
/* Make an IN node */
SubLink *n = (SubLink *)$4;
+ n->isExpr = false;
n->subLinkType = ANY_SUBLINK;
n->lefthand = makeList1($1);
n->operName = makeList1(makeString("="));
@@ -5957,11 +5963,38 @@ a_expr: c_expr { $$ = $1; }
{
SubLink *n = makeNode(SubLink);
n->subLinkType = $3;
+ n->isExpr = false;
n->lefthand = makeList1($1);
n->operName = $2;
n->subselect = $4;
$$ = (Node *)n;
}
+ | a_expr qual_all_Op sub_type '(' a_expr ')' %prec Op
+ {
+ SubLink *n = makeNode(SubLink);
+ SelectStmt *s = makeNode(SelectStmt);
+ ResTarget *r = makeNode(ResTarget);
+
+ r->name = NULL;
+ r->indirection = NIL;
+ r->val = (Node *)$5;
+
+ s->distinctClause = NIL;
+ s->targetList = makeList1(r);
+ s->into = NULL;
+ s->intoColNames = NIL;
+ s->fromClause = NIL;
+ s->whereClause = NULL;
+ s->groupClause = NIL;
+ s->havingClause = NULL;
+
+ n->subLinkType = $3;
+ n->isExpr = true;
+ n->lefthand = makeList1($1);
+ n->operName = $2;
+ n->subselect = (Node *) s;
+ $$ = (Node *)n;
+ }
| UNIQUE select_with_parens %prec Op
{
/* Not sure how to get rid of the parentheses
@@ -6538,6 +6571,7 @@ c_expr: columnref { $$ = (Node *) $1; }
{
SubLink *n = makeNode(SubLink);
n->subLinkType = EXPR_SUBLINK;
+ n->isExpr = false;
n->lefthand = NIL;
n->operName = NIL;
n->subselect = $1;
@@ -6547,6 +6581,7 @@ c_expr: columnref { $$ = (Node *) $1; }
{
SubLink *n = makeNode(SubLink);
n->subLinkType = EXISTS_SUBLINK;
+ n->isExpr = false;
n->lefthand = NIL;
n->operName = NIL;
n->subselect = $2;
@@ -6556,6 +6591,7 @@ c_expr: columnref { $$ = (Node *) $1; }
{
SubLink *n = makeNode(SubLink);
n->subLinkType = ARRAY_SUBLINK;
+ n->isExpr = false;
n->lefthand = NIL;
n->operName = NIL;
n->subselect = $2;
@@ -6730,6 +6766,7 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); }
in_expr: select_with_parens
{
SubLink *n = makeNode(SubLink);
+ n->isExpr = false;
n->subselect = $1;
/* other fields will be filled later */
$$ = (Node *)n;
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index fc35c2d6d41..9861d18fdb0 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.97 2003/05/26 00:11:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.98 2003/06/24 23:14:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -859,7 +859,11 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
/* Get the element type based on the array type, if we have one */
if (OidIsValid(array_typeid))
{
- array_typelem = get_element_type(array_typeid);
+ if (array_typeid != ANYARRAYOID)
+ array_typelem = get_element_type(array_typeid);
+ else
+ array_typelem = ANYELEMENTOID;
+
if (!OidIsValid(array_typelem))
elog(ERROR, "Argument declared ANYARRAY is not an array: %s",
format_type_be(array_typeid));
@@ -919,7 +923,11 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
{
if (!OidIsValid(array_typeid))
{
- array_typeid = get_array_type(elem_typeid);
+ if (elem_typeid != ANYELEMENTOID)
+ array_typeid = get_array_type(elem_typeid);
+ else
+ array_typeid = ANYARRAYOID;
+
if (!OidIsValid(array_typeid))
elog(ERROR, "Cannot find array type for datatype %s",
format_type_be(elem_typeid));
@@ -1170,6 +1178,11 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
if (srctype == targettype)
return true;
+ /* Last of the fast-paths: check for matching polymorphic arrays */
+ if (targettype == ANYARRAYOID)
+ if (get_element_type(srctype) != InvalidOid)
+ return true;
+
/* Else look in pg_cast */
tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(srctype),
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 429a9ac8c8a..5234c22e4fb 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.148 2003/04/29 22:13:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.149 2003/06/24 23:14:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -436,6 +436,7 @@ transformExpr(ParseState *pstate, Node *expr)
sublink->operName = NIL;
sublink->operOids = NIL;
sublink->useOr = FALSE;
+ sublink->isExpr = FALSE;
}
else if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
@@ -463,6 +464,7 @@ transformExpr(ParseState *pstate, Node *expr)
sublink->operName = NIL;
sublink->operOids = NIL;
sublink->useOr = FALSE;
+ sublink->isExpr = FALSE;
}
else
{
@@ -538,10 +540,30 @@ transformExpr(ParseState *pstate, Node *expr)
* here, because make_subplan() will insert type
* coercion calls if needed.
*/
- optup = oper(op,
- exprType(lexpr),
- exprType((Node *) tent->expr),
- false);
+ if (!sublink->isExpr)
+ {
+ optup = oper(op,
+ exprType(lexpr),
+ exprType((Node *) tent->expr),
+ false);
+ }
+ else
+ {
+ Oid exprtype = exprType((Node *) tent->expr);
+ Oid elemtype = get_element_type(exprtype);
+
+ if (elemtype != InvalidOid)
+ optup = oper(op,
+ exprType(lexpr),
+ elemtype,
+ false);
+ else
+ optup = oper(op,
+ exprType(lexpr),
+ exprtype,
+ false);
+ }
+
opform = (Form_pg_operator) GETSTRUCT(optup);
if (opform->oprresult != BOOLOID)
@@ -743,7 +765,7 @@ transformExpr(ParseState *pstate, Node *expr)
ArrayExpr *e = (ArrayExpr *) lfirst(element);
if (!IsA(e, ArrayExpr))
- elog(ERROR, "Multi-dimensional ARRAY[] must be built from nested array expressions");
+ elog(ERROR, "Multidimensional ARRAY[] must be built from nested array expressions");
if (ndims == 0)
ndims = e->ndims;
else if (e->ndims != ndims)
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 6f858e17a8b..5ff2bc6d819 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.149 2003/06/06 15:04:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.150 2003/06/24 23:14:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -336,6 +336,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
aggref->target = lfirst(fargs);
aggref->aggstar = agg_star;
aggref->aggdistinct = agg_distinct;
+ aggref->args = fargs;
/* parse_agg.c does additional aggregate-specific processing */
transformAggregateCall(pstate, aggref);
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 21f73994c42..a6b66625be2 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.64 2003/05/26 00:11:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.65 2003/06/24 23:14:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -137,6 +137,33 @@ Operator
equality_oper(Oid argtype, bool noError)
{
Operator optup;
+ Oid elem_type = get_element_type(argtype);
+
+ if (OidIsValid(elem_type))
+ {
+ bool found = false;
+ /*
+ * If the datatype is an array, look for an "=" operator for the
+ * element datatype. We require it to be an exact or binary-compatible
+ * match, since most callers are not prepared to cope with adding any
+ * run-time type coercion steps.
+ */
+ optup = equality_oper(elem_type, true);
+ if (optup != NULL)
+ {
+ found = true;
+ ReleaseSysCache(optup);
+ }
+
+ if (!found)
+ {
+ if (!noError)
+ elog(ERROR, "Unable to identify an equality operator for " \
+ "array type's element type %s",
+ format_type_be(elem_type));
+ return NULL;
+ }
+ }
/*
* Look for an "=" operator for the datatype. We require it to be
@@ -175,6 +202,33 @@ Operator
ordering_oper(Oid argtype, bool noError)
{
Operator optup;
+ Oid elem_type = get_element_type(argtype);
+
+ if (OidIsValid(elem_type))
+ {
+ bool found = false;
+ /*
+ * If the datatype is an array, find the array element type's equality
+ * operator, and use its lsortop (it *must* be mergejoinable). We use
+ * this definition because for sorting and grouping purposes, it's
+ * important that the equality and ordering operators are consistent.
+ */
+ optup = ordering_oper(elem_type, true);
+ if (optup != NULL)
+ {
+ found = true;
+ ReleaseSysCache(optup);
+ }
+
+ if (!found)
+ {
+ if (!noError)
+ elog(ERROR, "Unable to identify an ordering operator for " \
+ "array type's element type %s",
+ format_type_be(elem_type));
+ return NULL;
+ }
+ }
/*
* Find the type's equality operator, and use its lsortop (it *must*
@@ -221,6 +275,21 @@ equality_oper_funcid(Oid argtype)
}
/*
+ * ordering_oper_funcid - convenience routine for oprfuncid(ordering_oper())
+ */
+Oid
+ordering_oper_funcid(Oid argtype)
+{
+ Operator optup;
+ Oid result;
+
+ optup = ordering_oper(argtype, false);
+ result = oprfuncid(optup);
+ ReleaseSysCache(optup);
+ return result;
+}
+
+/*
* ordering_oper_opid - convenience routine for oprid(ordering_oper())
*
* This was formerly called any_ordering_op()