diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-06-24 23:14:49 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-06-24 23:14:49 +0000 |
commit | 46bf65148002f03a4775e6fbb2c4f758184062c5 (patch) | |
tree | 35508e7d4793489135efdbdff9b0fd2325c3b3e3 /src/backend/parser | |
parent | 50e53236aff06a6193059b5a92e60561645338ab (diff) |
Array mega-patch.
Joe Conway
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 39 | ||||
-rw-r--r-- | src/backend/parser/parse_coerce.c | 19 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 34 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 3 | ||||
-rw-r--r-- | src/backend/parser/parse_oper.c | 71 |
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() |