1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

Revise collation derivation method and expression-tree representation.

All expression nodes now have an explicit output-collation field, unless
they are known to only return a noncollatable data type (such as boolean
or record).  Also, nodes that can invoke collation-aware functions store
a separate field that is the collation value to pass to the function.
This avoids confusion that arises when a function has collatable inputs
and noncollatable output type, or vice versa.

Also, replace the parser's on-the-fly collation assignment method with
a post-pass over the completed expression tree.  This allows us to use
a more complex (and hopefully more nearly spec-compliant) assignment
rule without paying for it in extra storage in every expression node.

Fix assorted bugs in the planner's handling of collations by making
collation one of the defining properties of an EquivalenceClass and
by converting CollateExprs into discardable RelabelType nodes during
expression preprocessing.
This commit is contained in:
Tom Lane
2011-03-19 20:29:08 -04:00
parent 025f4c72f0
commit b310b6e31c
73 changed files with 2365 additions and 1084 deletions

View File

@@ -139,7 +139,7 @@ typedef struct Var
* all */
Oid vartype; /* pg_type OID for the type of this var */
int32 vartypmod; /* pg_attribute typmod value */
Oid varcollid; /* collation */
Oid varcollid; /* OID of collation, or InvalidOid if none */
Index varlevelsup; /* for subquery variables referencing outer
* relations; 0 in a normal var, >0 means N
* levels up */
@@ -156,7 +156,7 @@ typedef struct Const
Expr xpr;
Oid consttype; /* pg_type OID of the constant's datatype */
int32 consttypmod; /* typmod value, if any */
Oid constcollid; /* collation */
Oid constcollid; /* OID of collation, or InvalidOid if none */
int constlen; /* typlen of the constant's datatype */
Datum constvalue; /* the constant's value */
bool constisnull; /* whether the constant is null (if true,
@@ -207,7 +207,7 @@ typedef struct Param
int paramid; /* numeric ID for parameter */
Oid paramtype; /* pg_type OID of parameter's datatype */
int32 paramtypmod; /* typmod value, if known */
Oid paramcollation; /* parameter's collation */
Oid paramcollid; /* OID of collation, or InvalidOid if none */
int location; /* token location, or -1 if unknown */
} Param;
@@ -231,12 +231,13 @@ typedef struct Aggref
Expr xpr;
Oid aggfnoid; /* pg_proc Oid of the aggregate */
Oid aggtype; /* type Oid of result of the aggregate */
Oid aggcollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
List *args; /* arguments and sort expressions */
List *aggorder; /* ORDER BY (list of SortGroupClause) */
List *aggdistinct; /* DISTINCT (list of SortGroupClause) */
bool aggstar; /* TRUE if argument list was really '*' */
Index agglevelsup; /* > 0 if agg belongs to outer query */
Oid collid; /* collation OID to use by function */
int location; /* token location, or -1 if unknown */
} Aggref;
@@ -248,11 +249,12 @@ typedef struct WindowFunc
Expr xpr;
Oid winfnoid; /* pg_proc Oid of the function */
Oid wintype; /* type Oid of result of the window function */
Oid wincollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
List *args; /* arguments to the window function */
Index winref; /* index of associated WindowClause */
bool winstar; /* TRUE if argument list was really '*' */
bool winagg; /* is function a simple aggregate? */
Oid collid; /* collation OID to use by function */
int location; /* token location, or -1 if unknown */
} WindowFunc;
@@ -284,7 +286,7 @@ typedef struct ArrayRef
Oid refarraytype; /* type of the array proper */
Oid refelemtype; /* type of the array elements */
int32 reftypmod; /* typmod of the array (and elements too) */
Oid refcollid; /* collation */
Oid refcollid; /* OID of collation, or InvalidOid if none */
List *refupperindexpr;/* expressions that evaluate to upper array
* indexes */
List *reflowerindexpr;/* expressions that evaluate to lower array
@@ -329,8 +331,9 @@ typedef struct FuncExpr
Oid funcresulttype; /* PG_TYPE OID of result value */
bool funcretset; /* true if function returns set */
CoercionForm funcformat; /* how to display this function call */
Oid funccollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
List *args; /* arguments to the function */
Oid collid; /* collation OID to use by function */
int location; /* token location, or -1 if unknown */
} FuncExpr;
@@ -373,8 +376,9 @@ typedef struct OpExpr
Oid opfuncid; /* PG_PROC OID of underlying function */
Oid opresulttype; /* PG_TYPE OID of result value */
bool opretset; /* true if operator returns set */
Oid opcollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that operator should use */
List *args; /* arguments to the operator (1 or 2) */
Oid collid; /* collation OID to use by operator */
int location; /* token location, or -1 if unknown */
} OpExpr;
@@ -390,6 +394,14 @@ typedef struct OpExpr
*/
typedef OpExpr DistinctExpr;
/*
* NullIfExpr - a NULLIF expression
*
* Like DistinctExpr, this is represented the same as an OpExpr referencing
* the "=" operator for x and y.
*/
typedef OpExpr NullIfExpr;
/*
* ScalarArrayOpExpr - expression node for "scalar op ANY/ALL (array)"
*
@@ -398,7 +410,7 @@ typedef OpExpr DistinctExpr;
* with OR or AND (for ANY or ALL respectively). The node representation
* is almost the same as for the underlying operator, but we need a useOr
* flag to remember whether it's ANY or ALL, and we don't have to store
* the result type because it must be boolean.
* the result type (or the collation) because it must be boolean.
*/
typedef struct ScalarArrayOpExpr
{
@@ -406,8 +418,8 @@ typedef struct ScalarArrayOpExpr
Oid opno; /* PG_OPERATOR OID of the operator */
Oid opfuncid; /* PG_PROC OID of underlying function */
bool useOr; /* true for ANY, false for ALL */
Oid inputcollid; /* OID of collation that operator should use */
List *args; /* the scalar and array operands */
Oid collid; /* collation OID to use by operator */
int location; /* token location, or -1 if unknown */
} ScalarArrayOpExpr;
@@ -602,7 +614,7 @@ typedef struct FieldSelect
Oid resulttype; /* type of the field (result type of this
* node) */
int32 resulttypmod; /* output typmod (usually -1) */
Oid resultcollation;/* collation of the field */
Oid resultcollid; /* OID of collation of the field */
} FieldSelect;
/* ----------------
@@ -627,7 +639,7 @@ typedef struct FieldStore
List *newvals; /* new value(s) for field(s) */
List *fieldnums; /* integer list of field attnums */
Oid resulttype; /* type of result (same as type of arg) */
/* Like RowExpr, we deliberately omit a typmod here */
/* Like RowExpr, we deliberately omit a typmod and collation here */
} FieldStore;
/* ----------------
@@ -649,6 +661,7 @@ typedef struct RelabelType
Expr *arg; /* input expression */
Oid resulttype; /* output type of coercion expression */
int32 resulttypmod; /* output typmod (usually -1) */
Oid resultcollid; /* OID of collation, or InvalidOid if none */
CoercionForm relabelformat; /* how to display this node */
int location; /* token location, or -1 if unknown */
} RelabelType;
@@ -668,6 +681,7 @@ typedef struct CoerceViaIO
Expr *arg; /* input expression */
Oid resulttype; /* output type of coercion */
/* output typmod is not stored, but is presumed -1 */
Oid resultcollid; /* OID of collation, or InvalidOid if none */
CoercionForm coerceformat; /* how to display this node */
int location; /* token location, or -1 if unknown */
} CoerceViaIO;
@@ -691,6 +705,7 @@ typedef struct ArrayCoerceExpr
Oid elemfuncid; /* OID of element coercion function, or 0 */
Oid resulttype; /* output type of coercion (an array type) */
int32 resulttypmod; /* output typmod (also element typmod) */
Oid resultcollid; /* OID of collation, or InvalidOid if none */
bool isExplicit; /* conversion semantics flag to pass to func */
CoercionForm coerceformat; /* how to display this node */
int location; /* token location, or -1 if unknown */
@@ -713,13 +728,16 @@ typedef struct ConvertRowtypeExpr
Expr xpr;
Expr *arg; /* input expression */
Oid resulttype; /* output type (always a composite type) */
/* result typmod is not stored, but must be -1; see RowExpr comments */
/* Like RowExpr, we deliberately omit a typmod and collation here */
CoercionForm convertformat; /* how to display this node */
int location; /* token location, or -1 if unknown */
} ConvertRowtypeExpr;
/*----------
* CollateExpr - COLLATE
*
* The planner replaces CollateExpr with RelabelType during expression
* preprocessing, so execution never sees a CollateExpr.
*----------
*/
typedef struct CollateExpr
@@ -756,7 +774,7 @@ typedef struct CaseExpr
{
Expr xpr;
Oid casetype; /* type of expression result */
Oid casecollation; /* collation of expression result */
Oid casecollid; /* OID of collation, or InvalidOid if none */
Expr *arg; /* implicit equality comparison argument */
List *args; /* the arguments (list of WHEN clauses) */
Expr *defresult; /* the default result (ELSE clause) */
@@ -802,6 +820,7 @@ typedef struct ArrayExpr
{
Expr xpr;
Oid array_typeid; /* type of expression result */
Oid array_collid; /* OID of collation, or InvalidOid if none */
Oid element_typeid; /* common type of array elements */
List *elements; /* the array elements or sub-arrays */
bool multidims; /* true if elements are sub-arrays */
@@ -838,6 +857,9 @@ typedef struct RowExpr
* associated with specific RECORD types at runtime, it will differ for
* different backends, and so cannot safely be stored in stored
* parsetrees. We must assume typmod -1 for a RowExpr node.
*
* We don't need to store a collation either. The result type is
* necessarily composite, and composite types never have a collation.
*/
CoercionForm row_format; /* how to display this node */
List *colnames; /* list of String, or NIL */
@@ -875,7 +897,7 @@ typedef struct RowCompareExpr
RowCompareType rctype; /* LT LE GE or GT, never EQ or NE */
List *opnos; /* OID list of pairwise comparison ops */
List *opfamilies; /* OID list of containing operator families */
List *collids; /* OID list of collations for the comparisons */
List *inputcollids; /* OID list of collations for comparisons */
List *largs; /* the left-hand input arguments */
List *rargs; /* the right-hand input arguments */
} RowCompareExpr;
@@ -887,7 +909,7 @@ typedef struct CoalesceExpr
{
Expr xpr;
Oid coalescetype; /* type of expression result */
Oid coalescecollation; /* collation of expression result */
Oid coalescecollid; /* OID of collation, or InvalidOid if none */
List *args; /* the arguments */
int location; /* token location, or -1 if unknown */
} CoalesceExpr;
@@ -905,9 +927,10 @@ typedef struct MinMaxExpr
{
Expr xpr;
Oid minmaxtype; /* common type of arguments and result */
Oid minmaxcollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
MinMaxOp op; /* function to execute */
List *args; /* the arguments */
Oid collid; /* collation to use */
int location; /* token location, or -1 if unknown */
} MinMaxExpr;
@@ -917,6 +940,10 @@ typedef struct MinMaxExpr
* 'name' carries the "NAME foo" argument (already XML-escaped).
* 'named_args' and 'arg_names' represent an xml_attribute list.
* 'args' carries all other arguments.
*
* Note: result type/typmod/collation are not stored, but can be deduced
* from the XmlExprOp. The type/typmod fields are just used for display
* purposes, and are NOT the true result type of the node.
*/
typedef enum XmlExprOp
{
@@ -945,19 +972,11 @@ typedef struct XmlExpr
List *arg_names; /* parallel list of Value strings */
List *args; /* list of expressions */
XmlOptionType xmloption; /* DOCUMENT or CONTENT */
Oid type; /* target type for XMLSERIALIZE */
Oid type; /* target type/typmod for XMLSERIALIZE */
int32 typmod;
int location; /* token location, or -1 if unknown */
} XmlExpr;
/*
* NullIfExpr - a NULLIF expression
*
* Like DistinctExpr, this is represented the same as an OpExpr referencing
* the "=" operator for x and y.
*/
typedef OpExpr NullIfExpr;
/* ----------------
* NullTest
*
@@ -1018,6 +1037,7 @@ typedef struct CoerceToDomain
Expr *arg; /* input expression */
Oid resulttype; /* domain type ID (result type) */
int32 resulttypmod; /* output typmod (currently always -1) */
Oid resultcollid; /* OID of collation, or InvalidOid if none */
CoercionForm coercionformat; /* how to display this node */
int location; /* token location, or -1 if unknown */
} CoerceToDomain;
@@ -1036,6 +1056,7 @@ typedef struct CoerceToDomainValue
Expr xpr;
Oid typeId; /* type for substituted value */
int32 typeMod; /* typemod for substituted value */
Oid collation; /* collation for the substituted value */
int location; /* token location, or -1 if unknown */
} CoerceToDomainValue;
@@ -1051,7 +1072,7 @@ typedef struct SetToDefault
Expr xpr;
Oid typeId; /* type for substituted value */
int32 typeMod; /* typemod for substituted value */
Oid collid; /* collation for the substituted value */
Oid collation; /* collation for the substituted value */
int location; /* token location, or -1 if unknown */
} SetToDefault;