parse_coerce.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:10k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * parse_coerce.c
  4.  * handle type coersions/conversions for parser
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.18 1999/06/17 22:21:41 tgl Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <string.h>
  15. #include "postgres.h"
  16. #include "utils/builtins.h"
  17. #include "fmgr.h"
  18. #include "nodes/makefuncs.h"
  19. #include "parser/parse_expr.h"
  20. #include "catalog/pg_type.h"
  21. #include "parser/parse_func.h"
  22. #include "parser/parse_type.h"
  23. #include "parser/parse_target.h"
  24. #include "parser/parse_coerce.h"
  25. #include "utils/syscache.h"
  26. Oid DemoteType(Oid inType);
  27. Oid PromoteTypeToNext(Oid inType);
  28. static Oid PreferredType(CATEGORY category, Oid type);
  29. /* coerce_type()
  30.  * Convert a function argument to a different type.
  31.  */
  32. Node *
  33. coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId,
  34. int32 atttypmod)
  35. {
  36. Node    *result = NULL;
  37. Type targetType;
  38. Oid infunc;
  39. Datum val;
  40. if (targetTypeId == InvalidOid)
  41. result = node;
  42. else if (inputTypeId != targetTypeId)
  43. {
  44. /*
  45.  * one of the known-good transparent conversions? then drop
  46.  * through...
  47.  */
  48. if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
  49. result = node;
  50. /*
  51.  * if not unknown input type, try for explicit conversion using
  52.  * functions...
  53.  */
  54. else if (inputTypeId != UNKNOWNOID)
  55. {
  56. /*
  57.  * We already know there is a function which will do this, so
  58.  * let's use it
  59.  */
  60. FuncCall   *n = makeNode(FuncCall);
  61. n->funcname = typeidTypeName(targetTypeId);
  62. n->args = lcons(node, NIL);
  63. result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
  64. }
  65. else
  66. {
  67. if (nodeTag(node) == T_Const)
  68. {
  69. Const    *con = (Const *) node;
  70. val = (Datum) textout((struct varlena *) con->constvalue);
  71. targetType = typeidType(targetTypeId);
  72. infunc = typeInfunc(targetType);
  73. con = makeNode(Const);
  74. con->consttype = targetTypeId;
  75. con->constlen = typeLen(targetType);
  76. /*
  77.  * Use "-1" for varchar() type. For char(), we need to pad
  78.  * out the type with the proper number of spaces.  This
  79.  * was a major problem for DEFAULT string constants to
  80.  * char() types.
  81.  */
  82. con->constvalue = (Datum) fmgr(infunc,
  83.    val,
  84.    typeTypElem(targetType),
  85.    (targetTypeId != BPCHAROID) ? -1 : atttypmod);
  86. con->constisnull = false;
  87. con->constbyval = typeByVal(targetType);
  88. con->constisset = false;
  89. result = (Node *) con;
  90. }
  91. else
  92. result = node;
  93. }
  94. }
  95. else
  96. result = node;
  97. return result;
  98. }
  99. /* can_coerce_type()
  100.  * Can input_typeids be coerced to func_typeids?
  101.  *
  102.  * There are a few types which are known apriori to be convertible.
  103.  * We will check for those cases first, and then look for possible
  104.  * conversion functions.
  105.  *
  106.  * Notes:
  107.  * This uses the same mechanism as the CAST() SQL construct in gram.y.
  108.  * We should also check the function return type on candidate conversion
  109.  * routines just to be safe but we do not do that yet...
  110.  * We need to have a zero-filled OID array here, otherwise the cache lookup fails.
  111.  * - thomas 1998-03-31
  112.  */
  113. bool
  114. can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
  115. {
  116. HeapTuple ftup;
  117. int i;
  118. Type tp;
  119. Oid oid_array[MAXFARGS];
  120. /* run through argument list... */
  121. for (i = 0; i < nargs; i++)
  122. {
  123. if (input_typeids[i] != func_typeids[i])
  124. {
  125. /*
  126.  * one of the known-good transparent conversions? then drop
  127.  * through...
  128.  */
  129. if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
  130. ;
  131. /* don't know what to do for the output type? then quit... */
  132. else if (func_typeids[i] == InvalidOid)
  133. return false;
  134. /* don't know what to do for the input type? then quit... */
  135. else if (input_typeids[i] == InvalidOid)
  136. return false;
  137. /*
  138.  * if not unknown input type, try for explicit conversion
  139.  * using functions...
  140.  */
  141. else if (input_typeids[i] != UNKNOWNOID)
  142. {
  143. MemSet(oid_array, 0, MAXFARGS * sizeof(Oid));
  144. oid_array[0] = input_typeids[i];
  145. /*
  146.  * look for a single-argument function named with the
  147.  * target type name
  148.  */
  149. ftup = SearchSysCacheTuple(PRONAME,
  150. PointerGetDatum(typeidTypeName(func_typeids[i])),
  151.    Int32GetDatum(1),
  152.    PointerGetDatum(oid_array),
  153.    0);
  154. /*
  155.  * should also check the function return type just to be
  156.  * safe...
  157.  */
  158. if (!HeapTupleIsValid(ftup))
  159. return false;
  160. }
  161. tp = typeidType(input_typeids[i]);
  162. if (typeTypeFlag(tp) == 'c')
  163. return false;
  164. }
  165. }
  166. return true;
  167. }
  168. /* TypeCategory()
  169.  * Assign a category to the specified OID.
  170.  */
  171. CATEGORY
  172. TypeCategory(Oid inType)
  173. {
  174. CATEGORY result;
  175. switch (inType)
  176. {
  177. case (BOOLOID):
  178. result = BOOLEAN_TYPE;
  179. break;
  180. case (CHAROID):
  181. case (BPCHAROID):
  182. case (VARCHAROID):
  183. case (TEXTOID):
  184. result = STRING_TYPE;
  185. break;
  186. case (OIDOID):
  187. case (INT2OID):
  188. case (INT4OID):
  189. case (INT8OID):
  190. case (FLOAT4OID):
  191. case (FLOAT8OID):
  192. case (CASHOID):
  193. result = NUMERIC_TYPE;
  194. break;
  195. case (ABSTIMEOID):
  196. case (TIMESTAMPOID):
  197. case (DATETIMEOID):
  198. result = DATETIME_TYPE;
  199. break;
  200. case (RELTIMEOID):
  201. case (TIMESPANOID):
  202. result = TIMESPAN_TYPE;
  203. break;
  204. case (POINTOID):
  205. case (LSEGOID):
  206. case (LINEOID):
  207. case (BOXOID):
  208. case (PATHOID):
  209. case (CIRCLEOID):
  210. case (POLYGONOID):
  211. result = GEOMETRIC_TYPE;
  212. break;
  213. case (INETOID):
  214. case (CIDROID):
  215. result = NETWORK_TYPE;
  216. break;
  217. default:
  218. result = USER_TYPE;
  219. break;
  220. }
  221. return result;
  222. } /* TypeCategory() */
  223. /* IsPreferredType()
  224.  * Check if this type is a preferred type.
  225.  */
  226. bool
  227. IsPreferredType(CATEGORY category, Oid type)
  228. {
  229. return type == PreferredType(category, type);
  230. } /* IsPreferredType() */
  231. /* PreferredType()
  232.  * Return the preferred type OID for the specified category.
  233.  */
  234. static Oid
  235. PreferredType(CATEGORY category, Oid type)
  236. {
  237. Oid result;
  238. switch (category)
  239. {
  240. case (BOOLEAN_TYPE):
  241. result = BOOLOID;
  242. break;
  243. case (STRING_TYPE):
  244. result = TEXTOID;
  245. break;
  246. case (NUMERIC_TYPE):
  247. if (type == OIDOID)
  248. result = OIDOID;
  249. else
  250. result = FLOAT8OID;
  251. break;
  252. case (DATETIME_TYPE):
  253. result = DATETIMEOID;
  254. break;
  255. case (TIMESPAN_TYPE):
  256. result = TIMESPANOID;
  257. break;
  258. case (NETWORK_TYPE):
  259. result = INETOID;
  260. break;
  261. case (GEOMETRIC_TYPE):
  262. case (USER_TYPE):
  263. result = type;
  264. break;
  265. default:
  266. result = UNKNOWNOID;
  267. break;
  268. }
  269. return result;
  270. } /* PreferredType() */
  271. #ifdef NOT_USED
  272. Oid
  273. PromoteTypeToNext(Oid inType)
  274. {
  275. Oid result;
  276. switch (inType)
  277. {
  278. case (CHAROID):
  279. case (BPCHAROID):
  280. result = VARCHAROID;
  281. break;
  282. case (VARCHAROID):
  283. result = TEXTOID;
  284. break;
  285. case (INT2OID):
  286. case (CASHOID):
  287. result = INT4OID;
  288. break;
  289. case (INT4OID):
  290. case (INT8OID):
  291. case (FLOAT4OID):
  292. result = FLOAT8OID;
  293. break;
  294. case (DATEOID):
  295. case (ABSTIMEOID):
  296. case (TIMESTAMPOID):
  297. result = DATETIMEOID;
  298. break;
  299. case (TIMEOID):
  300. case (RELTIMEOID):
  301. result = TIMESPANOID;
  302. break;
  303. case (BOOLOID):
  304. case (TEXTOID):
  305. case (FLOAT8OID):
  306. case (DATETIMEOID):
  307. case (TIMESPANOID):
  308. default:
  309. result = inType;
  310. break;
  311. }
  312. return result;
  313. } /* PromoteTypeToNext() */
  314. Oid
  315. DemoteType(Oid inType)
  316. {
  317. Oid result;
  318. switch (inType)
  319. {
  320. case (FLOAT4OID):
  321. case (FLOAT8OID):
  322. result = INT4OID;
  323. break;
  324. default:
  325. result = inType;
  326. break;
  327. }
  328. return result;
  329. } /* DemoteType() */
  330. Oid
  331. PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
  332. {
  333. Oid result;
  334. if (inType1 == inType2)
  335. {
  336. result = PromoteTypeToNext(inType1);
  337. inType1 = result;
  338. *arg2 = result;
  339. return result;
  340. }
  341. kind1 = ClassifyType(inType1);
  342. kind2 = ClassifyType(*arg2);
  343. if (kind1 != kind2)
  344. {
  345. *newType1 = inType1;
  346. *newType2 = inType2;
  347. result = InvalidOid;
  348. }
  349. isBuiltIn1 = IS_BUILTIN_TYPE(inType1);
  350. isBuiltIn2 = IS_BUILTIN_TYPE(*arg2);
  351. if (isBuiltIn1 && isBuiltIn2)
  352. {
  353. switch (*arg1)
  354. {
  355. case (CHAROID):
  356. switch (*arg2)
  357. {
  358. case (BPCHAROID):
  359. case (VARCHAROID):
  360. case (TEXTOID):
  361. case (INT2OID):
  362. case (INT4OID):
  363. case (FLOAT4OID):
  364. case (FLOAT8OID):
  365. case (CASHOID):
  366. case (POINTOID):
  367. case (LSEGOID):
  368. case (LINEOID):
  369. case (BOXOID):
  370. case (PATHOID):
  371. case (CIRCLEOID):
  372. case (POLYGONOID):
  373. case (InvalidOid):
  374. case (UNKNOWNOID):
  375. case (BOOLOID):
  376. default:
  377. *arg1 = InvalidOid;
  378. *arg2 = InvalidOid;
  379. result = InvalidOid;
  380. }
  381. }
  382. }
  383. else if (isBuiltIn1 && !isBuiltIn2)
  384. {
  385. if ((promotedType = PromoteBuiltInType(*arg1)) != *arg1)
  386. {
  387. *arg1 = promotedType;
  388. return promotedType;
  389. }
  390. else if (CanCoerceType(*arg1, *arg2))
  391. {
  392. *arg1 = *arg2;
  393. return *arg2;
  394. }
  395. }
  396. else if (!isBuiltIn1 && isBuiltIn2)
  397. {
  398. if ((promotedType = PromoteBuiltInType(*arg2)) != *arg2)
  399. {
  400. *arg2 = promotedType;
  401. return promotedType;
  402. }
  403. else if (CanCoerceType(*arg2, *arg1))
  404. {
  405. *arg2 = *arg1;
  406. return *arg1;
  407. }
  408. }
  409. if (*arg2 == InvalidOid)
  410. return InvalidOid;
  411. switch (*arg1)
  412. {
  413. case (CHAROID):
  414. switch (*arg2)
  415. {
  416. case (BPCHAROID):
  417. case (VARCHAROID):
  418. case (TEXTOID):
  419. case (INT2OID):
  420. case (INT4OID):
  421. case (FLOAT4OID):
  422. case (FLOAT8OID):
  423. case (CASHOID):
  424. case (POINTOID):
  425. case (LSEGOID):
  426. case (LINEOID):
  427. case (BOXOID):
  428. case (PATHOID):
  429. case (CIRCLEOID):
  430. case (POLYGONOID):
  431. case (InvalidOid):
  432. case (UNKNOWNOID):
  433. case (BOOLOID):
  434. default:
  435. *arg1 = InvalidOid;
  436. *arg2 = InvalidOid;
  437. result = InvalidOid;
  438. }
  439. }
  440. }
  441. #endif