1998-05-10 01:31:34 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* parse_coerce.c
|
2000-02-20 22:32:16 +01:00
|
|
|
* handle type coercions/conversions for parser
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-03-12 00:19:50 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.34 2000/03/11 23:19:50 tgl Exp $
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
|
1999-10-03 01:29:19 +02:00
|
|
|
#include "optimizer/clauses.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "parser/parse_coerce.h"
|
|
|
|
#include "parser/parse_expr.h"
|
1999-06-18 00:21:41 +02:00
|
|
|
#include "parser/parse_func.h"
|
1998-05-10 01:31:34 +02:00
|
|
|
#include "parser/parse_target.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "utils/builtins.h"
|
1998-05-10 01:31:34 +02:00
|
|
|
#include "utils/syscache.h"
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
Oid DemoteType(Oid inType);
|
|
|
|
Oid PromoteTypeToNext(Oid inType);
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1999-05-25 18:15:34 +02:00
|
|
|
static Oid PreferredType(CATEGORY category, Oid type);
|
1998-10-08 20:30:52 +02:00
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
/* coerce_type()
|
|
|
|
* Convert a function argument to a different type.
|
|
|
|
*/
|
|
|
|
Node *
|
2000-01-17 01:14:49 +01:00
|
|
|
coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
|
|
|
Oid targetTypeId, int32 atttypmod)
|
1998-05-10 01:31:34 +02:00
|
|
|
{
|
2000-02-20 22:32:16 +01:00
|
|
|
Node *result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1999-08-05 04:33:54 +02:00
|
|
|
if (targetTypeId == InvalidOid ||
|
|
|
|
targetTypeId == inputTypeId)
|
|
|
|
{
|
|
|
|
/* no conversion needed */
|
1998-05-10 01:31:34 +02:00
|
|
|
result = node;
|
1999-08-05 04:33:54 +02:00
|
|
|
}
|
|
|
|
else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
|
|
|
|
{
|
1999-10-03 01:29:19 +02:00
|
|
|
/*
|
|
|
|
* Input is a string constant with previously undetermined type.
|
1999-08-05 04:33:54 +02:00
|
|
|
* Apply the target type's typinput function to it to produce
|
|
|
|
* a constant of the target type.
|
|
|
|
*
|
|
|
|
* NOTE: this case cannot be folded together with the other
|
|
|
|
* constant-input case, since the typinput function does not
|
|
|
|
* necessarily behave the same as a type conversion function.
|
|
|
|
* For example, int4's typinput function will reject "1.2",
|
|
|
|
* whereas float-to-int type conversion will round to integer.
|
1999-10-03 01:29:19 +02:00
|
|
|
*
|
|
|
|
* XXX if the typinput function is not cachable, we really ought
|
|
|
|
* to postpone evaluation of the function call until runtime.
|
|
|
|
* But there is no way to represent a typinput function call as
|
|
|
|
* an expression tree, because C-string values are not Datums.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
1999-08-05 04:33:54 +02:00
|
|
|
Const *con = (Const *) node;
|
1999-08-24 02:09:56 +02:00
|
|
|
Const *newcon = makeNode(Const);
|
1999-08-05 04:33:54 +02:00
|
|
|
Type targetType = typeidType(targetTypeId);
|
|
|
|
|
1999-08-24 02:09:56 +02:00
|
|
|
newcon->consttype = targetTypeId;
|
|
|
|
newcon->constlen = typeLen(targetType);
|
|
|
|
newcon->constbyval = typeByVal(targetType);
|
|
|
|
newcon->constisnull = con->constisnull;
|
|
|
|
newcon->constisset = false;
|
1999-08-05 04:33:54 +02:00
|
|
|
|
1999-08-24 02:09:56 +02:00
|
|
|
if (! con->constisnull)
|
|
|
|
{
|
|
|
|
/* We know the source constant is really of type 'text' */
|
|
|
|
char *val = textout((text *) con->constvalue);
|
|
|
|
newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
|
|
|
|
pfree(val);
|
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1999-08-24 02:09:56 +02:00
|
|
|
result = (Node *) newcon;
|
1999-08-05 04:33:54 +02:00
|
|
|
}
|
2000-02-20 22:32:16 +01:00
|
|
|
else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We don't really need to do a conversion, but we do need to attach
|
|
|
|
* a RelabelType node so that the expression will be seen to have
|
|
|
|
* the intended type when inspected by higher-level code.
|
|
|
|
*/
|
|
|
|
RelabelType *relabel = makeNode(RelabelType);
|
|
|
|
|
|
|
|
relabel->arg = node;
|
|
|
|
relabel->resulttype = targetTypeId;
|
|
|
|
/*
|
|
|
|
* XXX could we label result with exprTypmod(node) instead of
|
|
|
|
* default -1 typmod, to save a possible length-coercion later?
|
|
|
|
* Would work if both types have same interpretation of typmod,
|
|
|
|
* which is likely but not certain.
|
|
|
|
*/
|
|
|
|
relabel->resulttypmod = -1;
|
|
|
|
|
|
|
|
result = (Node *) relabel;
|
|
|
|
}
|
1999-08-05 04:33:54 +02:00
|
|
|
else
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
/*
|
1999-08-05 04:33:54 +02:00
|
|
|
* Otherwise, find the appropriate type conversion function
|
|
|
|
* (caller should have determined that there is one), and
|
|
|
|
* generate an expression tree representing run-time
|
|
|
|
* application of the conversion function.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
1999-08-05 04:33:54 +02:00
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
Type targetType = typeidType(targetTypeId);
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-08-05 04:33:54 +02:00
|
|
|
n->funcname = typeTypeName(targetType);
|
|
|
|
n->args = lcons(node, NIL);
|
1999-12-10 08:37:35 +01:00
|
|
|
n->agg_star = false;
|
|
|
|
n->agg_distinct = false;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1999-08-05 04:33:54 +02:00
|
|
|
result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1999-08-05 04:33:54 +02:00
|
|
|
/*
|
|
|
|
* If the input is a constant, apply the type conversion function
|
1999-10-03 01:29:19 +02:00
|
|
|
* now instead of delaying to runtime. (We could, of course,
|
|
|
|
* just leave this to be done during planning/optimization;
|
|
|
|
* but it's a very frequent special case, and we save cycles
|
|
|
|
* in the rewriter if we fold the expression now.)
|
1999-08-05 04:33:54 +02:00
|
|
|
*
|
1999-10-03 01:29:19 +02:00
|
|
|
* Note that no folding will occur if the conversion function is
|
|
|
|
* not marked 'iscachable'.
|
1999-08-05 04:33:54 +02:00
|
|
|
*/
|
1999-10-03 01:29:19 +02:00
|
|
|
if (IsA(node, Const))
|
|
|
|
result = eval_const_expressions(result);
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
1999-05-22 06:12:29 +02:00
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* can_coerce_type()
|
|
|
|
* Can input_typeids be coerced to func_typeids?
|
|
|
|
*
|
|
|
|
* There are a few types which are known apriori to be convertible.
|
|
|
|
* We will check for those cases first, and then look for possible
|
1998-09-01 06:40:42 +02:00
|
|
|
* conversion functions.
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
|
|
|
* Notes:
|
|
|
|
* This uses the same mechanism as the CAST() SQL construct in gram.y.
|
|
|
|
* We should also check the function return type on candidate conversion
|
1998-09-01 06:40:42 +02:00
|
|
|
* routines just to be safe but we do not do that yet...
|
1998-05-10 01:31:34 +02:00
|
|
|
* We need to have a zero-filled OID array here, otherwise the cache lookup fails.
|
|
|
|
* - thomas 1998-03-31
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
|
|
|
|
{
|
|
|
|
HeapTuple ftup;
|
|
|
|
int i;
|
|
|
|
Type tp;
|
2000-01-10 18:14:46 +01:00
|
|
|
Oid oid_array[FUNC_MAX_ARGS];
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
/* run through argument list... */
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
|
|
|
if (input_typeids[i] != func_typeids[i])
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* one of the known-good transparent conversions? then drop
|
|
|
|
* through...
|
|
|
|
*/
|
1998-05-10 01:31:34 +02:00
|
|
|
if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
|
1999-05-22 04:55:58 +02:00
|
|
|
;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
/* don't know what to do for the output type? then quit... */
|
|
|
|
else if (func_typeids[i] == InvalidOid)
|
|
|
|
return false;
|
|
|
|
/* don't know what to do for the input type? then quit... */
|
|
|
|
else if (input_typeids[i] == InvalidOid)
|
|
|
|
return false;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
/*
|
|
|
|
* if not unknown input type, try for explicit conversion
|
|
|
|
* using functions...
|
|
|
|
*/
|
1998-05-10 01:31:34 +02:00
|
|
|
else if (input_typeids[i] != UNKNOWNOID)
|
|
|
|
{
|
2000-01-10 18:14:46 +01:00
|
|
|
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
1998-05-10 01:31:34 +02:00
|
|
|
oid_array[0] = input_typeids[i];
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
/*
|
|
|
|
* look for a single-argument function named with the
|
|
|
|
* target type name
|
|
|
|
*/
|
1999-11-22 18:56:41 +01:00
|
|
|
ftup = SearchSysCacheTuple(PROCNAME,
|
1998-09-01 06:40:42 +02:00
|
|
|
PointerGetDatum(typeidTypeName(func_typeids[i])),
|
1998-05-10 01:31:34 +02:00
|
|
|
Int32GetDatum(1),
|
|
|
|
PointerGetDatum(oid_array),
|
|
|
|
0);
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
/*
|
|
|
|
* should also check the function return type just to be
|
|
|
|
* safe...
|
|
|
|
*/
|
1999-05-22 04:55:58 +02:00
|
|
|
if (!HeapTupleIsValid(ftup))
|
1998-05-10 01:31:34 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
tp = typeidType(input_typeids[i]);
|
|
|
|
if (typeTypeFlag(tp) == 'c')
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
1999-05-22 06:12:29 +02:00
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2000-01-17 01:14:49 +01:00
|
|
|
/* coerce_type_typmod()
|
|
|
|
* Force a value to a particular typmod, if meaningful and possible.
|
|
|
|
*
|
|
|
|
* This is applied to values that are going to be stored in a relation
|
|
|
|
* (where we have an atttypmod for the column) as well as values being
|
|
|
|
* explicitly CASTed (where the typmod comes from the target type spec).
|
|
|
|
*
|
|
|
|
* The caller must have already ensured that the value is of the correct
|
|
|
|
* type, typically by applying coerce_type.
|
|
|
|
*
|
|
|
|
* If the target column type possesses a function named for the type
|
|
|
|
* and having parameter signature (columntype, int4), we assume that
|
|
|
|
* the type requires coercion to its own length and that the said
|
|
|
|
* function should be invoked to do that.
|
|
|
|
*
|
|
|
|
* "bpchar" (ie, char(N)) and "numeric" are examples of such types.
|
|
|
|
*/
|
|
|
|
Node *
|
|
|
|
coerce_type_typmod(ParseState *pstate, Node *node,
|
|
|
|
Oid targetTypeId, int32 atttypmod)
|
|
|
|
{
|
|
|
|
char *funcname;
|
|
|
|
Oid oid_array[FUNC_MAX_ARGS];
|
|
|
|
HeapTuple ftup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We assume that only typmod values greater than 0 indicate a forced
|
|
|
|
* conversion is necessary.
|
|
|
|
*/
|
|
|
|
if (atttypmod <= 0 ||
|
|
|
|
atttypmod == exprTypmod(node))
|
|
|
|
return node;
|
|
|
|
|
|
|
|
funcname = typeidTypeName(targetTypeId);
|
|
|
|
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
|
|
|
oid_array[0] = targetTypeId;
|
|
|
|
oid_array[1] = INT4OID;
|
|
|
|
|
|
|
|
/* attempt to find with arguments exactly as specified... */
|
|
|
|
ftup = SearchSysCacheTuple(PROCNAME,
|
|
|
|
PointerGetDatum(funcname),
|
|
|
|
Int32GetDatum(2),
|
|
|
|
PointerGetDatum(oid_array),
|
|
|
|
0);
|
|
|
|
|
|
|
|
if (HeapTupleIsValid(ftup))
|
|
|
|
{
|
|
|
|
A_Const *cons = makeNode(A_Const);
|
|
|
|
FuncCall *func = makeNode(FuncCall);
|
|
|
|
|
|
|
|
cons->val.type = T_Integer;
|
|
|
|
cons->val.val.ival = atttypmod;
|
|
|
|
|
|
|
|
func->funcname = funcname;
|
|
|
|
func->args = lappend(lcons(node, NIL), cons);
|
|
|
|
func->agg_star = false;
|
|
|
|
func->agg_distinct = false;
|
|
|
|
|
|
|
|
node = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
/* TypeCategory()
|
|
|
|
* Assign a category to the specified OID.
|
|
|
|
*/
|
|
|
|
CATEGORY
|
|
|
|
TypeCategory(Oid inType)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
CATEGORY result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
switch (inType)
|
|
|
|
{
|
|
|
|
case (BOOLOID):
|
|
|
|
result = BOOLEAN_TYPE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (CHAROID):
|
2000-03-12 00:19:50 +01:00
|
|
|
case (NAMEOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (BPCHAROID):
|
|
|
|
case (VARCHAROID):
|
|
|
|
case (TEXTOID):
|
2000-02-27 19:54:43 +01:00
|
|
|
case (LZTEXTOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
result = STRING_TYPE;
|
|
|
|
break;
|
|
|
|
|
1998-08-14 18:07:00 +02:00
|
|
|
case (OIDOID):
|
2000-02-27 19:54:43 +01:00
|
|
|
case (REGPROCOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (INT2OID):
|
|
|
|
case (INT4OID):
|
1998-07-08 16:04:11 +02:00
|
|
|
case (INT8OID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (FLOAT4OID):
|
|
|
|
case (FLOAT8OID):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
case (NUMERICOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (CASHOID):
|
|
|
|
result = NUMERIC_TYPE;
|
|
|
|
break;
|
|
|
|
|
2000-02-20 07:28:42 +01:00
|
|
|
case (DATEOID):
|
|
|
|
case (TIMEOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (ABSTIMEOID):
|
|
|
|
case (TIMESTAMPOID):
|
|
|
|
result = DATETIME_TYPE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (RELTIMEOID):
|
2000-02-20 07:28:42 +01:00
|
|
|
case (TINTERVALOID):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
case (INTERVALOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
result = TIMESPAN_TYPE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (POINTOID):
|
|
|
|
case (LSEGOID):
|
|
|
|
case (PATHOID):
|
2000-03-12 00:19:50 +01:00
|
|
|
case (BOXOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (POLYGONOID):
|
2000-03-12 00:19:50 +01:00
|
|
|
case (LINEOID):
|
|
|
|
case (CIRCLEOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
result = GEOMETRIC_TYPE;
|
|
|
|
break;
|
|
|
|
|
1998-10-22 15:51:07 +02:00
|
|
|
case (INETOID):
|
|
|
|
case (CIDROID):
|
|
|
|
result = NETWORK_TYPE;
|
|
|
|
break;
|
|
|
|
|
2000-03-12 00:19:50 +01:00
|
|
|
case (UNKNOWNOID):
|
|
|
|
case (InvalidOid):
|
|
|
|
result = UNKNOWN_TYPE;
|
|
|
|
break;
|
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
default:
|
|
|
|
result = USER_TYPE;
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1998-09-01 06:40:42 +02:00
|
|
|
} /* TypeCategory() */
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* IsPreferredType()
|
1998-12-04 16:34:49 +01:00
|
|
|
* Check if this type is a preferred type.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
IsPreferredType(CATEGORY category, Oid type)
|
|
|
|
{
|
1998-09-01 05:29:17 +02:00
|
|
|
return type == PreferredType(category, type);
|
1998-09-01 06:40:42 +02:00
|
|
|
} /* IsPreferredType() */
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* PreferredType()
|
1998-05-29 16:00:24 +02:00
|
|
|
* Return the preferred type OID for the specified category.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
1998-10-08 20:30:52 +02:00
|
|
|
static Oid
|
1998-05-10 01:31:34 +02:00
|
|
|
PreferredType(CATEGORY category, Oid type)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
Oid result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
switch (category)
|
|
|
|
{
|
|
|
|
case (BOOLEAN_TYPE):
|
|
|
|
result = BOOLOID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (STRING_TYPE):
|
|
|
|
result = TEXTOID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (NUMERIC_TYPE):
|
1998-08-14 18:07:00 +02:00
|
|
|
if (type == OIDOID)
|
|
|
|
result = OIDOID;
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
else if (type == NUMERICOID)
|
|
|
|
result = NUMERICOID;
|
1998-08-14 18:07:00 +02:00
|
|
|
else
|
|
|
|
result = FLOAT8OID;
|
1998-05-10 01:31:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case (DATETIME_TYPE):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
result = TIMESTAMPOID;
|
1998-05-10 01:31:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case (TIMESPAN_TYPE):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
result = INTERVALOID;
|
1998-05-10 01:31:34 +02:00
|
|
|
break;
|
|
|
|
|
1998-10-22 15:51:07 +02:00
|
|
|
case (NETWORK_TYPE):
|
|
|
|
result = INETOID;
|
|
|
|
break;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
case (GEOMETRIC_TYPE):
|
|
|
|
case (USER_TYPE):
|
|
|
|
result = type;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
result = UNKNOWNOID;
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1998-09-01 06:40:42 +02:00
|
|
|
} /* PreferredType() */
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
1999-02-21 04:49:55 +01:00
|
|
|
#ifdef NOT_USED
|
1998-05-10 01:31:34 +02:00
|
|
|
Oid
|
|
|
|
PromoteTypeToNext(Oid inType)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
Oid result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
switch (inType)
|
|
|
|
{
|
|
|
|
case (CHAROID):
|
|
|
|
case (BPCHAROID):
|
|
|
|
result = VARCHAROID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (VARCHAROID):
|
|
|
|
result = TEXTOID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (INT2OID):
|
|
|
|
case (CASHOID):
|
|
|
|
result = INT4OID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (INT4OID):
|
1998-07-08 16:04:11 +02:00
|
|
|
case (INT8OID):
|
1998-05-10 01:31:34 +02:00
|
|
|
case (FLOAT4OID):
|
|
|
|
result = FLOAT8OID;
|
|
|
|
break;
|
|
|
|
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
case (NUMERICOID):
|
|
|
|
result = NUMERICOID;
|
|
|
|
break;
|
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
case (DATEOID):
|
|
|
|
case (ABSTIMEOID):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
result = TIMESTAMPOID;
|
1998-05-10 01:31:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case (TIMEOID):
|
|
|
|
case (RELTIMEOID):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
result = INTERVALOID;
|
1998-05-10 01:31:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case (BOOLOID):
|
|
|
|
case (TEXTOID):
|
|
|
|
case (FLOAT8OID):
|
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:26:26 +01:00
|
|
|
case (TIMESTAMPOID):
|
|
|
|
case (INTERVALOID):
|
1998-05-10 01:31:34 +02:00
|
|
|
default:
|
|
|
|
result = inType;
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1998-09-01 06:40:42 +02:00
|
|
|
} /* PromoteTypeToNext() */
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
Oid
|
|
|
|
DemoteType(Oid inType)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
Oid result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
switch (inType)
|
|
|
|
{
|
|
|
|
case (FLOAT4OID):
|
|
|
|
case (FLOAT8OID):
|
|
|
|
result = INT4OID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
result = inType;
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1998-09-01 06:40:42 +02:00
|
|
|
} /* DemoteType() */
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
Oid
|
|
|
|
PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
Oid result;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
if (inType1 == inType2)
|
|
|
|
{
|
|
|
|
result = PromoteTypeToNext(inType1);
|
|
|
|
inType1 = result;
|
|
|
|
*arg2 = result;
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
kind1 = ClassifyType(inType1);
|
|
|
|
kind2 = ClassifyType(*arg2);
|
|
|
|
if (kind1 != kind2)
|
|
|
|
{
|
|
|
|
*newType1 = inType1;
|
|
|
|
*newType2 = inType2;
|
|
|
|
result = InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
isBuiltIn1 = IS_BUILTIN_TYPE(inType1);
|
|
|
|
isBuiltIn2 = IS_BUILTIN_TYPE(*arg2);
|
|
|
|
|
|
|
|
if (isBuiltIn1 && isBuiltIn2)
|
|
|
|
{
|
|
|
|
switch (*arg1)
|
|
|
|
{
|
|
|
|
case (CHAROID):
|
1998-09-01 06:40:42 +02:00
|
|
|
switch (*arg2)
|
|
|
|
{
|
|
|
|
case (BPCHAROID):
|
|
|
|
case (VARCHAROID):
|
|
|
|
case (TEXTOID):
|
|
|
|
|
|
|
|
case (INT2OID):
|
|
|
|
case (INT4OID):
|
|
|
|
case (FLOAT4OID):
|
|
|
|
case (FLOAT8OID):
|
|
|
|
case (CASHOID):
|
|
|
|
|
|
|
|
case (POINTOID):
|
|
|
|
case (LSEGOID):
|
|
|
|
case (LINEOID):
|
|
|
|
case (BOXOID):
|
|
|
|
case (PATHOID):
|
|
|
|
case (CIRCLEOID):
|
|
|
|
case (POLYGONOID):
|
|
|
|
|
|
|
|
case (InvalidOid):
|
|
|
|
case (UNKNOWNOID):
|
|
|
|
case (BOOLOID):
|
|
|
|
default:
|
|
|
|
*arg1 = InvalidOid;
|
|
|
|
*arg2 = InvalidOid;
|
|
|
|
result = InvalidOid;
|
|
|
|
}
|
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
else if (isBuiltIn1 && !isBuiltIn2)
|
|
|
|
{
|
|
|
|
if ((promotedType = PromoteBuiltInType(*arg1)) != *arg1)
|
|
|
|
{
|
|
|
|
*arg1 = promotedType;
|
1998-09-01 05:29:17 +02:00
|
|
|
return promotedType;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
else if (CanCoerceType(*arg1, *arg2))
|
|
|
|
{
|
|
|
|
*arg1 = *arg2;
|
1998-09-01 05:29:17 +02:00
|
|
|
return *arg2;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!isBuiltIn1 && isBuiltIn2)
|
|
|
|
{
|
|
|
|
if ((promotedType = PromoteBuiltInType(*arg2)) != *arg2)
|
|
|
|
{
|
|
|
|
*arg2 = promotedType;
|
1998-09-01 05:29:17 +02:00
|
|
|
return promotedType;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
else if (CanCoerceType(*arg2, *arg1))
|
|
|
|
{
|
|
|
|
*arg2 = *arg1;
|
1998-09-01 05:29:17 +02:00
|
|
|
return *arg1;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (*arg2 == InvalidOid)
|
|
|
|
return InvalidOid;
|
|
|
|
|
|
|
|
switch (*arg1)
|
|
|
|
{
|
|
|
|
case (CHAROID):
|
|
|
|
switch (*arg2)
|
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
case (BPCHAROID):
|
|
|
|
case (VARCHAROID):
|
|
|
|
case (TEXTOID):
|
|
|
|
|
|
|
|
case (INT2OID):
|
|
|
|
case (INT4OID):
|
|
|
|
case (FLOAT4OID):
|
|
|
|
case (FLOAT8OID):
|
|
|
|
case (CASHOID):
|
|
|
|
|
|
|
|
case (POINTOID):
|
|
|
|
case (LSEGOID):
|
|
|
|
case (LINEOID):
|
|
|
|
case (BOXOID):
|
|
|
|
case (PATHOID):
|
|
|
|
case (CIRCLEOID):
|
|
|
|
case (POLYGONOID):
|
|
|
|
|
|
|
|
case (InvalidOid):
|
|
|
|
case (UNKNOWNOID):
|
|
|
|
case (BOOLOID):
|
|
|
|
default:
|
|
|
|
*arg1 = InvalidOid;
|
|
|
|
*arg2 = InvalidOid;
|
|
|
|
result = InvalidOid;
|
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
#endif
|