Break parser functions into smaller files, group together.

This commit is contained in:
Bruce Momjian 1997-11-25 22:07:18 +00:00
parent 3aff4011c7
commit 4a5b781d71
62 changed files with 5590 additions and 5027 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.28 1997/11/24 05:07:42 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.29 1997/11/25 21:58:35 momjian Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@ -20,8 +20,9 @@
#include <postgres.h>
#include <parser/catalog_utils.h>
#include <catalog/pg_type.h>
#include <nodes/parsenodes.h>
#include <parser/parse_type.h>
#include <utils/builtins.h>
#include <utils/fcache.h>
#include <utils/syscache.h>
@ -377,10 +378,10 @@ TupleDescInitEntry(TupleDesc desc,
*/
if (attisset)
{
Type t = type("oid");
Type t = typeidType(OIDOID);
att->attlen = tlen(t);
att->attbyval = tbyval(t);
att->attlen = typeLen(t);
att->attbyval = typeByVal(t);
}
else
{
@ -410,12 +411,12 @@ TupleDescMakeSelfReference(TupleDesc desc,
char *relname)
{
AttributeTupleForm att;
Type t = type("oid");
Type t = typeidType(OIDOID);
att = desc->attrs[attnum - 1];
att->atttypid = TypeShellMake(relname);
att->attlen = tlen(t);
att->attbyval = tbyval(t);
att->attlen = typeLen(t);
att->attbyval = typeByVal(t);
att->attnelems = 0;
}

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.33 1997/11/24 05:08:07 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.34 1997/11/25 21:58:40 momjian Exp $
*
* INTERFACE ROUTINES
* heap_creatr() - Create an uncataloged heap relation
@ -42,11 +42,12 @@
#include <catalog/pg_attrdef.h>
#include <catalog/pg_relcheck.h>
#include <commands/trigger.h>
#include <parser/parse_expr.h>
#include <parser/parse_node.h>
#include <parser/parse_type.h>
#include <storage/bufmgr.h>
#include <storage/lmgr.h>
#include <storage/smgr.h>
#include <parser/catalog_utils.h>
#include <parser/parse_query.h>
#include <rewrite/rewriteRemove.h>
#include <utils/builtins.h>
#include <utils/mcxt.h>
@ -722,8 +723,8 @@ addNewRelationType(char *typeName, Oid new_rel_oid)
*/
new_type_oid = TypeCreate(typeName, /* type name */
new_rel_oid, /* relation oid */
tlen(type("oid")), /* internal size */
tlen(type("oid")), /* external size */
typeLen(typeidType(OIDOID)), /* internal size */
typeLen(typeidType(OIDOID)), /* external size */
'c', /* type-type (catalog) */
',', /* default array delimiter */
"int4in", /* input procedure */

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.29 1997/11/24 05:08:11 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.30 1997/11/25 21:58:43 momjian Exp $
*
*
* INTERFACE ROUTINES
@ -30,26 +30,27 @@
#include <fmgr.h>
#include <access/genam.h>
#include <access/heapam.h>
#include <storage/lmgr.h>
#include <miscadmin.h>
#include <access/istrat.h>
#include <access/xact.h>
#include <parser/catalog_utils.h>
#include <storage/smgr.h>
#include <utils/builtins.h>
#include <utils/mcxt.h>
#include <utils/relcache.h>
#include <utils/syscache.h>
#include <utils/tqual.h>
#include <bootstrap/bootstrap.h>
#include <catalog/catname.h>
#include <catalog/catalog.h>
#include <catalog/indexing.h>
#include <catalog/heap.h>
#include <catalog/index.h>
#include <catalog/pg_type.h>
#include <executor/executor.h>
#include <miscadmin.h>
#include <optimizer/clauses.h>
#include <optimizer/prep.h>
#include <access/istrat.h>
#include <parser/parse_func.h>
#include <storage/lmgr.h>
#include <storage/smgr.h>
#include <utils/builtins.h>
#include <utils/mcxt.h>
#include <utils/relcache.h>
#include <utils/syscache.h>
#include <utils/tqual.h>
#ifndef HAVE_MEMMOVE
#include <regex/utils.h>

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.16 1997/11/24 05:08:15 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.17 1997/11/25 21:58:46 momjian Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
@ -20,9 +20,10 @@
#include <utils/syscache.h>
#include <utils/tqual.h>
#include <access/heapam.h>
#include <parser/catalog_utils.h>
#include <catalog/catname.h>
#include <catalog/pg_operator.h>
#include <catalog/pg_type.h>
#include <parser/parse_oper.h>
#include <storage/bufmgr.h>
#include <fmgr.h>
#include <miscadmin.h>

View File

@ -7,28 +7,28 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.9 1997/09/18 20:20:18 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.10 1997/11/25 21:58:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
#include <fmgr.h>
#include <miscadmin.h>
#include <utils/syscache.h>
#include <catalog/pg_proc.h>
#include <access/heapam.h>
#include <access/relscan.h>
#include <fmgr.h>
#include <utils/builtins.h>
#include <utils/sets.h>
#include <catalog/catname.h>
#include <catalog/indexing.h>
#include <parser/parse_query.h>
#include <catalog/pg_type.h>
#include <parser/parse_node.h>
#include <tcop/tcopprot.h>
#include <parser/catalog_utils.h>
#include <utils/builtins.h>
#include <utils/sets.h>
#include <utils/lsyscache.h>
#include <optimizer/internal.h>
#include <optimizer/planner.h>
#include <utils/lsyscache.h>
#include <miscadmin.h>
#ifndef HAVE_MEMMOVE
#include <regex/utils.h>
#else
@ -200,7 +200,7 @@ ProcedureCreate(char *procedureName,
if (parameterCount == 1 &&
(toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
defined &&
(relid = typeid_get_relid(toid)) != 0 &&
(relid = typeidTypeRelid(toid)) != 0 &&
get_attnum(relid, procedureName) != InvalidAttrNumber)
elog(WARN, "method %s already an attribute of type %s",
procedureName, strVal(lfirst(argList)));

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.13 1997/11/24 05:08:17 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.14 1997/11/25 21:58:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,9 +20,10 @@
#include <utils/builtins.h>
#include <utils/tqual.h>
#include <fmgr.h>
#include <parser/catalog_utils.h>
#include <catalog/catname.h>
#include <catalog/indexing.h>
#include <catalog/pg_type.h>
#include <parser/parse_func.h>
#include <storage/lmgr.h>
#include <miscadmin.h>
#ifndef HAVE_MEMMOVE

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.7 1997/09/08 02:22:18 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.8 1997/11/25 21:59:11 momjian Exp $
*
* NOTES
* At the point the version is defined, 2 physical relations are created
@ -30,6 +30,7 @@
#include <utils/builtins.h>
#include <commands/version.h>
#include <access/xact.h> /* for GetCurrentXactStartTime */
#include <parser/parse_node.h>
#include <tcop/tcopprot.h>
#define MAX_QUERY_LEN 1024

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.14 1997/09/18 20:20:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.15 1997/11/25 21:58:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,12 +16,11 @@
#include <postgres.h>
#include <parser/catalog_utils.h>
#include <parser/parse_query.h> /* for MakeTimeRange() */
#include <nodes/plannodes.h>
#include <tcop/tcopprot.h>
#include <lib/stringinfo.h>
#include <commands/explain.h>
#include <parser/parse_node.h>
#include <optimizer/planner.h>
#include <access/xact.h>

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.12 1997/11/21 18:09:51 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.13 1997/11/25 21:59:00 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,9 +20,9 @@
#include <catalog/pg_type.h>
#include <commands/recipe.h>
#include <libpq/libpq-be.h>
#include <parser/parse_node.h>
#include <utils/builtins.h>
#include <utils/relcache.h> /* for RelationNameGetRelation */
#include <parser/parse_query.h>
#include <rewrite/rewriteHandler.h>
#include <rewrite/rewriteManip.h>
#include <tcop/pquery.h>
@ -488,7 +488,7 @@ tg_replaceNumberedParam(Node *expression,
* "result" attribute from the tee relation
*/
isRel = (typeid_get_relid(p->paramtype) != 0);
isRel = (typeidTypeRelid(p->paramtype) != 0);
if (isRel)
{
newVar = makeVar(rt_ind,

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.16 1997/11/20 23:21:13 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.17 1997/11/25 21:59:03 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,7 +24,8 @@
#include <catalog/pg_language.h>
#include <catalog/pg_operator.h>
#include <catalog/pg_proc.h>
#include <parser/catalog_utils.h>
#include <catalog/pg_type.h>
#include <parser/parse_func.h>
#include <storage/bufmgr.h>
#include <fmgr.h>
#ifndef HAVE_MEMMOVE

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.52 1997/11/21 19:59:34 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.53 1997/11/25 21:59:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -36,6 +36,7 @@
#include <catalog/pg_statistic.h>
#include <catalog/pg_type.h>
#include <catalog/pg_operator.h>
#include <parser/parse_oper.h>
#include <storage/smgr.h>
#include <storage/lmgr.h>
#include <utils/inval.h>
@ -44,7 +45,6 @@
#include <utils/syscache.h>
#include <utils/builtins.h>
#include <commands/vacuum.h>
#include <parser/catalog_utils.h>
#include <storage/bufpage.h>
#include "storage/shmem.h"
#ifndef HAVE_GETRUSAGE

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.15 1997/11/21 18:09:58 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.16 1997/11/25 21:59:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,8 +21,8 @@
#include <access/xact.h>
#include <utils/builtins.h>
#include <nodes/relation.h>
#include <parser/catalog_utils.h>
#include <parser/parse_query.h>
#include <parser/parse_relation.h>
#include <parser/parse_type.h>
#include <rewrite/rewriteDefine.h>
#include <rewrite/rewriteHandler.h>
#include <rewrite/rewriteManip.h>
@ -72,7 +72,7 @@ DefineVirtualRelation(char *relname, List *tlist)
entry = lfirst(t);
res = entry->resdom;
resname = res->resname;
restypename = tname(get_id_type(res->restype));
restypename = typeidTypeName(res->restype);
typename = makeNode(TypeName);

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.10 1997/09/18 20:20:32 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.11 1997/11/25 21:59:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -125,11 +125,11 @@
#undef ExecStoreTuple
#include "access/tupdesc.h"
#include "catalog/pg_type.h"
#include "parser/parse_type.h"
#include "storage/bufmgr.h"
#include "utils/palloc.h"
#include "utils/lsyscache.h"
#include "storage/bufmgr.h"
#include "parser/catalog_utils.h"
#include "catalog/pg_type.h"
static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.12 1997/09/18 20:20:37 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.13 1997/11/25 21:59:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,7 +21,6 @@
#include "nodes/plannodes.h"
#include "catalog/pg_proc.h"
#include "parser/parse_query.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"

View File

@ -23,12 +23,12 @@
#include "access/heapam.h"
#include "catalog/pg_aggregate.h"
#include "catalog/catalog.h"
#include "parser/parse_type.h"
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "storage/bufmgr.h"
#include "utils/palloc.h"
#include "utils/syscache.h"
#include "parser/catalog_utils.h"
/*
* AggFuncInfo -
@ -172,7 +172,7 @@ ExecAgg(Agg *node)
if (!HeapTupleIsValid(aggTuple))
elog(WARN, "ExecAgg: cache lookup failed for aggregate \"%s\"(%s)",
aggname,
tname(get_id_type(agg->basetype)));
typeidTypeName(agg->basetype));
aggp = (Form_pg_aggregate) GETSTRUCT(aggTuple);
xfn1_oid = aggp->aggtransfn1;

View File

@ -6,6 +6,7 @@
*-------------------------------------------------------------------------
*/
#include "executor/spi.h"
#include "catalog/pg_type.h"
#include "access/printtup.h"
#include "fmgr.h"

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.15 1997/11/20 23:21:40 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.16 1997/11/25 21:59:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,7 +22,6 @@
#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"
#include "parser/parse_query.h"
#include "utils/syscache.h"
#include "utils/builtins.h" /* for namecpy */

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.10 1997/10/25 01:09:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.11 1997/11/25 21:59:44 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -26,11 +26,11 @@
#include "nodes/parsenodes.h"
#include "nodes/print.h"
#include "parser/parsetree.h"
#include "parser/catalog_utils.h"
#include "access/heapam.h"
#include "utils/lsyscache.h"
#include "nodes/nodes.h"
#include "nodes/plannodes.h"
#include "parser/parse_relation.h"
#include "optimizer/clauses.h"
static char *plannode_type(Plan *p);
@ -194,7 +194,7 @@ print_expr(Node *expr, List *rtable)
r = heap_openr(relname);
if (rt->refname)
relname = rt->refname; /* table renamed */
attname = getAttrName(r, var->varattno);
attname = attnumAttName(r, var->varattno);
heap_close(r);
}
break;

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.6 1997/09/08 21:45:10 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.7 1997/11/25 21:59:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -641,10 +641,10 @@ xfunc_width(LispValue clause)
}
else if (IsA(clause, Param))
{
if (typeid_get_relid(get_paramtype((Param) clause)))
if (typeidTypeRelid(get_paramtype((Param) clause)))
{
/* Param node returns a tuple. Find its width */
rd = heap_open(typeid_get_relid(get_paramtype((Param) clause)));
rd = heap_open(typeidTypeRelid(get_paramtype((Param) clause)));
retval = xfunc_tuple_width(rd);
heap_close(rd);
}
@ -659,7 +659,7 @@ xfunc_width(LispValue clause)
else
{
/* Param node returns a base type */
retval = tlen(get_id_type(get_paramtype((Param) clause)));
retval = typeLen(typeidType(get_paramtype((Param) clause)));
}
goto exit;
}
@ -1324,9 +1324,9 @@ xfunc_func_width(RegProcedure funcid, LispValue args)
proc = (Form_pg_proc) GETSTRUCT(tupl);
/* if function returns a tuple, get the width of that */
if (typeid_get_relid(proc->prorettype))
if (typeidTypeRelid(proc->prorettype))
{
rd = heap_open(typeid_get_relid(proc->prorettype));
rd = heap_open(typeidTypeRelid(proc->prorettype));
retval = xfunc_tuple_width(rd);
heap_close(rd);
goto exit;

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.15 1997/09/08 21:45:13 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.16 1997/11/25 21:59:56 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,7 +31,6 @@
#include "utils/palloc.h"
#include "utils/builtins.h"
#include "parser/parse_query.h"
#include "optimizer/clauseinfo.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.10 1997/11/21 18:10:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.11 1997/11/25 21:59:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,9 +19,8 @@
#include "nodes/plannodes.h"
#include "nodes/parsenodes.h"
#include "nodes/relation.h"
#include "parser/parse_expr.h"
#include "parser/catalog_utils.h"
#include "parser/parse_query.h"
#include "utils/elog.h"
#include "utils/lsyscache.h"
#include "access/heapam.h"
@ -310,7 +309,7 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
}
/* by here, the function is declared to return some type */
if ((typ = (Type) get_id_type(rettype)) == NULL)
if ((typ = typeidType(rettype)) == NULL)
elog(WARN, "can't find return type %d for function\n", rettype);
/*
@ -318,21 +317,21 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
* final query had better be a retrieve.
*/
if (cmd != CMD_SELECT)
elog(WARN, "function declared to return type %s, but final query is not a retrieve", tname(typ));
elog(WARN, "function declared to return type %s, but final query is not a retrieve", typeTypeName(typ));
/*
* test 4: for base type returns, the target list should have exactly
* one entry, and its type should agree with what the user declared.
*/
if (get_typrelid(typ) == InvalidOid)
if (typeTypeRelid(typ) == InvalidOid)
{
if (exec_tlist_length(tlist) > 1)
elog(WARN, "function declared to return %s returns multiple values in final retrieve", tname(typ));
elog(WARN, "function declared to return %s returns multiple values in final retrieve", typeTypeName(typ));
resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
if (resnode->restype != rettype)
elog(WARN, "return type mismatch in function: declared to return %s, returns %s", tname(typ), tname(get_id_type(resnode->restype)));
elog(WARN, "return type mismatch in function: declared to return %s, returns %s", typeTypeName(typ), typeidTypeName(resnode->restype));
/* by here, base return types match */
return;
@ -358,16 +357,16 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
* declared return type, and be sure that attributes 1 .. n in the
* target list match the declared types.
*/
reln = heap_open(get_typrelid(typ));
reln = heap_open(typeTypeRelid(typ));
if (!RelationIsValid(reln))
elog(WARN, "cannot open relation relid %d", get_typrelid(typ));
elog(WARN, "cannot open relation relid %d", typeTypeRelid(typ));
relid = reln->rd_id;
relnatts = reln->rd_rel->relnatts;
if (exec_tlist_length(tlist) != relnatts)
elog(WARN, "function declared to return type %s does not retrieve (%s.*)", tname(typ), tname(typ));
elog(WARN, "function declared to return type %s does not retrieve (%s.*)", typeTypeName(typ), typeTypeName(typ));
/* expect attributes 1 .. n in order */
for (i = 1; i <= relnatts; i++)
@ -397,14 +396,14 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
else if (IsA(thenode, Func))
tletype = (Oid) get_functype((Func *) thenode);
else
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
}
else
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
#endif
/* reach right in there, why don't you? */
if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
}
heap_close(reln);

View File

@ -7,13 +7,14 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.5 1997/09/08 21:45:36 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.6 1997/11/25 22:00:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include "postgres.h"
#include "catalog/pg_type.h"
#include "nodes/pg_list.h"
#include "nodes/relation.h"
#include "nodes/primnodes.h"
@ -24,9 +25,9 @@
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/palloc.h"
#include "parser/parse_type.h"
#include "parser/parsetree.h" /* for getrelid() */
#include "parser/catalog_utils.h"
#include "optimizer/internal.h"
#include "optimizer/prep.h"
@ -278,7 +279,7 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
attisset = get_attisset( /* type_id, */ relid, attname);
if (attisset)
{
typlen = tlen(type("oid"));
typlen = typeLen(typeidType(OIDOID));
}
else
{

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.8 1997/11/21 18:10:44 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.9 1997/11/25 22:00:10 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,7 +22,6 @@
#include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "parser/parse_query.h"
#include "parser/parsetree.h"
#include "utils/elog.h"

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.7 1997/09/08 21:45:55 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.8 1997/11/25 22:00:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -26,7 +26,6 @@
#include "optimizer/clauses.h"
#include "nodes/makefuncs.h"
#include "parser/catalog_utils.h"
static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);

View File

@ -4,7 +4,7 @@
# Makefile for parser
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.11 1997/11/24 05:20:57 momjian Exp $
# $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.12 1997/11/25 22:00:21 momjian Exp $
#
#-------------------------------------------------------------------------
@ -22,8 +22,9 @@ CFLAGS+= -Wno-error
endif
OBJS= analyze.o catalog_utils.o gram.o \
keywords.o parser.o parse_query.o scan.o scansup.o
OBJS= analyze.o gram.o keywords.o parser.o parse_agg.o parse_clause.o \
parse_expr.o parse_func.o parse_node.o parse_oper.o parse_relation.o \
parse_type.o parse_target.o scan.o scansup.o
all: SUBSYS.o

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.71 1997/11/24 16:55:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.72 1997/11/25 22:05:29 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -39,8 +39,6 @@
#include "nodes/parsenodes.h"
#include "nodes/print.h"
#include "parser/gramparse.h"
#include "parser/catalog_utils.h"
#include "parser/parse_query.h"
#include "utils/acl.h"
#include "catalog/catname.h"
#include "utils/elog.h"
@ -49,8 +47,11 @@
static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
static bool QueryIsRule = FALSE;
static Node *saved_In_Expr;
static Oid *param_type_info;
static int pfunc_num_args;
extern List *parsetree;
/*
* If you need access to certain yacc-generated variables and find that
* they're static by default, uncomment the next line. (this is not a
@ -64,6 +65,9 @@ static List *makeConstantList( A_Const *node);
static char *FlattenStringList(List *list);
static char *fmtId(char *rawid);
static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
static void param_type_init(Oid *typev, int nargs);
Oid param_type(int t); /* used in parse_expr.c */
/* old versions of flex define this as a macro */
#if defined(yywrap)
@ -2324,7 +2328,7 @@ Typename: Array opt_array_bounds
* emp(name=text,mgr=emp)
*/
$$->setof = TRUE;
else if (get_typrelid((Type)type($$->name)) != InvalidOid)
else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
/* (Eventually add in here that the set can only
* contain one element.)
*/
@ -3690,4 +3694,24 @@ printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp)
#endif
return(cp);
} /* fmtId() */
}
/*
* param_type_init()
*
* keep enough information around fill out the type of param nodes
* used in postquel functions
*/
static void
param_type_init(Oid *typev, int nargs)
{
pfunc_num_args = nargs;
param_type_info = typev;
}
Oid param_type(int t)
{
if ((t > pfunc_num_args) || (t == 0))
return InvalidOid;
return param_type_info[t - 1];
}

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.24 1997/11/24 05:32:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.25 1997/11/25 22:05:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,8 +18,8 @@
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
#include "parse.h"
#include "utils/elog.h"
#include "parser/keywords.h"
#include "utils/elog.h"
/*
* List of (keyword-name, keyword-token-value) pairs.

View File

@ -0,0 +1,371 @@
/*-------------------------------------------------------------------------
*
* parse_agg.c--
* handle aggregates in parser
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.1 1997/11/25 22:05:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/pg_aggregate.h"
#include "nodes/nodeFuncs.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h"
#include "optimizer/clauses.h"
#include "parser/parse_agg.h"
#include "parser/parse_node.h"
#include "parser/parse_target.h"
#include "utils/syscache.h"
#ifdef 0
#include "nodes/nodes.h"
#include "nodes/params.h"
#include "parse.h" /* for AND, OR, etc. */
#include "catalog/pg_type.h" /* for INT4OID, etc. */
#include "catalog/pg_proc.h"
#include "utils/elog.h"
#include "utils/builtins.h" /* namecmp(), textout() */
#include "utils/lsyscache.h"
#include "utils/palloc.h"
#include "utils/mcxt.h"
#include "utils/acl.h"
#include "nodes/makefuncs.h" /* for makeResdom(), etc. */
#include "commands/sequence.h"
#endif
/*
* AddAggToParseState -
* add the aggregate to the list of unique aggregates in pstate.
*
* SIDE EFFECT: aggno in target list entry will be modified
*/
void
AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
{
List *ag;
int i;
/*
* see if we have the aggregate already (we only need to record the
* aggregate once)
*/
i = 0;
foreach(ag, pstate->p_aggs)
{
Aggreg *a = lfirst(ag);
if (!strcmp(a->aggname, aggreg->aggname) &&
equal(a->target, aggreg->target))
{
/* fill in the aggno and we're done */
aggreg->aggno = i;
return;
}
i++;
}
/* not found, new aggregate */
aggreg->aggno = i;
pstate->p_numAgg++;
pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
return;
}
/*
* finalizeAggregates -
* fill in qry_aggs from pstate. Also checks to make sure that aggregates
* are used in the proper place.
*/
void
finalizeAggregates(ParseState *pstate, Query *qry)
{
List *l;
int i;
parseCheckAggregates(pstate, qry);
qry->qry_numAgg = pstate->p_numAgg;
qry->qry_aggs =
(Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
i = 0;
foreach(l, pstate->p_aggs)
qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
}
/*
* contain_agg_clause--
* Recursively find aggreg nodes from a clause.
*
* Returns true if any aggregate found.
*/
bool
contain_agg_clause(Node *clause)
{
if (clause == NULL)
return FALSE;
else if (IsA(clause, Aggreg))
return TRUE;
else if (IsA(clause, Iter))
return contain_agg_clause(((Iter *) clause)->iterexpr);
else if (single_node(clause))
return FALSE;
else if (or_clause(clause))
{
List *temp;
foreach(temp, ((Expr *) clause)->args)
if (contain_agg_clause(lfirst(temp)))
return TRUE;
return FALSE;
}
else if (is_funcclause(clause))
{
List *temp;
foreach(temp, ((Expr *) clause)->args)
if (contain_agg_clause(lfirst(temp)))
return TRUE;
return FALSE;
}
else if (IsA(clause, ArrayRef))
{
List *temp;
foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
if (contain_agg_clause(lfirst(temp)))
return TRUE;
foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
if (contain_agg_clause(lfirst(temp)))
return TRUE;
if (contain_agg_clause(((ArrayRef *) clause)->refexpr))
return TRUE;
if (contain_agg_clause(((ArrayRef *) clause)->refassgnexpr))
return TRUE;
return FALSE;
}
else if (not_clause(clause))
return contain_agg_clause((Node *) get_notclausearg((Expr *) clause));
else if (is_opclause(clause))
return (contain_agg_clause((Node *) get_leftop((Expr *) clause)) ||
contain_agg_clause((Node *) get_rightop((Expr *) clause)));
return FALSE;
}
/*
* exprIsAggOrGroupCol -
* returns true if the expression does not contain non-group columns.
*/
bool
exprIsAggOrGroupCol(Node *expr, List *groupClause)
{
List *gl;
if (expr == NULL || IsA(expr, Const) ||
IsA(expr, Param) ||IsA(expr, Aggreg))
return TRUE;
foreach(gl, groupClause)
{
GroupClause *grpcl = lfirst(gl);
if (equal(expr, grpcl->entry->expr))
return TRUE;
}
if (IsA(expr, Expr))
{
List *temp;
foreach(temp, ((Expr *) expr)->args)
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
return FALSE;
return TRUE;
}
return FALSE;
}
/*
* tleIsAggOrGroupCol -
* returns true if the TargetEntry is Agg or GroupCol.
*/
bool
tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
{
Node *expr = tle->expr;
List *gl;
if (expr == NULL || IsA(expr, Const) ||IsA(expr, Param))
return TRUE;
foreach(gl, groupClause)
{
GroupClause *grpcl = lfirst(gl);
if (tle->resdom->resno == grpcl->entry->resdom->resno)
{
if (contain_agg_clause((Node *) expr))
elog(WARN, "parser: aggregates not allowed in GROUP BY clause");
return TRUE;
}
}
if (IsA(expr, Aggreg))
return TRUE;
if (IsA(expr, Expr))
{
List *temp;
foreach(temp, ((Expr *) expr)->args)
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
return FALSE;
return TRUE;
}
return FALSE;
}
/*
* parseCheckAggregates -
* this should really be done earlier but the current grammar
* cannot differentiate functions from aggregates. So we have do check
* here when the target list and the qualifications are finalized.
*/
void
parseCheckAggregates(ParseState *pstate, Query *qry)
{
List *tl;
Assert(pstate->p_numAgg > 0);
/*
* aggregates never appear in WHERE clauses. (we have to check where
* clause first because if there is an aggregate, the check for
* non-group column in target list may fail.)
*/
if (contain_agg_clause(qry->qual))
elog(WARN, "parser: aggregates not allowed in WHERE clause");
/*
* the target list can only contain aggregates, group columns and
* functions thereof.
*/
foreach(tl, qry->targetList)
{
TargetEntry *tle = lfirst(tl);
if (!tleIsAggOrGroupCol(tle, qry->groupClause))
elog(WARN,
"parser: illegal use of aggregates or non-group column in target list");
}
/*
* the expression specified in the HAVING clause has the same
* restriction as those in the target list.
*/
/*
* Need to change here when we get HAVING works. Currently
* qry->havingQual is NULL. - vadim 04/05/97
if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
elog(WARN,
"parser: illegal use of aggregates or non-group column in HAVING clause");
*/
return;
}
Aggreg *
ParseAgg(char *aggname, Oid basetype, Node *target)
{
Oid fintype;
Oid vartype;
Oid xfn1;
Form_pg_aggregate aggform;
Aggreg *aggreg;
HeapTuple theAggTuple;
theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
ObjectIdGetDatum(basetype),
0, 0);
if (!HeapTupleIsValid(theAggTuple))
{
elog(WARN, "aggregate %s does not exist", aggname);
}
aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
fintype = aggform->aggfinaltype;
xfn1 = aggform->aggtransfn1;
if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
/* only aggregates with transfn1 need a base type */
if (OidIsValid(xfn1))
{
basetype = aggform->aggbasetype;
if (nodeTag(target) == T_Var)
vartype = ((Var *) target)->vartype;
else
vartype = ((Expr *) target)->typeOid;
if (basetype != vartype)
{
Type tp1,
tp2;
tp1 = typeidType(basetype);
tp2 = typeidType(vartype);
elog(NOTICE, "Aggregate type mismatch:");
elog(WARN, "%s works on %s, not %s", aggname,
typeTypeName(tp1), typeTypeName(tp2));
}
}
aggreg = makeNode(Aggreg);
aggreg->aggname = pstrdup(aggname);
aggreg->basetype = aggform->aggbasetype;
aggreg->aggtype = fintype;
aggreg->target = target;
return aggreg;
}
/*
* Error message when aggregate lookup fails that gives details of the
* basetype
*/
void
agg_error(char *caller, char *aggname, Oid basetypeID)
{
/*
* basetypeID that is Invalid (zero) means aggregate over all types.
* (count)
*/
if (basetypeID == InvalidOid)
{
elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
}
else
{
elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
typeidTypeName(basetypeID));
}
}

View File

@ -0,0 +1,407 @@
/*-------------------------------------------------------------------------
*
* parse_clause.c--
* handle clauses in parser
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.1 1997/11/25 22:05:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "postgres.h"
#include "access/heapam.h"
#include "parser/parse_clause.h"
#include "parser/parse_expr.h"
#include "parser/parse_node.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "catalog/pg_type.h"
#ifdef 0
#include "nodes/nodes.h"
#include "nodes/params.h"
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "nodes/relation.h"
#include "parse.h" /* for AND, OR, etc. */
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "utils/elog.h"
#include "utils/builtins.h" /* namecmp(), textout() */
#include "utils/lsyscache.h"
#include "utils/palloc.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
#include "utils/acl.h"
#include "nodes/makefuncs.h" /* for makeResdom(), etc. */
#include "nodes/nodeFuncs.h"
#include "commands/sequence.h"
#include "optimizer/clauses.h"
#include "miscadmin.h"
#include "port-protos.h" /* strdup() */
#endif
/*
* parseFromClause -
* turns the table references specified in the from-clause into a
* range table. The range table may grow as we transform the expressions
* in the target list. (Note that this happens because in POSTQUEL, we
* allow references to relations not specified in the from-clause. We
* also allow that in our POST-SQL)
*
*/
void
parseFromClause(ParseState *pstate, List *frmList)
{
List *fl;
foreach(fl, frmList)
{
RangeVar *r = lfirst(fl);
RelExpr *baserel = r->relExpr;
char *relname = baserel->relname;
char *refname = r->name;
RangeTblEntry *rte;
if (refname == NULL)
refname = relname;
/*
* marks this entry to indicate it comes from the FROM clause. In
* SQL, the target list can only refer to range variables
* specified in the from clause but we follow the more powerful
* POSTQUEL semantics and automatically generate the range
* variable if not specified. However there are times we need to
* know whether the entries are legitimate.
*
* eg. select * from foo f where f.x = 1; will generate wrong answer
* if we expand * to foo.x.
*/
rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE);
}
}
/*
* makeRangeTable -
* make a range table with the specified relation (optional) and the
* from-clause.
*/
void
makeRangeTable(ParseState *pstate, char *relname, List *frmList)
{
RangeTblEntry *rte;
parseFromClause(pstate, frmList);
if (relname == NULL)
return;
if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE);
else
rte = refnameRangeTableEntry(pstate->p_rtable, relname);
pstate->p_target_rangetblentry = rte;
Assert(pstate->p_target_relation == NULL);
pstate->p_target_relation = heap_open(rte->relid);
Assert(pstate->p_target_relation != NULL);
/* will close relation later */
}
/*****************************************************************************
*
* Where Clause
*
*****************************************************************************/
/*
* transformWhereClause -
* transforms the qualification and make sure it is of type Boolean
*
*/
Node *
transformWhereClause(ParseState *pstate, Node *a_expr)
{
Node *qual;
if (a_expr == NULL)
return (Node *) NULL; /* no qualifiers */
pstate->p_in_where_clause = true;
qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
pstate->p_in_where_clause = false;
if (exprType(qual) != BOOLOID)
{
elog(WARN,
"where clause must return type bool, not %s",
typeidTypeName(exprType(qual)));
}
return qual;
}
/*****************************************************************************
*
* Sort Clause
*
*****************************************************************************/
/*
* find_targetlist_entry -
* returns the Resdom in the target list matching the specified varname
* and range
*
*/
TargetEntry *
find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
{
List *i;
int real_rtable_pos = 0,
target_pos = 0;
TargetEntry *target_result = NULL;
if (sortgroupby->range)
real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
sortgroupby->range);
foreach(i, tlist)
{
TargetEntry *target = (TargetEntry *) lfirst(i);
Resdom *resnode = target->resdom;
Var *var = (Var *) target->expr;
char *resname = resnode->resname;
int test_rtable_pos = var->varno;
#ifdef PARSEDEBUG
printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
(sortgroupby->name ? sortgroupby->name : "(null)"), target_pos + 1, sortgroupby->resno);
#endif
if (!sortgroupby->name)
{
if (sortgroupby->resno == ++target_pos)
{
target_result = target;
break;
}
}
else
{
if (!strcmp(resname, sortgroupby->name))
{
if (sortgroupby->range)
{
if (real_rtable_pos == test_rtable_pos)
{
if (target_result != NULL)
elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
else
target_result = target;
}
}
else
{
if (target_result != NULL)
elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
else
target_result = target;
}
}
}
}
return target_result;
}
/*
* transformGroupClause -
* transform a Group By clause
*
*/
List *
transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
{
List *glist = NIL,
*gl = NIL;
while (grouplist != NIL)
{
GroupClause *grpcl = makeNode(GroupClause);
TargetEntry *restarget;
Resdom *resdom;
restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
if (restarget == NULL)
elog(WARN, "The field being grouped by must appear in the target list");
grpcl->entry = restarget;
resdom = restarget->resdom;
grpcl->grpOpoid = oprid(oper("<",
resdom->restype,
resdom->restype, false));
if (glist == NIL)
gl = glist = lcons(grpcl, NIL);
else
{
List *i;
foreach (i, glist)
{
GroupClause *gcl = (GroupClause *) lfirst (i);
if ( gcl->entry == grpcl->entry )
break;
}
if ( i == NIL ) /* not in grouplist already */
{
lnext(gl) = lcons(grpcl, NIL);
gl = lnext(gl);
}
else
pfree (grpcl); /* get rid of this */
}
grouplist = lnext(grouplist);
}
return glist;
}
/*
* transformSortClause -
* transform an Order By clause
*
*/
List *
transformSortClause(ParseState *pstate,
List *orderlist, List *targetlist,
char *uniqueFlag)
{
List *sortlist = NIL;
List *s = NIL;
while (orderlist != NIL)
{
SortGroupBy *sortby = lfirst(orderlist);
SortClause *sortcl = makeNode(SortClause);
TargetEntry *restarget;
Resdom *resdom;
restarget = find_targetlist_entry(pstate, sortby, targetlist);
if (restarget == NULL)
elog(WARN, "The field being ordered by must appear in the target list");
sortcl->resdom = resdom = restarget->resdom;
sortcl->opoid = oprid(oper(sortby->useOp,
resdom->restype,
resdom->restype, false));
if (sortlist == NIL)
{
s = sortlist = lcons(sortcl, NIL);
}
else
{
List *i;
foreach (i, sortlist)
{
SortClause *scl = (SortClause *) lfirst (i);
if ( scl->resdom == sortcl->resdom )
break;
}
if ( i == NIL ) /* not in sortlist already */
{
lnext(s) = lcons(sortcl, NIL);
s = lnext(s);
}
else
pfree (sortcl); /* get rid of this */
}
orderlist = lnext(orderlist);
}
if (uniqueFlag)
{
List *i;
if (uniqueFlag[0] == '*')
{
/*
* concatenate all elements from target list that are not
* already in the sortby list
*/
foreach(i, targetlist)
{
TargetEntry *tlelt = (TargetEntry *) lfirst(i);
s = sortlist;
while (s != NIL)
{
SortClause *sortcl = lfirst(s);
if (sortcl->resdom == tlelt->resdom)
break;
s = lnext(s);
}
if (s == NIL)
{
/* not a member of the sortclauses yet */
SortClause *sortcl = makeNode(SortClause);
sortcl->resdom = tlelt->resdom;
sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
sortlist = lappend(sortlist, sortcl);
}
}
}
else
{
TargetEntry *tlelt = NULL;
char *uniqueAttrName = uniqueFlag;
/* only create sort clause with the specified unique attribute */
foreach(i, targetlist)
{
tlelt = (TargetEntry *) lfirst(i);
if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
break;
}
if (i == NIL)
{
elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
}
s = sortlist;
foreach(s, sortlist)
{
SortClause *sortcl = lfirst(s);
if (sortcl->resdom == tlelt->resdom)
break;
}
if (s == NIL)
{
/* not a member of the sortclauses yet */
SortClause *sortcl = makeNode(SortClause);
sortcl->resdom = tlelt->resdom;
sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
sortlist = lappend(sortlist, sortcl);
}
}
}
return sortlist;
}

View File

@ -0,0 +1,694 @@
/*-------------------------------------------------------------------------
*
* parse_expr.c
* handle expressions in parser
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.1 1997/11/25 22:05:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "postgres.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodes.h"
#include "nodes/params.h"
#include "nodes/relation.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parse.h"
#include "utils/builtins.h"
#ifdef 0
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "utils/elog.h"
#include "utils/lsyscache.h"
#include "utils/palloc.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
#include "utils/acl.h"
#include "nodes/nodeFuncs.h"
#include "commands/sequence.h"
#include "optimizer/clauses.h"
#include "access/heapam.h"
#include "miscadmin.h"
#endif
Oid param_type(int t); /* from gram.y */
/*
* transformExpr -
* analyze and transform expressions. Type checking and type casting is
* done here. The optimizer and the executor cannot handle the original
* (raw) expressions collected by the parse tree. Hence the transformation
* here.
*/
Node *
transformExpr(ParseState *pstate, Node *expr, int precedence)
{
Node *result = NULL;
if (expr == NULL)
return NULL;
switch (nodeTag(expr))
{
case T_Attr:
{
Attr *att = (Attr *) expr;
Node *temp;
/* what if att.attrs == "*"?? */
temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
if (att->indirection != NIL)
{
List *idx = att->indirection;
while (idx != NIL)
{
A_Indices *ai = (A_Indices *) lfirst(idx);
Node *lexpr = NULL,
*uexpr;
uexpr = transformExpr(pstate, ai->uidx, precedence); /* must exists */
if (exprType(uexpr) != INT4OID)
elog(WARN, "array index expressions must be int4's");
if (ai->lidx != NULL)
{
lexpr = transformExpr(pstate, ai->lidx, precedence);
if (exprType(lexpr) != INT4OID)
elog(WARN, "array index expressions must be int4's");
}
#if 0
pfree(ai->uidx);
if (ai->lidx != NULL)
pfree(ai->lidx);
#endif
ai->lidx = lexpr;
ai->uidx = uexpr;
/*
* note we reuse the list of indices, make sure we
* don't free them! Otherwise, make a new list
* here
*/
idx = lnext(idx);
}
result = (Node *) make_array_ref(temp, att->indirection);
}
else
{
result = temp;
}
break;
}
case T_A_Const:
{
A_Const *con = (A_Const *) expr;
Value *val = &con->val;
if (con->typename != NULL)
{
result = parser_typecast(val, con->typename, -1);
}
else
{
result = (Node *) make_const(val);
}
break;
}
case T_ParamNo:
{
ParamNo *pno = (ParamNo *) expr;
Oid toid;
int paramno;
Param *param;
paramno = pno->number;
toid = param_type(paramno);
if (!OidIsValid(toid))
{
elog(WARN, "Parameter '$%d' is out of range",
paramno);
}
param = makeNode(Param);
param->paramkind = PARAM_NUM;
param->paramid = (AttrNumber) paramno;
param->paramname = "<unnamed>";
param->paramtype = (Oid) toid;
param->param_tlist = (List *) NULL;
result = (Node *) param;
break;
}
case T_A_Expr:
{
A_Expr *a = (A_Expr *) expr;
switch (a->oper)
{
case OP:
{
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
result = (Node *) make_op(a->opname, lexpr, rexpr);
}
break;
case ISNULL:
{
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
result = ParseFunc(pstate,
"nullvalue", lcons(lexpr, NIL),
&pstate->p_last_resno);
}
break;
case NOTNULL:
{
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
result = ParseFunc(pstate,
"nonnullvalue", lcons(lexpr, NIL),
&pstate->p_last_resno);
}
break;
case AND:
{
Expr *expr = makeNode(Expr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(lexpr) != BOOLOID)
elog(WARN,
"left-hand side of AND is type '%s', not bool",
typeidTypeName(exprType(lexpr)));
if (exprType(rexpr) != BOOLOID)
elog(WARN,
"right-hand side of AND is type '%s', not bool",
typeidTypeName(exprType(rexpr)));
expr->typeOid = BOOLOID;
expr->opType = AND_EXPR;
expr->args = makeList(lexpr, rexpr, -1);
result = (Node *) expr;
}
break;
case OR:
{
Expr *expr = makeNode(Expr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(lexpr) != BOOLOID)
elog(WARN,
"left-hand side of OR is type '%s', not bool",
typeidTypeName(exprType(lexpr)));
if (exprType(rexpr) != BOOLOID)
elog(WARN,
"right-hand side of OR is type '%s', not bool",
typeidTypeName(exprType(rexpr)));
expr->typeOid = BOOLOID;
expr->opType = OR_EXPR;
expr->args = makeList(lexpr, rexpr, -1);
result = (Node *) expr;
}
break;
case NOT:
{
Expr *expr = makeNode(Expr);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(rexpr) != BOOLOID)
elog(WARN,
"argument to NOT is type '%s', not bool",
typeidTypeName(exprType(rexpr)));
expr->typeOid = BOOLOID;
expr->opType = NOT_EXPR;
expr->args = makeList(rexpr, -1);
result = (Node *) expr;
}
break;
}
break;
}
case T_Ident:
{
/*
* look for a column name or a relation name (the default
* behavior)
*/
result = transformIdent(pstate, expr, precedence);
break;
}
case T_FuncCall:
{
FuncCall *fn = (FuncCall *) expr;
List *args;
/* transform the list of arguments */
foreach(args, fn->args)
lfirst(args) = transformExpr(pstate, (Node *) lfirst(args), precedence);
result = ParseFunc(pstate,
fn->funcname, fn->args, &pstate->p_last_resno);
break;
}
default:
/* should not reach here */
elog(WARN, "transformExpr: does not know how to transform %d\n",
nodeTag(expr));
break;
}
return result;
}
Node *
transformIdent(ParseState *pstate, Node *expr, int precedence)
{
Ident *ident = (Ident *) expr;
RangeTblEntry *rte;
Node *column_result,
*relation_result,
*result;
column_result = relation_result = result = 0;
/* try to find the ident as a column */
if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
{
Attr *att = makeNode(Attr);
att->relname = rte->refname;
att->attrs = lcons(makeString(ident->name), NIL);
column_result =
(Node *) handleNestedDots(pstate, att, &pstate->p_last_resno);
}
/* try to find the ident as a relation */
if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL)
{
ident->isRel = TRUE;
relation_result = (Node *) ident;
}
/* choose the right result based on the precedence */
if (precedence == EXPR_COLUMN_FIRST)
{
if (column_result)
result = column_result;
else
result = relation_result;
}
else
{
if (relation_result)
result = relation_result;
else
result = column_result;
}
if (result == NULL)
elog(WARN, "attribute '%s' not found", ident->name);
return result;
}
/*
* exprType -
* returns the Oid of the type of the expression. (Used for typechecking.)
*/
Oid
exprType(Node *expr)
{
Oid type = (Oid) 0;
switch (nodeTag(expr))
{
case T_Func:
type = ((Func *) expr)->functype;
break;
case T_Iter:
type = ((Iter *) expr)->itertype;
break;
case T_Var:
type = ((Var *) expr)->vartype;
break;
case T_Expr:
type = ((Expr *) expr)->typeOid;
break;
case T_Const:
type = ((Const *) expr)->consttype;
break;
case T_ArrayRef:
type = ((ArrayRef *) expr)->refelemtype;
break;
case T_Aggreg:
type = ((Aggreg *) expr)->aggtype;
break;
case T_Param:
type = ((Param *) expr)->paramtype;
break;
case T_Ident:
/* is this right? */
type = UNKNOWNOID;
break;
default:
elog(WARN, "exprType: don't know how to get type for %d node",
nodeTag(expr));
break;
}
return type;
}
/*
** HandleNestedDots --
** Given a nested dot expression (i.e. (relation func ... attr), build up
** a tree with of Iter and Func nodes.
*/
Node *
handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
{
List *mutator_iter;
Node *retval = NULL;
if (attr->paramNo != NULL)
{
Param *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
retval =
ParseFunc(pstate, strVal(lfirst(attr->attrs)),
lcons(param, NIL),
curr_resno);
}
else
{
Ident *ident = makeNode(Ident);
ident->name = attr->relname;
ident->isRel = TRUE;
retval =
ParseFunc(pstate, strVal(lfirst(attr->attrs)),
lcons(ident, NIL),
curr_resno);
}
foreach(mutator_iter, lnext(attr->attrs))
{
retval = ParseFunc(pstate, strVal(lfirst(mutator_iter)),
lcons(retval, NIL),
curr_resno);
}
return (retval);
}
Node *
parser_typecast(Value *expr, TypeName *typename, int typlen)
{
/* check for passing non-ints */
Const *adt;
Datum lcp;
Type tp;
char type_string[NAMEDATALEN];
int32 len;
char *cp = NULL;
char *const_string = NULL;
bool string_palloced = false;
switch (nodeTag(expr))
{
case T_String:
const_string = DatumGetPointer(expr->val.str);
break;
case T_Integer:
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%ld", expr->val.ival);
break;
default:
elog(WARN,
"parser_typecast: cannot cast this expression to type \"%s\"",
typename->name);
}
if (typename->arrayBounds != NIL)
{
sprintf(type_string, "_%s", typename->name);
tp = (Type) typenameType(type_string);
}
else
{
tp = (Type) typenameType(typename->name);
}
len = typeLen(tp);
#if 0 /* fix me */
switch (CInteger(lfirst(expr)))
{
case INT4OID: /* int4 */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
break;
case NAMEOID: /* char16 */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
break;
case CHAROID: /* char */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
break;
case FLOAT8OID: /* float8 */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
break;
case CASHOID: /* money */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%d",
(int) ((Const *) expr)->constvalue);
break;
case TEXTOID: /* text */
const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
const_string = (char *) textout((struct varlena *) const_string);
break;
case UNKNOWNOID: /* unknown */
const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
const_string = (char *) textout((struct varlena *) const_string);
break;
default:
elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
}
#endif
cp = stringTypeString(tp, const_string, typlen);
if (!typeByVal(tp))
{
/*
if (len >= 0 && len != PSIZE(cp)) {
char *pp;
pp = (char *) palloc(len);
memmove(pp, cp, len);
cp = pp;
}
*/
lcp = PointerGetDatum(cp);
}
else
{
switch (len)
{
case 1:
lcp = Int8GetDatum(cp);
break;
case 2:
lcp = Int16GetDatum(cp);
break;
case 4:
lcp = Int32GetDatum(cp);
break;
default:
lcp = PointerGetDatum(cp);
break;
}
}
adt = makeConst(typeTypeId(tp),
len,
(Datum) lcp,
false,
typeByVal(tp),
false, /* not a set */
true /* is cast */ );
if (string_palloced)
pfree(const_string);
return (Node *) adt;
}
Node *
parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
{
/* check for passing non-ints */
Const *adt;
Datum lcp;
int32 len = typeLen(tp);
char *cp = NULL;
char *const_string = NULL;
bool string_palloced = false;
Assert(IsA(expr, Const));
switch (exprType)
{
case 0: /* NULL */
break;
case INT4OID: /* int4 */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%d",
(int) ((Const *) expr)->constvalue);
break;
case NAMEOID: /* char16 */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%s",
(char *) ((Const *) expr)->constvalue);
break;
case CHAROID: /* char */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%c",
(char) ((Const *) expr)->constvalue);
break;
case FLOAT4OID: /* float4 */
{
float32 floatVal =
DatumGetFloat32(((Const *) expr)->constvalue);
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%f", *floatVal);
break;
}
case FLOAT8OID: /* float8 */
{
float64 floatVal =
DatumGetFloat64(((Const *) expr)->constvalue);
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%f", *floatVal);
break;
}
case CASHOID: /* money */
const_string = (char *) palloc(256);
string_palloced = true;
sprintf(const_string, "%ld",
(long) ((Const *) expr)->constvalue);
break;
case TEXTOID: /* text */
const_string =
DatumGetPointer(((Const *) expr)->constvalue);
const_string = (char *) textout((struct varlena *) const_string);
break;
case UNKNOWNOID: /* unknown */
const_string =
DatumGetPointer(((Const *) expr)->constvalue);
const_string = (char *) textout((struct varlena *) const_string);
break;
default:
elog(WARN, "unknown type %u ", exprType);
}
if (!exprType)
{
adt = makeConst(typeTypeId(tp),
(Size) 0,
(Datum) NULL,
true, /* isnull */
false, /* was omitted */
false, /* not a set */
true /* is cast */ );
return ((Node *) adt);
}
cp = stringTypeString(tp, const_string, typlen);
if (!typeByVal(tp))
{
/*
if (len >= 0 && len != PSIZE(cp)) {
char *pp;
pp = (char *) palloc(len);
memmove(pp, cp, len);
cp = pp;
}
*/
lcp = PointerGetDatum(cp);
}
else
{
switch (len)
{
case 1:
lcp = Int8GetDatum(cp);
break;
case 2:
lcp = Int16GetDatum(cp);
break;
case 4:
lcp = Int32GetDatum(cp);
break;
default:
lcp = PointerGetDatum(cp);
break;
}
}
adt = makeConst(typeTypeId(tp),
(Size) len,
(Datum) lcp,
false,
false, /* was omitted */
false, /* not a set */
true /* is cast */ );
/*
* printf("adt %s : %u %d %d\n",CString(expr),typeTypeId(tp) , len,cp);
*/
if (string_palloced)
pfree(const_string);
return ((Node *) adt);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,259 +1,76 @@
/*-------------------------------------------------------------------------
*
* parse_query.c--
* take an "optimizable" stmt and make the query tree that
* the planner requires.
* parse_node.c--
* various routines that make nodes for query plans
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.25 1997/11/24 05:08:27 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.1 1997/11/25 22:05:42 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include <string.h>
#include "postgres.h"
#include "postgres.h"
#include "fmgr.h"
#include "access/heapam.h"
#include "access/tupmacs.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "parser/parse_expr.h"
#include "parser/parse_oper.h"
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
#ifdef 0
#include "access/tupmacs.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "utils/acl.h" /* for ACL_NO_PRIV_WARNING */
#include "utils/rel.h" /* Relation stuff */
#include "utils/syscache.h"
#include "catalog/pg_type.h"
#include "catalog/pg_operator.h"
#include "parser/catalog_utils.h"
#include "parser/parse_query.h"
#include "utils/lsyscache.h"
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "nodes/makefuncs.h"
static void
checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname);
Oid *param_type_info;
int pfunc_num_args;
/* given refname, return a pointer to the range table entry */
RangeTblEntry *
refnameRangeTableEntry(List *rtable, char *refname)
{
List *temp;
foreach(temp, rtable)
{
RangeTblEntry *rte = lfirst(temp);
if (!strcmp(rte->refname, refname))
return rte;
}
return NULL;
}
/* given refname, return id of variable; position starts with 1 */
int
refnameRangeTablePosn(List *rtable, char *refname)
{
int index;
List *temp;
index = 1;
foreach(temp, rtable)
{
RangeTblEntry *rte = lfirst(temp);
if (!strcmp(rte->refname, refname))
return index;
index++;
}
return (0);
}
#endif
/*
* returns range entry if found, else NULL
* make_parsestate() --
* allocate and initialize a new ParseState.
* the CALLERS is responsible for freeing the ParseState* returned
*
*/
RangeTblEntry *
colnameRangeTableEntry(ParseState *pstate, char *colname)
ParseState *
make_parsestate(void)
{
List *et;
List *rtable;
RangeTblEntry *rte_result;
ParseState *pstate;
if (pstate->p_is_rule)
rtable = lnext(lnext(pstate->p_rtable));
else
rtable = pstate->p_rtable;
pstate = malloc(sizeof(ParseState));
pstate->p_last_resno = 1;
pstate->p_rtable = NIL;
pstate->p_numAgg = 0;
pstate->p_aggs = NIL;
pstate->p_is_insert = false;
pstate->p_insert_columns = NIL;
pstate->p_is_update = false;
pstate->p_is_rule = false;
pstate->p_in_where_clause = false;
pstate->p_target_relation = NULL;
pstate->p_target_rangetblentry = NULL;
rte_result = NULL;
foreach(et, rtable)
{
RangeTblEntry *rte = lfirst(et);
/* only entries on outer(non-function?) scope */
if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
continue;
if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
{
if (rte_result != NULL)
{
if (!pstate->p_is_insert ||
rte != pstate->p_target_rangetblentry)
elog(WARN, "Column %s is ambiguous", colname);
}
else
rte_result = rte;
}
}
return rte_result;
return (pstate);
}
/*
* put new entry in pstate p_rtable structure, or return pointer
* if pstate null
*/
RangeTblEntry *
addRangeTableEntry(ParseState *pstate,
char *relname,
char *refname,
bool inh,
bool inFromCl)
{
Relation relation;
RangeTblEntry *rte = makeNode(RangeTblEntry);
if (pstate != NULL &&
refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
elog(WARN, "Table name %s specified more than once", refname);
rte->relname = pstrdup(relname);
rte->refname = pstrdup(refname);
relation = heap_openr(relname);
if (relation == NULL)
{
elog(WARN, "%s: %s",
relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
}
/*
* Flags - zero or more from inheritance,union,version or
* recursive (transitive closure) [we don't support them all -- ay
* 9/94 ]
*/
rte->inh = inh;
/* RelOID */
rte->relid = RelationGetRelationId(relation);
rte->inFromCl = inFromCl;
/*
* close the relation we're done with it for now.
*/
if (pstate != NULL)
pstate->p_rtable = lappend(pstate->p_rtable, rte);
heap_close(relation);
return rte;
}
/*
* expandAll -
* makes a list of attributes
* assumes reldesc caching works
*/
List *
expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
{
Relation rdesc;
List *te_tail = NIL,
*te_head = NIL;
Var *varnode;
int varattno,
maxattrs;
Oid type_id;
int type_len;
RangeTblEntry *rte;
rte = refnameRangeTableEntry(pstate->p_rtable, refname);
if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
rdesc = heap_open(rte->relid);
if (rdesc == NULL)
{
elog(WARN, "Unable to expand all -- heap_open failed on %s",
rte->refname);
return NIL;
}
maxattrs = RelationGetNumberOfAttributes(rdesc);
for (varattno = 0; varattno <= maxattrs - 1; varattno++)
{
char *attrname;
char *resname = NULL;
TargetEntry *te = makeNode(TargetEntry);
attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
type_len = (int) tlen(get_id_type(type_id));
handleTargetColname(pstate, &resname, refname, attrname);
if (resname != NULL)
attrname = resname;
/*
* Even if the elements making up a set are complex, the set
* itself is not.
*/
te->resdom = makeResdom((AttrNumber) (*this_resno)++,
type_id,
(Size) type_len,
attrname,
(Index) 0,
(Oid) 0,
0);
te->expr = (Node *) varnode;
if (te_head == NIL)
te_head = te_tail = lcons(te, NIL);
else
te_tail = lappend(te_tail, te);
}
heap_close(rdesc);
return (te_head);
}
static void
disallow_setop(char *op, Type optype, Node *operand)
{
if (operand == NULL)
return;
if (nodeTag(operand) == T_Iter)
{
elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
op, tname(optype));
elog(WARN, "but '%s' takes single values, not sets.",
op);
}
}
static Node *
Node *
make_operand(char *opname,
Node *tree,
Oid orig_typeId,
@ -267,7 +84,7 @@ make_operand(char *opname,
if (tree != NULL)
{
result = tree;
true_type = get_id_type(true_typeId);
true_type = typeidType(true_typeId);
disallow_setop(opname, true_type, result);
if (true_typeId != orig_typeId)
{ /* must coerce */
@ -276,13 +93,13 @@ make_operand(char *opname,
Assert(nodeTag(result) == T_Const);
val = (Datum) textout((struct varlena *)
con->constvalue);
infunc = typeid_get_retinfunc(true_typeId);
infunc = typeidRetinfunc(true_typeId);
con = makeNode(Const);
con->consttype = true_typeId;
con->constlen = tlen(true_type);
con->constlen = typeLen(true_type);
con->constvalue = (Datum) fmgr(infunc,
val,
get_typelem(true_typeId),
typeidTypElem(true_typeId),
-1 /* for varchar() type */ );
con->constisnull = false;
con->constbyval = true;
@ -307,6 +124,21 @@ make_operand(char *opname,
}
void
disallow_setop(char *op, Type optype, Node *operand)
{
if (operand == NULL)
return;
if (nodeTag(operand) == T_Iter)
{
elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
op, typeTypeName(optype));
elog(WARN, "but '%s' takes single values, not sets.",
op);
}
}
Expr *
make_op(char *opname, Node *ltree, Node *rtree)
{
@ -367,30 +199,30 @@ make_op(char *opname, Node *ltree, Node *rtree)
CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
!((Const *) rtree)->constiscast)
{
outfunc = typeid_get_retoutfunc(rtypeId);
infunc = typeid_get_retinfunc(ltypeId);
outfunc = typeidRetoutfunc(rtypeId);
infunc = typeidRetinfunc(ltypeId);
outstr = (char *) fmgr(outfunc, ((Const *) rtree)->constvalue);
((Const *) rtree)->constvalue = (Datum) fmgr(infunc, outstr);
pfree(outstr);
((Const *) rtree)->consttype = rtypeId = ltypeId;
newtype = get_id_type(rtypeId);
((Const *) rtree)->constlen = tlen(newtype);
((Const *) rtree)->constbyval = tbyval(newtype);
newtype = typeidType(rtypeId);
((Const *) rtree)->constlen = typeLen(newtype);
((Const *) rtree)->constbyval = typeByVal(newtype);
}
if (CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) != T_Const &&
CONVERTABLE_TYPE(ltypeId) && nodeTag(ltree) == T_Const &&
!((Const *) ltree)->constiscast)
{
outfunc = typeid_get_retoutfunc(ltypeId);
infunc = typeid_get_retinfunc(rtypeId);
outfunc = typeidRetoutfunc(ltypeId);
infunc = typeidRetinfunc(rtypeId);
outstr = (char *) fmgr(outfunc, ((Const *) ltree)->constvalue);
((Const *) ltree)->constvalue = (Datum) fmgr(infunc, outstr);
pfree(outstr);
((Const *) ltree)->consttype = ltypeId = rtypeId;
newtype = get_id_type(ltypeId);
((Const *) ltree)->constlen = tlen(newtype);
((Const *) ltree)->constbyval = tbyval(newtype);
newtype = typeidType(ltypeId);
((Const *) ltree)->constlen = typeLen(newtype);
((Const *) ltree)->constbyval = typeByVal(newtype);
}
temp = oper(opname, ltypeId, rtypeId, false);
@ -426,38 +258,6 @@ make_op(char *opname, Node *ltree, Node *rtree)
return result;
}
Oid
find_atttype(Oid relid, char *attrname)
{
int attid;
Oid vartype;
Relation rd;
rd = heap_open(relid);
if (!RelationIsValid(rd))
{
rd = heap_openr(tname(get_id_type(relid)));
if (!RelationIsValid(rd))
elog(WARN, "cannot compute type of att %s for relid %d",
attrname, relid);
}
attid = nf_varattno(rd, attrname);
if (attid == InvalidAttrNumber)
elog(WARN, "Invalid attribute %s\n", attrname);
vartype = att_typeid(rd, attid);
/*
* close relation we're done with it now
*/
heap_close(rd);
return (vartype);
}
Var *
make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
{
@ -476,10 +276,8 @@ make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
rd = heap_open(rte->relid);
attid = nf_varattno(rd, attrname);
if (attid == InvalidAttrNumber)
elog(WARN, "Invalid attribute %s\n", attrname);
vartypeid = att_typeid(rd, attid);
attid = attnameAttNum(rd, attrname); /* could elog(WARN) */
vartypeid = attnumTypeId(rd, attid);
varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
@ -667,7 +465,7 @@ make_const(Value *value)
switch (nodeTag(value))
{
case T_Integer:
tp = type("int4");
tp = typeidType(INT4OID);
val = Int32GetDatum(intVal(value));
break;
@ -675,7 +473,7 @@ make_const(Value *value)
{
float64 dummy;
tp = type("float8");
tp = typeidType(FLOAT8OID);
dummy = (float64) palloc(sizeof(float64data));
*dummy = floatVal(value);
@ -685,7 +483,7 @@ make_const(Value *value)
break;
case T_String:
tp = type("unknown"); /* unknown for now, will be type
tp = typeidType(UNKNOWNOID); /* unknown for now, will be type
* coerced */
val = PointerGetDatum(textin(strVal(value)));
break;
@ -702,111 +500,14 @@ make_const(Value *value)
}
}
con = makeConst(typeid(tp),
tlen(tp),
con = makeConst(typeTypeId(tp),
typeLen(tp),
val,
false,
tbyval(tp),
typeByVal(tp),
false, /* not a set */
false);
return (con);
}
/*
* param_type_init()
*
* keep enough information around fill out the type of param nodes
* used in postquel functions
*/
void
param_type_init(Oid *typev, int nargs)
{
pfunc_num_args = nargs;
param_type_info = typev;
}
Oid
param_type(int t)
{
if ((t > pfunc_num_args) || (t == 0))
return InvalidOid;
return param_type_info[t - 1];
}
/*
* handleTargetColname -
* use column names from insert
*/
void
handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname)
{
if (pstate->p_is_insert)
{
if (pstate->p_insert_columns != NIL)
{
Ident *id = lfirst(pstate->p_insert_columns);
*resname = id->name;
pstate->p_insert_columns = lnext(pstate->p_insert_columns);
}
else
elog(WARN, "insert: more expressions than target columns");
}
if (pstate->p_is_insert || pstate->p_is_update)
checkTargetTypes(pstate, *resname, refname, colname);
}
/*
* checkTargetTypes -
* checks value and target column types
*/
static void
checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname)
{
Oid attrtype_id,
attrtype_target;
int resdomno_id,
resdomno_target;
Relation rd;
RangeTblEntry *rte;
if (target_colname == NULL || colname == NULL)
return;
if (refname != NULL)
rte = refnameRangeTableEntry(pstate->p_rtable, refname);
else
{
rte = colnameRangeTableEntry(pstate, colname);
if (rte == (RangeTblEntry *) NULL)
elog(WARN, "attribute %s not found", colname);
refname = rte->refname;
}
/*
if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
elog(WARN, "%s not available in this context", colname);
*/
rd = heap_open(rte->relid);
resdomno_id = varattno(rd, colname);
attrtype_id = att_typeid(rd, resdomno_id);
resdomno_target = varattno(pstate->p_target_relation, target_colname);
attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
if (attrtype_id != attrtype_target)
elog(WARN, "Type of %s does not match target column %s",
colname, target_colname);
if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
rd->rd_att->attrs[resdomno_id - 1]->attlen !=
pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
elog(WARN, "Length of %s does not match length of target column %s",
colname, target_colname);
heap_close(rd);
}

View File

@ -0,0 +1,613 @@
/*-------------------------------------------------------------------------
*
* parse_oper.h
* handle operator things for parser
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.1 1997/11/25 22:05:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include "postgres.h"
#include <fmgr.h>
#include <access/heapam.h>
#include <access/relscan.h>
#include <catalog/catname.h>
#include <catalog/pg_operator.h>
#include <catalog/pg_proc.h>
#include <catalog/pg_type.h>
#include <parser/parse_oper.h>
#include <parser/parse_type.h>
#include <storage/bufmgr.h>
#include <utils/syscache.h>
#ifdef 0
#include "lib/dllist.h"
#include "utils/datum.h"
#include "utils/builtins.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/indexing.h"
#include "catalog/catname.h"
#include "access/skey.h"
#include "access/relscan.h"
#include "access/tupdesc.h"
#include "access/htup.h"
#include "access/genam.h"
#include "access/itup.h"
#include "access/tupmacs.h"
#include "storage/buf.h"
#include "utils/lsyscache.h"
#include "storage/lmgr.h"
#include "port-protos.h" /* strdup() */
#endif
Oid
any_ordering_op(int restype)
{
Operator order_op;
Oid order_opid;
order_op = oper("<", restype, restype, false);
order_opid = oprid(order_op);
return order_opid;
}
/* given operator, return the operator OID */
Oid
oprid(Operator op)
{
return (op->t_oid);
}
/*
* given opname, leftTypeId and rightTypeId,
* find all possible (arg1, arg2) pairs for which an operator named
* opname exists, such that leftTypeId can be coerced to arg1 and
* rightTypeId can be coerced to arg2
*/
int
binary_oper_get_candidates(char *opname,
Oid leftTypeId,
Oid rightTypeId,
CandidateList *candidates)
{
CandidateList current_candidate;
Relation pg_operator_desc;
HeapScanDesc pg_operator_scan;
HeapTuple tup;
OperatorTupleForm oper;
Buffer buffer;
int nkeys;
int ncandidates = 0;
ScanKeyData opKey[3];
*candidates = NULL;
ScanKeyEntryInitialize(&opKey[0], 0,
Anum_pg_operator_oprname,
NameEqualRegProcedure,
NameGetDatum(opname));
ScanKeyEntryInitialize(&opKey[1], 0,
Anum_pg_operator_oprkind,
CharacterEqualRegProcedure,
CharGetDatum('b'));
if (leftTypeId == UNKNOWNOID)
{
if (rightTypeId == UNKNOWNOID)
{
nkeys = 2;
}
else
{
nkeys = 3;
ScanKeyEntryInitialize(&opKey[2], 0,
Anum_pg_operator_oprright,
ObjectIdEqualRegProcedure,
ObjectIdGetDatum(rightTypeId));
}
}
else if (rightTypeId == UNKNOWNOID)
{
nkeys = 3;
ScanKeyEntryInitialize(&opKey[2], 0,
Anum_pg_operator_oprleft,
ObjectIdEqualRegProcedure,
ObjectIdGetDatum(leftTypeId));
}
else
/* currently only "unknown" can be coerced */
return 0;
pg_operator_desc = heap_openr(OperatorRelationName);
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
true,
nkeys,
opKey);
do
{
tup = heap_getnext(pg_operator_scan, 0, &buffer);
if (HeapTupleIsValid(tup))
{
current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
oper = (OperatorTupleForm) GETSTRUCT(tup);
current_candidate->args[0] = oper->oprleft;
current_candidate->args[1] = oper->oprright;
current_candidate->next = *candidates;
*candidates = current_candidate;
ncandidates++;
ReleaseBuffer(buffer);
}
} while (HeapTupleIsValid(tup));
heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc);
return ncandidates;
}
/*
* equivalentOpersAfterPromotion -
* checks if a list of candidate operators obtained from
* binary_oper_get_candidates() contain equivalent operators. If
* this routine is called, we have more than 1 candidate and need to
* decided whether to pick one of them. This routine returns true if
* the all the candidates operate on the same data types after
* promotion (int2, int4, float4 -> float8).
*/
bool
equivalentOpersAfterPromotion(CandidateList candidates)
{
CandidateList result;
CandidateList promotedCandidates = NULL;
Oid leftarg,
rightarg;
for (result = candidates; result != NULL; result = result->next)
{
CandidateList c;
c = (CandidateList) palloc(sizeof(*c));
c->args = (Oid *) palloc(2 * sizeof(Oid));
switch (result->args[0])
{
case FLOAT4OID:
case INT4OID:
case INT2OID:
case CASHOID:
c->args[0] = FLOAT8OID;
break;
default:
c->args[0] = result->args[0];
break;
}
switch (result->args[1])
{
case FLOAT4OID:
case INT4OID:
case INT2OID:
case CASHOID:
c->args[1] = FLOAT8OID;
break;
default:
c->args[1] = result->args[1];
break;
}
c->next = promotedCandidates;
promotedCandidates = c;
}
/*
* if we get called, we have more than 1 candidates so we can do the
* following safely
*/
leftarg = promotedCandidates->args[0];
rightarg = promotedCandidates->args[1];
for (result = promotedCandidates->next; result != NULL; result = result->next)
{
if (result->args[0] != leftarg || result->args[1] != rightarg)
/*
* this list contains operators that operate on different data
* types even after promotion. Hence we can't decide on which
* one to pick. The user must do explicit type casting.
*/
return FALSE;
}
/*
* all the candidates are equivalent in the following sense: they
* operate on equivalent data types and picking any one of them is as
* good.
*/
return TRUE;
}
/*
* given a choice of argument type pairs for a binary operator,
* try to choose a default pair
*/
CandidateList
binary_oper_select_candidate(Oid arg1,
Oid arg2,
CandidateList candidates)
{
CandidateList result;
/*
* if both are "unknown", there is no way to select a candidate
*
* current wisdom holds that the default operator should be one in which
* both operands have the same type (there will only be one such
* operator)
*
* 7.27.93 - I have decided not to do this; it's too hard to justify, and
* it's easy enough to typecast explicitly -avi [the rest of this
* routine were commented out since then -ay]
*/
if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID)
return (NULL);
/*
* 6/23/95 - I don't complete agree with avi. In particular, casting
* floats is a pain for users. Whatever the rationale behind not doing
* this is, I need the following special case to work.
*
* In the WHERE clause of a query, if a float is specified without
* quotes, we treat it as float8. I added the float48* operators so
* that we can operate on float4 and float8. But now we have more than
* one matching operator if the right arg is unknown (eg. float
* specified with quotes). This break some stuff in the regression
* test where there are floats in quotes not properly casted. Below is
* the solution. In addition to requiring the operator operates on the
* same type for both operands [as in the code Avi originally
* commented out], we also require that the operators be equivalent in
* some sense. (see equivalentOpersAfterPromotion for details.) - ay
* 6/95
*/
if (!equivalentOpersAfterPromotion(candidates))
return NULL;
/*
* if we get here, any one will do but we're more picky and require
* both operands be the same.
*/
for (result = candidates; result != NULL; result = result->next)
{
if (result->args[0] == result->args[1])
return result;
}
return (NULL);
}
/* Given operator, types of arg1, and arg2, return oper struct */
/* arg1, arg2 --typeids */
Operator
oper(char *op, Oid arg1, Oid arg2, bool noWarnings)
{
HeapTuple tup;
CandidateList candidates;
int ncandidates;
if (!arg2)
arg2 = arg1;
if (!arg1)
arg1 = arg2;
if (!(tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(arg1),
ObjectIdGetDatum(arg2),
Int8GetDatum('b'))))
{
ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
if (ncandidates == 0)
{
/*
* no operators of the desired types found
*/
if (!noWarnings)
op_error(op, arg1, arg2);
return (NULL);
}
else if (ncandidates == 1)
{
/*
* exactly one operator of the desired types found
*/
tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(candidates->args[0]),
ObjectIdGetDatum(candidates->args[1]),
Int8GetDatum('b'));
Assert(HeapTupleIsValid(tup));
}
else
{
/*
* multiple operators of the desired types found
*/
candidates = binary_oper_select_candidate(arg1, arg2, candidates);
if (candidates != NULL)
{
/* we chose one of them */
tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(candidates->args[0]),
ObjectIdGetDatum(candidates->args[1]),
Int8GetDatum('b'));
Assert(HeapTupleIsValid(tup));
}
else
{
Type tp1,
tp2;
/* we chose none of them */
tp1 = typeidType(arg1);
tp2 = typeidType(arg2);
if (!noWarnings)
{
elog(NOTICE, "there is more than one operator %s for types", op);
elog(NOTICE, "%s and %s. You will have to retype this query",
typeTypeName(tp1), typeTypeName(tp2));
elog(WARN, "using an explicit cast");
}
return (NULL);
}
}
}
return ((Operator) tup);
}
/*
* given opname and typeId, find all possible types for which
* a right/left unary operator named opname exists,
* such that typeId can be coerced to it
*/
int
unary_oper_get_candidates(char *op,
Oid typeId,
CandidateList *candidates,
char rightleft)
{
CandidateList current_candidate;
Relation pg_operator_desc;
HeapScanDesc pg_operator_scan;
HeapTuple tup;
OperatorTupleForm oper;
Buffer buffer;
int ncandidates = 0;
static ScanKeyData opKey[2] = {
{0, Anum_pg_operator_oprname, NameEqualRegProcedure},
{0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}};
*candidates = NULL;
fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func,
&opKey[0].sk_nargs);
opKey[0].sk_argument = NameGetDatum(op);
fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func,
&opKey[1].sk_nargs);
opKey[1].sk_argument = CharGetDatum(rightleft);
/* currently, only "unknown" can be coerced */
/*
* but we should allow types that are internally the same to be
* "coerced"
*/
if (typeId != UNKNOWNOID)
{
return 0;
}
pg_operator_desc = heap_openr(OperatorRelationName);
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
true,
2,
opKey);
do
{
tup = heap_getnext(pg_operator_scan, 0, &buffer);
if (HeapTupleIsValid(tup))
{
current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
current_candidate->args = (Oid *) palloc(sizeof(Oid));
oper = (OperatorTupleForm) GETSTRUCT(tup);
if (rightleft == 'r')
current_candidate->args[0] = oper->oprleft;
else
current_candidate->args[0] = oper->oprright;
current_candidate->next = *candidates;
*candidates = current_candidate;
ncandidates++;
ReleaseBuffer(buffer);
}
} while (HeapTupleIsValid(tup));
heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc);
return ncandidates;
}
/* Given unary right-side operator (operator on right), return oper struct */
/* arg-- type id */
Operator
right_oper(char *op, Oid arg)
{
HeapTuple tup;
CandidateList candidates;
int ncandidates;
/*
* if (!OpCache) { init_op_cache(); }
*/
if (!(tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(arg),
ObjectIdGetDatum(InvalidOid),
Int8GetDatum('r'))))
{
ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
if (ncandidates == 0)
{
elog(WARN,
"Can't find right op: %s for type %d", op, arg);
return (NULL);
}
else if (ncandidates == 1)
{
tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(candidates->args[0]),
ObjectIdGetDatum(InvalidOid),
Int8GetDatum('r'));
Assert(HeapTupleIsValid(tup));
}
else
{
elog(NOTICE, "there is more than one right operator %s", op);
elog(NOTICE, "you will have to retype this query");
elog(WARN, "using an explicit cast");
return (NULL);
}
}
return ((Operator) tup);
}
/* Given unary left-side operator (operator on left), return oper struct */
/* arg--type id */
Operator
left_oper(char *op, Oid arg)
{
HeapTuple tup;
CandidateList candidates;
int ncandidates;
/*
* if (!OpCache) { init_op_cache(); }
*/
if (!(tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(arg),
Int8GetDatum('l'))))
{
ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
if (ncandidates == 0)
{
elog(WARN,
"Can't find left op: %s for type %d", op, arg);
return (NULL);
}
else if (ncandidates == 1)
{
tup = SearchSysCacheTuple(OPRNAME,
PointerGetDatum(op),
ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(candidates->args[0]),
Int8GetDatum('l'));
Assert(HeapTupleIsValid(tup));
}
else
{
elog(NOTICE, "there is more than one left operator %s", op);
elog(NOTICE, "you will have to retype this query");
elog(WARN, "using an explicit cast");
return (NULL);
}
}
return ((Operator) tup);
}
/* Given a typename and value, returns the ascii form of the value */
#ifdef NOT_USED
char *
outstr(char *typename, /* Name of type of value */
char *value) /* Could be of any type */
{
TypeTupleForm tp;
Oid op;
tp = (TypeTupleForm) GETSTRUCT(type(typename));
op = tp->typoutput;
return ((char *) fmgr(op, value));
}
#endif
/*
* Give a somewhat useful error message when the operator for two types
* is not found.
*/
void
op_error(char *op, Oid arg1, Oid arg2)
{
Type tp1 = NULL,
tp2 = NULL;
if (typeidIsValid(arg1))
{
tp1 = typeidType(arg1);
}
else
{
elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
}
if (typeidIsValid(arg2))
{
tp2 = typeidType(arg2);
}
else
{
elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op);
}
elog(NOTICE, "there is no operator %s for types %s and %s",
op, typeTypeName(tp1), typeTypeName(tp2));
elog(NOTICE, "You will either have to retype this query using an");
elog(NOTICE, "explicit cast, or you will have to define the operator");
elog(WARN, "%s for %s and %s using CREATE OPERATOR",
op, typeTypeName(tp1), typeTypeName(tp2));
}

View File

@ -0,0 +1,480 @@
/*-------------------------------------------------------------------------
*
* parse_relation.c--
* parser support routines dealing with relations
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.1 1997/11/25 22:05:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include <string.h>
#include "postgres.h"
#include "access/heapam.h"
#include <access/htup.h>
#include <catalog/pg_type.h>
#include "nodes/makefuncs.h"
#include <parser/parse_relation.h>
#include <utils/acl.h>
#include "utils/builtins.h"
#include <utils/lsyscache.h>
#ifdef 0
#include "fmgr.h"
#include "access/tupmacs.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "utils/acl.h" /* for ACL_NO_PRIV_WARNING */
#include "utils/syscache.h"
#include "catalog/pg_operator.h"
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#endif
struct
{
char *field;
int code;
} special_attr[] =
{
{
"ctid", SelfItemPointerAttributeNumber
},
{
"oid", ObjectIdAttributeNumber
},
{
"xmin", MinTransactionIdAttributeNumber
},
{
"cmin", MinCommandIdAttributeNumber
},
{
"xmax", MaxTransactionIdAttributeNumber
},
{
"cmax", MaxCommandIdAttributeNumber
},
};
#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
static char *attnum_type[SPECIALS] = {
"tid",
"oid",
"xid",
"cid",
"xid",
"cid",
};
/* given refname, return a pointer to the range table entry */
RangeTblEntry *
refnameRangeTableEntry(List *rtable, char *refname)
{
List *temp;
foreach(temp, rtable)
{
RangeTblEntry *rte = lfirst(temp);
if (!strcmp(rte->refname, refname))
return rte;
}
return NULL;
}
/* given refname, return id of variable; position starts with 1 */
int
refnameRangeTablePosn(List *rtable, char *refname)
{
int index;
List *temp;
index = 1;
foreach(temp, rtable)
{
RangeTblEntry *rte = lfirst(temp);
if (!strcmp(rte->refname, refname))
return index;
index++;
}
return (0);
}
/*
* returns range entry if found, else NULL
*/
RangeTblEntry *
colnameRangeTableEntry(ParseState *pstate, char *colname)
{
List *et;
List *rtable;
RangeTblEntry *rte_result;
if (pstate->p_is_rule)
rtable = lnext(lnext(pstate->p_rtable));
else
rtable = pstate->p_rtable;
rte_result = NULL;
foreach(et, rtable)
{
RangeTblEntry *rte = lfirst(et);
/* only entries on outer(non-function?) scope */
if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
continue;
if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
{
if (rte_result != NULL)
{
if (!pstate->p_is_insert ||
rte != pstate->p_target_rangetblentry)
elog(WARN, "Column %s is ambiguous", colname);
}
else
rte_result = rte;
}
}
return rte_result;
}
/*
* put new entry in pstate p_rtable structure, or return pointer
* if pstate null
*/
RangeTblEntry *
addRangeTableEntry(ParseState *pstate,
char *relname,
char *refname,
bool inh,
bool inFromCl)
{
Relation relation;
RangeTblEntry *rte = makeNode(RangeTblEntry);
if (pstate != NULL &&
refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
elog(WARN, "Table name %s specified more than once", refname);
rte->relname = pstrdup(relname);
rte->refname = pstrdup(refname);
relation = heap_openr(relname);
if (relation == NULL)
{
elog(WARN, "%s: %s",
relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
}
/*
* Flags - zero or more from inheritance,union,version or
* recursive (transitive closure) [we don't support them all -- ay
* 9/94 ]
*/
rte->inh = inh;
/* RelOID */
rte->relid = RelationGetRelationId(relation);
rte->inFromCl = inFromCl;
/*
* close the relation we're done with it for now.
*/
if (pstate != NULL)
pstate->p_rtable = lappend(pstate->p_rtable, rte);
heap_close(relation);
return rte;
}
/*
* expandAll -
* makes a list of attributes
* assumes reldesc caching works
*/
List *
expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
{
Relation rdesc;
List *te_tail = NIL,
*te_head = NIL;
Var *varnode;
int varattno,
maxattrs;
Oid type_id;
int type_len;
RangeTblEntry *rte;
rte = refnameRangeTableEntry(pstate->p_rtable, refname);
if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
rdesc = heap_open(rte->relid);
if (rdesc == NULL)
{
elog(WARN, "Unable to expand all -- heap_open failed on %s",
rte->refname);
return NIL;
}
maxattrs = RelationGetNumberOfAttributes(rdesc);
for (varattno = 0; varattno <= maxattrs - 1; varattno++)
{
char *attrname;
char *resname = NULL;
TargetEntry *te = makeNode(TargetEntry);
attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
type_len = (int) typeLen(typeidType(type_id));
handleTargetColname(pstate, &resname, refname, attrname);
if (resname != NULL)
attrname = resname;
/*
* Even if the elements making up a set are complex, the set
* itself is not.
*/
te->resdom = makeResdom((AttrNumber) (*this_resno)++,
type_id,
(Size) type_len,
attrname,
(Index) 0,
(Oid) 0,
0);
te->expr = (Node *) varnode;
if (te_head == NIL)
te_head = te_tail = lcons(te, NIL);
else
te_tail = lappend(te_tail, te);
}
heap_close(rdesc);
return (te_head);
}
/* given relation and att name, return id of variable */
int
attnameAttNum(Relation rd, char *a)
{
int i;
for (i = 0; i < rd->rd_rel->relnatts; i++)
if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
return (i + 1);
for (i = 0; i < SPECIALS; i++)
if (!strcmp(special_attr[i].field, a))
return (special_attr[i].code);
/* on failure */
elog(WARN, "Relation %s does not have attribute %s",
RelationGetRelationName(rd), a);
return 0; /* lint */
}
/* Given range variable, return whether attribute of this name
* is a set.
* NOTE the ASSUMPTION here that no system attributes are, or ever
* will be, sets.
*/
bool
attnameIsSet(Relation rd, char *name)
{
int i;
/* First check if this is a system attribute */
for (i = 0; i < SPECIALS; i++)
{
if (!strcmp(special_attr[i].field, name))
{
return (false); /* no sys attr is a set */
}
}
return (get_attisset(rd->rd_id, name));
}
/*-------------
* given an attribute number and a relation, return its relation name
*/
char *
attnumAttName(Relation rd, int attrno)
{
char *name;
int i;
if (attrno < 0)
{
for (i = 0; i < SPECIALS; i++)
{
if (special_attr[i].code == attrno)
{
name = special_attr[i].field;
return (name);
}
}
elog(WARN, "Illegal attr no %d for relation %s",
attrno, RelationGetRelationName(rd));
}
else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd))
{
name = (rd->rd_att->attrs[attrno - 1]->attname).data;
return (name);
}
else
{
elog(WARN, "Illegal attr no %d for relation %s",
attrno, RelationGetRelationName(rd));
}
/*
* Shouldn't get here, but we want lint to be happy...
*/
return (NULL);
}
int
attnumAttNelems(Relation rd, int attid)
{
return (rd->rd_att->attrs[attid - 1]->attnelems);
}
Oid
attnameTypeId(Oid relid, char *attrname)
{
int attid;
Oid vartype;
Relation rd;
rd = heap_open(relid);
if (!RelationIsValid(rd))
{
rd = heap_openr(typeidTypeName(relid));
if (!RelationIsValid(rd))
elog(WARN, "cannot compute type of att %s for relid %d",
attrname, relid);
}
attid = attnameAttNum(rd, attrname); /* could elog(WARN) and never return */
vartype = attnumTypeId(rd, attid);
/*
* close relation we're done with it now
*/
heap_close(rd);
return (vartype);
}
/* given attribute id, return type of that attribute */
/* XXX Special case for pseudo-attributes is a hack */
Oid
attnumTypeId(Relation rd, int attid)
{
if (attid < 0)
return (typeTypeId(typenameType(attnum_type[-attid - 1])));
/*
* -1 because varattno (where attid comes from) returns one more than
* index
*/
return (rd->rd_att->attrs[attid - 1]->atttypid);
}
/*
* handleTargetColname -
* use column names from insert
*/
void
handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname)
{
if (pstate->p_is_insert)
{
if (pstate->p_insert_columns != NIL)
{
Ident *id = lfirst(pstate->p_insert_columns);
*resname = id->name;
pstate->p_insert_columns = lnext(pstate->p_insert_columns);
}
else
elog(WARN, "insert: more expressions than target columns");
}
if (pstate->p_is_insert || pstate->p_is_update)
checkTargetTypes(pstate, *resname, refname, colname);
}
/*
* checkTargetTypes -
* checks value and target column types
*/
void
checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname)
{
Oid attrtype_id,
attrtype_target;
int resdomno_id,
resdomno_target;
Relation rd;
RangeTblEntry *rte;
if (target_colname == NULL || colname == NULL)
return;
if (refname != NULL)
rte = refnameRangeTableEntry(pstate->p_rtable, refname);
else
{
rte = colnameRangeTableEntry(pstate, colname);
if (rte == (RangeTblEntry *) NULL)
elog(WARN, "attribute %s not found", colname);
refname = rte->refname;
}
/*
if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
elog(WARN, "%s not available in this context", colname);
*/
rd = heap_open(rte->relid);
resdomno_id = attnameAttNum(rd, colname);
attrtype_id = attnumTypeId(rd, resdomno_id);
resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
if (attrtype_id != attrtype_target)
elog(WARN, "Type of %s does not match target column %s",
colname, target_colname);
if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
rd->rd_att->attrs[resdomno_id - 1]->attlen !=
pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
elog(WARN, "Length of %s does not match length of target column %s",
colname, target_colname);
heap_close(rd);
}

View File

@ -0,0 +1,679 @@
/*-------------------------------------------------------------------------
*
* parse_target.c
* handle target lists
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.1 1997/11/25 22:05:47 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "postgres.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/primnodes.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_node.h"
#include "utils/builtins.h"
#ifdef 0
#include "nodes/nodes.h"
#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "nodes/relation.h"
#include "parse.h" /* for AND, OR, etc. */
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
#include "utils/acl.h"
#include "nodes/nodeFuncs.h"
#include "commands/sequence.h"
#include "optimizer/clauses.h"
#include "access/heapam.h"
#include "miscadmin.h"
#include "port-protos.h" /* strdup() */
#endif
/*
* transformTargetList -
* turns a list of ResTarget's into a list of TargetEntry's
*/
List *
transformTargetList(ParseState *pstate, List *targetlist)
{
List *p_target = NIL;
List *tail_p_target = NIL;
while (targetlist != NIL)
{
ResTarget *res = (ResTarget *) lfirst(targetlist);
TargetEntry *tent = makeNode(TargetEntry);
switch (nodeTag(res->val))
{
case T_Ident:
{
Node *expr;
Oid type_id;
int type_len;
char *identname;
char *resname;
identname = ((Ident *) res->val)->name;
handleTargetColname(pstate, &res->name, NULL, identname);
/*
* here we want to look for column names only, not relation
* names (even though they can be stored in Ident nodes, too)
*/
expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
type_id = exprType(expr);
type_len = typeLen(typeidType(type_id));
resname = (res->name) ? res->name : identname;
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
(Oid) type_id,
(Size) type_len,
resname,
(Index) 0,
(Oid) 0,
0);
tent->expr = expr;
break;
}
case T_ParamNo:
case T_FuncCall:
case T_A_Const:
case T_A_Expr:
{
Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
handleTargetColname(pstate, &res->name, NULL, NULL);
/* note indirection has not been transformed */
if (pstate->p_is_insert && res->indirection != NIL)
{
/* this is an array assignment */
char *val;
char *str,
*save_str;
List *elt;
int i = 0,
ndims;
int lindx[MAXDIM],
uindx[MAXDIM];
int resdomno;
Relation rd;
Value *constval;
if (exprType(expr) != UNKNOWNOID ||
!IsA(expr, Const))
elog(WARN, "yyparse: string constant expected");
val = (char *) textout((struct varlena *)
((Const *) expr)->constvalue);
str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
foreach(elt, res->indirection)
{
A_Indices *aind = (A_Indices *) lfirst(elt);
aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
if (!IsA(aind->uidx, Const))
elog(WARN,
"Array Index for Append should be a constant");
uindx[i] = ((Const *) aind->uidx)->constvalue;
if (aind->lidx != NULL)
{
aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
if (!IsA(aind->lidx, Const))
elog(WARN,
"Array Index for Append should be a constant");
lindx[i] = ((Const *) aind->lidx)->constvalue;
}
else
{
lindx[i] = 1;
}
if (lindx[i] > uindx[i])
elog(WARN, "yyparse: lower index cannot be greater than upper index");
sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
str += strlen(str);
i++;
}
sprintf(str, "=%s", val);
rd = pstate->p_target_relation;
Assert(rd != NULL);
resdomno = attnameAttNum(rd, res->name);
ndims = attnumAttNelems(rd, resdomno);
if (i != ndims)
elog(WARN, "yyparse: array dimensions do not match");
constval = makeNode(Value);
constval->type = T_String;
constval->val.str = save_str;
tent = make_targetlist_expr(pstate, res->name,
(Node *) make_const(constval),
NULL);
pfree(save_str);
}
else
{
char *colname = res->name;
/* this is not an array assignment */
if (colname == NULL)
{
/*
* if you're wondering why this is here, look
* at the yacc grammar for why a name can be
* missing. -ay
*/
colname = figureColname(expr, res->val);
}
if (res->indirection)
{
List *ilist = res->indirection;
while (ilist != NIL)
{
A_Indices *ind = lfirst(ilist);
ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
ilist = lnext(ilist);
}
}
res->name = colname;
tent = make_targetlist_expr(pstate, res->name, expr,
res->indirection);
}
break;
}
case T_Attr:
{
Oid type_id;
int type_len;
Attr *att = (Attr *) res->val;
Node *result;
char *attrname;
char *resname;
Resdom *resnode;
List *attrs = att->attrs;
/*
* Target item is a single '*', expand all tables (eg.
* SELECT * FROM emp)
*/
if (att->relname != NULL && !strcmp(att->relname, "*"))
{
if (tail_p_target == NIL)
p_target = tail_p_target = expandAllTables(pstate);
else
lnext(tail_p_target) = expandAllTables(pstate);
while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */
tail_p_target = lnext(tail_p_target);
/*
* skip rest of while loop
*/
targetlist = lnext(targetlist);
continue;
}
/*
* Target item is relation.*, expand the table (eg.
* SELECT emp.*, dname FROM emp, dept)
*/
attrname = strVal(lfirst(att->attrs));
if (att->attrs != NIL && !strcmp(attrname, "*"))
{
/*
* tail_p_target is the target list we're building
* in the while loop. Make sure we fix it after
* appending more nodes.
*/
if (tail_p_target == NIL)
p_target = tail_p_target = expandAll(pstate, att->relname,
att->relname, &pstate->p_last_resno);
else
lnext(tail_p_target) =
expandAll(pstate, att->relname, att->relname,
&pstate->p_last_resno);
while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */
tail_p_target = lnext(tail_p_target);
/*
* skip the rest of the while loop
*/
targetlist = lnext(targetlist);
continue;
}
/*
* Target item is fully specified: ie.
* relation.attribute
*/
result = handleNestedDots(pstate, att, &pstate->p_last_resno);
handleTargetColname(pstate, &res->name, att->relname, attrname);
if (att->indirection != NIL)
{
List *ilist = att->indirection;
while (ilist != NIL)
{
A_Indices *ind = lfirst(ilist);
ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
ilist = lnext(ilist);
}
result = (Node *) make_array_ref(result, att->indirection);
}
type_id = exprType(result);
type_len = typeLen(typeidType(type_id));
/* move to last entry */
while (lnext(attrs) != NIL)
attrs = lnext(attrs);
resname = (res->name) ? res->name : strVal(lfirst(attrs));
resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
(Oid) type_id,
(Size) type_len,
resname,
(Index) 0,
(Oid) 0,
0);
tent->resdom = resnode;
tent->expr = result;
break;
}
default:
/* internal error */
elog(WARN,
"internal error: do not know how to transform targetlist");
break;
}
if (p_target == NIL)
{
p_target = tail_p_target = lcons(tent, NIL);
}
else
{
lnext(tail_p_target) = lcons(tent, NIL);
tail_p_target = lnext(tail_p_target);
}
targetlist = lnext(targetlist);
}
return p_target;
}
/*
* make_targetlist_expr -
* make a TargetEntry from an expression
*
* arrayRef is a list of transformed A_Indices
*/
TargetEntry *
make_targetlist_expr(ParseState *pstate,
char *colname,
Node *expr,
List *arrayRef)
{
Oid type_id,
attrtype;
int type_len,
attrlen;
int resdomno;
Relation rd;
bool attrisset;
TargetEntry *tent;
Resdom *resnode;
if (expr == NULL)
elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
type_id = exprType(expr);
if (type_id == InvalidOid)
{
type_len = 0;
}
else
type_len = typeLen(typeidType(type_id));
/* I have no idea what the following does! */
/* It appears to process target columns that will be receiving results */
if (pstate->p_is_insert || pstate->p_is_update)
{
/*
* append or replace query -- append, replace work only on one
* relation, so multiple occurence of same resdomno is bogus
*/
rd = pstate->p_target_relation;
Assert(rd != NULL);
resdomno = attnameAttNum(rd, colname);
attrisset = attnameIsSet(rd, colname);
attrtype = attnumTypeId(rd, resdomno);
if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
attrtype = GetArrayElementType(attrtype);
if (attrtype == BPCHAROID || attrtype == VARCHAROID)
{
attrlen = rd->rd_att->attrs[resdomno - 1]->attlen;
}
else
{
attrlen = typeLen(typeidType(attrtype));
}
#if 0
if (Input_is_string && Typecast_ok)
{
Datum val;
if (type_id == typeTypeId(type("unknown")))
{
val = (Datum) textout((struct varlena *)
((Const) lnext(expr))->constvalue);
}
else
{
val = ((Const) lnext(expr))->constvalue;
}
if (attrisset)
{
lnext(expr) = makeConst(attrtype,
attrlen,
val,
false,
true,
true, /* is set */
false);
}
else
{
lnext(expr) =
makeConst(attrtype,
attrlen,
(Datum) fmgr(typeidRetinfunc(attrtype),
val, typeidTypElem(attrtype), -1),
false,
true /* Maybe correct-- 80% chance */ ,
false, /* is not a set */
false);
}
}
else if ((Typecast_ok) && (attrtype != type_id))
{
lnext(expr) =
parser_typecast2(expr, typeidType(attrtype));
}
else if (attrtype != type_id)
{
if ((attrtype == INT2OID) && (type_id == INT4OID))
lfirst(expr) = lispInteger(INT2OID); /* handle CASHOID too */
else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
lfirst(expr) = lispInteger(FLOAT4OID);
else
elog(WARN, "unequal type in tlist : %s \n", colname);
}
Input_is_string = false;
Input_is_integer = false;
Typecast_ok = true;
#endif
if (attrtype != type_id)
{
if (IsA(expr, Const))
{
/* try to cast the constant */
if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
{
/* updating a single item */
Oid typelem = typeidTypElem(attrtype);
expr = (Node *) parser_typecast2(expr,
type_id,
typeidType(typelem),
attrlen);
}
else
expr = (Node *) parser_typecast2(expr,
type_id,
typeidType(attrtype),
attrlen);
}
else
{
/* currently, we can't handle casting of expressions */
elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
colname,
typeidTypeName(attrtype),
typeidTypeName(type_id));
}
}
if (arrayRef != NIL)
{
Expr *target_expr;
Attr *att = makeNode(Attr);
List *ar = arrayRef;
List *upperIndexpr = NIL;
List *lowerIndexpr = NIL;
att->relname = pstrdup(RelationGetRelationName(rd)->data);
att->attrs = lcons(makeString(colname), NIL);
target_expr = (Expr *) handleNestedDots(pstate, att,
&pstate->p_last_resno);
while (ar != NIL)
{
A_Indices *ind = lfirst(ar);
if (lowerIndexpr || (!upperIndexpr && ind->lidx))
{
/*
* XXX assume all lowerIndexpr is non-null in this
* case
*/
lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
}
upperIndexpr = lappend(upperIndexpr, ind->uidx);
ar = lnext(ar);
}
expr = (Node *) make_array_set(target_expr,
upperIndexpr,
lowerIndexpr,
(Expr *) expr);
attrtype = attnumTypeId(rd, resdomno);
attrlen = typeLen(typeidType(attrtype));
}
}
else
{
resdomno = pstate->p_last_resno++;
attrtype = type_id;
attrlen = type_len;
}
tent = makeNode(TargetEntry);
resnode = makeResdom((AttrNumber) resdomno,
(Oid) attrtype,
(Size) attrlen,
colname,
(Index) 0,
(Oid) 0,
0);
tent->resdom = resnode;
tent->expr = expr;
return tent;
}
/*
* makeTargetNames -
* generate a list of column names if not supplied or
* test supplied column names to make sure they are in target table
* (used exclusively for inserts)
*/
List *
makeTargetNames(ParseState *pstate, List *cols)
{
List *tl = NULL;
/* Generate ResTarget if not supplied */
if (cols == NIL)
{
int numcol;
int i;
AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
numcol = pstate->p_target_relation->rd_rel->relnatts;
for (i = 0; i < numcol; i++)
{
Ident *id = makeNode(Ident);
id->name = palloc(NAMEDATALEN);
StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
id->indirection = NIL;
id->isRel = false;
if (tl == NIL)
cols = tl = lcons(id, NIL);
else
{
lnext(tl) = lcons(id, NIL);
tl = lnext(tl);
}
}
}
else
{
foreach(tl, cols)
{
List *nxt;
char *name = ((Ident *) lfirst(tl))->name;
/* elog on failure */
attnameAttNum(pstate->p_target_relation, name);
foreach(nxt, lnext(tl))
if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
elog (WARN, "Attribute '%s' should be specified only once", name);
}
}
return cols;
}
/*
* expandAllTables -
* turns '*' (in the target list) into a list of attributes
* (of all relations in the range table)
*/
List *
expandAllTables(ParseState *pstate)
{
List *target = NIL;
List *legit_rtable = NIL;
List *rt,
*rtable;
rtable = pstate->p_rtable;
if (pstate->p_is_rule)
{
/*
* skip first two entries, "*new*" and "*current*"
*/
rtable = lnext(lnext(pstate->p_rtable));
}
/* this should not happen */
if (rtable == NULL)
elog(WARN, "cannot expand: null p_rtable");
/*
* go through the range table and make a list of range table entries
* which we will expand.
*/
foreach(rt, rtable)
{
RangeTblEntry *rte = lfirst(rt);
/*
* we only expand those specify in the from clause. (This will
* also prevent us from using the wrong table in inserts: eg.
* tenk2 in "insert into tenk2 select * from tenk1;")
*/
if (!rte->inFromCl)
continue;
legit_rtable = lappend(legit_rtable, rte);
}
foreach(rt, legit_rtable)
{
RangeTblEntry *rte = lfirst(rt);
List *temp = target;
if (temp == NIL)
target = expandAll(pstate, rte->relname, rte->refname,
&pstate->p_last_resno);
else
{
while (temp != NIL && lnext(temp) != NIL)
temp = lnext(temp);
lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
&pstate->p_last_resno);
}
}
return target;
}
/*
* figureColname -
* if the name of the resulting column is not specified in the target
* list, we have to guess.
*
*/
char *
figureColname(Node *expr, Node *resval)
{
switch (nodeTag(expr))
{
case T_Aggreg:
return (char *) /* XXX */
((Aggreg *) expr)->aggname;
case T_Expr:
if (((Expr *) expr)->opType == FUNC_EXPR)
{
if (nodeTag(resval) == T_FuncCall)
return ((FuncCall *) resval)->funcname;
}
break;
default:
break;
}
return "?column?";
}

View File

@ -0,0 +1,319 @@
/*-------------------------------------------------------------------------
*
* parse_type.h
* handle type operations for parser
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.1 1997/11/25 22:05:51 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include "postgres.h"
#include "fmgr.h"
#include <catalog/pg_type.h>
#include <parser/parse_target.h>
#include <parser/parse_type.h>
#include "utils/syscache.h"
#ifdef 0
#include "lib/dllist.h"
#include "utils/datum.h"
#include "utils/builtins.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
#include "catalog/catname.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/indexing.h"
#include "catalog/catname.h"
#include "access/skey.h"
#include "access/relscan.h"
#include "access/tupdesc.h"
#include "access/htup.h"
#include "access/heapam.h"
#include "access/genam.h"
#include "access/itup.h"
#include "access/tupmacs.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "utils/lsyscache.h"
#include "storage/lmgr.h"
#include "port-protos.h" /* strdup() */
#endif
/* check to see if a type id is valid,
* returns true if it is. By using this call before calling
* typeidType or typeidTypeName, more meaningful error messages
* can be produced because the caller typically has more context of
* what's going on - jolly
*/
bool
typeidIsValid(Oid id)
{
return (SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(id),
0, 0, 0) != NULL);
}
/* return a type name, given a typeid */
char *
typeidTypeName(Oid id)
{
HeapTuple tup;
TypeTupleForm typetuple;
if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
0, 0, 0)))
{
elog(WARN, "type id lookup of %ud failed", id);
return (NULL);
}
typetuple = (TypeTupleForm) GETSTRUCT(tup);
return (typetuple->typname).data;
}
/* return a Type structure, given an typid */
Type
typeidType(Oid id)
{
HeapTuple tup;
if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
0, 0, 0)))
{
elog(WARN, "type id lookup of %ud failed", id);
return (NULL);
}
return ((Type) tup);
}
/* return a Type structure, given type name */
Type
typenameType(char *s)
{
HeapTuple tup;
if (s == NULL)
{
elog(WARN, "type(): Null type");
}
if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0)))
{
elog(WARN, "type name lookup of %s failed", s);
}
return ((Type) tup);
}
/* given type, return the type OID */
Oid
typeTypeId(Type tp)
{
if (tp == NULL)
elog(WARN, "typeTypeId() called with NULL type struct");
return (tp->t_oid);
}
/* given type (as type struct), return the length of type */
int16
typeLen(Type t)
{
TypeTupleForm typ;
typ = (TypeTupleForm) GETSTRUCT(t);
return (typ->typlen);
}
/* given type (as type struct), return the value of its 'byval' attribute.*/
bool
typeByVal(Type t)
{
TypeTupleForm typ;
typ = (TypeTupleForm) GETSTRUCT(t);
return (typ->typbyval);
}
/* given type (as type struct), return the name of type */
char *
typeTypeName(Type t)
{
TypeTupleForm typ;
typ = (TypeTupleForm) GETSTRUCT(t);
return (typ->typname).data;
}
/* given a type, return its typetype ('c' for 'c'atalog types) */
char
typeTypeFlag(Type t)
{
TypeTupleForm typ;
typ = (TypeTupleForm) GETSTRUCT(t);
return (typ->typtype);
}
/* Given a type structure and a string, returns the internal form of
that string */
char *
stringTypeString(Type tp, char *string, int typlen)
{
Oid op;
Oid typelem;
op = ((TypeTupleForm) GETSTRUCT(tp))->typinput;
typelem = ((TypeTupleForm) GETSTRUCT(tp))->typelem; /* XXX - used for array_in */
/* typlen is for bpcharin() and varcharin() */
return ((char *) fmgr(op, string, typelem, typlen));
}
/* Given a type id, returns the out-conversion function of the type */
Oid
typeidRetoutfunc(Oid type_id)
{
HeapTuple typeTuple;
TypeTupleForm type;
Oid outfunc;
typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_id),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(WARN, "typeidRetoutfunc: Invalid type - oid = %u", type_id);
type = (TypeTupleForm) GETSTRUCT(typeTuple);
outfunc = type->typoutput;
return (outfunc);
}
Oid
typeidTypeRelid(Oid type_id)
{
HeapTuple typeTuple;
TypeTupleForm type;
Oid infunc;
typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_id),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(WARN, "typeidTypeRelid: Invalid type - oid = %u", type_id);
type = (TypeTupleForm) GETSTRUCT(typeTuple);
infunc = type->typrelid;
return (infunc);
}
Oid
typeTypeRelid(Type typ)
{
TypeTupleForm typtup;
typtup = (TypeTupleForm) GETSTRUCT(typ);
return (typtup->typrelid);
}
Oid
typeidTypElem(Oid type_id)
{
HeapTuple typeTuple;
TypeTupleForm type;
if (!(typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_id),
0, 0, 0)))
{
elog(WARN, "type id lookup of %u failed", type_id);
}
type = (TypeTupleForm) GETSTRUCT(typeTuple);
return (type->typelem);
}
/* Given the attribute type of an array return the arrtribute type of
an element of the array */
Oid
GetArrayElementType(Oid typearray)
{
HeapTuple type_tuple;
TypeTupleForm type_struct_array;
type_tuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(typearray),
0, 0, 0);
if (!HeapTupleIsValid(type_tuple))
elog(WARN, "GetArrayElementType: Cache lookup failed for type %d",
typearray);
/* get the array type struct from the type tuple */
type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
if (type_struct_array->typelem == InvalidOid)
{
elog(WARN, "GetArrayElementType: type %s is not an array",
(Name) &(type_struct_array->typname.data[0]));
}
return (type_struct_array->typelem);
}
/* Given a type id, returns the in-conversion function of the type */
Oid
typeidRetinfunc(Oid type_id)
{
HeapTuple typeTuple;
TypeTupleForm type;
Oid infunc;
typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_id),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(WARN, "typeidRetinfunc: Invalid type - oid = %u", type_id);
type = (TypeTupleForm) GETSTRUCT(typeTuple);
infunc = type->typinput;
return (infunc);
}
#ifdef NOT_USED
char
FindDelimiter(char *typename)
{
char delim;
HeapTuple typeTuple;
TypeTupleForm type;
if (!(typeTuple = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(typename),
0, 0, 0)))
{
elog(WARN, "type name lookup of %s failed", typename);
}
type = (TypeTupleForm) GETSTRUCT(typeTuple);
delim = type->typdelim;
return (delim);
}
#endif

View File

@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.28 1997/11/20 23:22:24 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.29 1997/11/25 22:05:52 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -14,9 +14,20 @@
#include <stdio.h>
#include "postgres.h"
#include "nodes/pg_list.h"
#include "parser/parser.h"
#include "parser/analyze.h"
#include "parser/parse_node.h"
void init_io(); /* from scan.l */
void parser_init(Oid *typev, int nargs); /* from gram.y */
int yyparse(); /* from gram.c */
#ifdef 0
#include "parser/parse.h"
#include "parser/gramparse.h"
#include "parser/parse_query.h"
#include "utils/palloc.h"
#endif
char *parseString; /* the char* which holds the string to be
* parsed */
@ -103,10 +114,10 @@ static void
define_sets(Node *clause)
{
Oid setoid;
Type t = type("oid");
Oid typeoid = typeid(t);
Size oidsize = tlen(t);
bool oidbyval = tbyval(t);
Type t = typeidType(OIDOID);
Oid typeoid = typeTypeId(t);
Size oidsize = typeLen(t);
bool oidbyval = typeByVal(t);
if (clause == NULL)
{
@ -125,11 +136,11 @@ define_sets(Node *clause)
return;
}
setoid = SetDefine(((Const *) clause)->constvalue,
get_id_typname(((Const *) clause)->consttype));
typeidTypeName(((Const *) clause)->consttype));
set_constvalue((Const) clause, setoid);
set_consttype((Const) clause, typeoid);
set_constlen((Const) clause, oidsize);
set_constbyval((Const) clause, oidbyval);
set_constypeByVal((Const) clause, oidbyval);
}
else if (IsA(clause, Iter))
{
@ -173,6 +184,5 @@ define_sets(Node *clause)
define_sets(get_rightop(clause));
}
}
#endif

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.7 1997/09/08 02:25:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.8 1997/11/25 22:05:55 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,7 +17,6 @@
#include <ctype.h>
#include <string.h>
#include "c.h"
#include "postgres.h"
#include "miscadmin.h"
#include "utils/elog.h"

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.7 1997/10/25 05:37:07 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.8 1997/11/25 22:06:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -23,7 +23,8 @@
#include "utils/lsyscache.h" /* for get_typlen */
#include "nodes/pg_list.h" /* for Lisp support */
#include "nodes/parsenodes.h"
#include "parser/catalog_utils.h"
#include "parser/parse_relation.h"
#include "rewrite/locks.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteRemove.h"
@ -107,7 +108,7 @@ InsertRule(char *rulname,
if (evslot == NULL)
evslot_index = -1;
else
evslot_index = varattno(eventrel, (char *) evslot);
evslot_index = attnameAttNum(eventrel, (char *) evslot);
heap_close(eventrel);
if (evinstead)
@ -221,8 +222,8 @@ DefineQueryRewrite(RuleStmt *stmt)
}
else
{
event_attno = varattno(event_relation, eslot_string);
event_attype = att_typeid(event_relation, event_attno);
event_attno = attnameAttNum(event_relation, eslot_string);
event_attype = attnumTypeId(event_relation, event_attno);
}
heap_close(event_relation);

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.19 1997/11/24 05:08:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.20 1997/11/25 22:06:08 momjian Exp $
*
* NOTES
* See acl.h.
@ -31,10 +31,12 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
#include "parser/catalog_utils.h"
#include "fmgr.h"
static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.54 1997/11/10 15:24:55 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.55 1997/11/25 22:06:14 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -45,11 +45,10 @@
#include "lib/dllist.h"
#include "parser/catalog_utils.h"
#include "parser/parse_query.h" /* for MakeTimeRange() */
#include "commands/async.h"
#include "tcop/tcopprot.h" /* where declarations for this file go */
#include "optimizer/planner.h"
#include "parser/parser.h"
#include "tcop/tcopprot.h"
#include "tcop/tcopdebug.h"
@ -1341,7 +1340,7 @@ PostgresMain(int argc, char *argv[])
if (IsUnderPostmaster == false)
{
puts("\nPOSTGRES backend interactive interface");
puts("$Revision: 1.54 $ $Date: 1997/11/10 15:24:55 $");
puts("$Revision: 1.55 $ $Date: 1997/11/25 22:06:14 $");
}
/* ----------------

View File

@ -15,7 +15,6 @@
#include "nodes/execnodes.h"
#include "nodes/plannodes.h"
#include "catalog/pg_proc.h"
#include "parser/parse_query.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"

View File

@ -6,13 +6,16 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: nodeFuncs.h,v 1.5 1997/09/08 21:52:45 momjian Exp $
* $Id: nodeFuncs.h,v 1.6 1997/11/25 22:06:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEFUNCS_H
#define NODEFUNCS_H
#include <nodes/nodes.h>
#include <nodes/primnodes.h>
extern bool single_node(Node *node);
extern bool var_is_outer(Var *var);
extern bool var_is_rel(Var *var);

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: planner.h,v 1.5 1997/09/08 21:53:29 momjian Exp $
* $Id: planner.h,v 1.6 1997/11/25 22:06:37 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,6 +16,8 @@
/*
*/
#include <parser/parse_node.h>
extern Plan *planner(Query *parse);
extern void pg_checkretval(Oid rettype, QueryTreeList *querytree_list);

View File

@ -0,0 +1,19 @@
/*-------------------------------------------------------------------------
*
* analyze.h
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: analyze.h,v 1.1 1997/11/25 22:06:47 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef ANALYZE_H
#define ANALYZE_H
#include <parser/parse_node.h>
QueryTreeList *parse_analyze(List *pl);
#endif /* ANALYZE_H */

View File

@ -1,54 +0,0 @@
/*-------------------------------------------------------------------------
*
* catalog_utils.h--
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: catalog_utils.h,v 1.13 1997/09/08 21:53:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef CATALOG_UTILS_H
#define CATALOG_UTILS_H
#include <catalog/pg_type.h>
#include <access/htup.h>
typedef HeapTuple Type;
typedef HeapTuple Operator;
extern Type get_id_type(Oid id);
extern char *get_id_typname(Oid id);
extern Type type(char *);
extern Oid att_typeid(Relation rd, int attid);
extern int att_attnelems(Relation rd, int attid);
extern Oid typeid(Type tp);
extern int16 tlen(Type t);
extern bool tbyval(Type t);
extern char *tname(Type t);
extern int tbyvalue(Type t);
extern Oid oprid(Operator op);
extern Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
extern Operator right_oper(char *op, Oid arg);
extern Operator left_oper(char *op, Oid arg);
extern int varattno(Relation rd, char *a);
extern bool varisset(Relation rd, char *name);
extern int nf_varattno(Relation rd, char *a);
extern char *getAttrName(Relation rd, int attrno);
extern char *instr2(Type tp, char *string, int typlen);
extern Oid GetArrayElementType(Oid typearray);
extern Oid funcid_get_rettype(Oid funcid);
extern bool
func_get_detail(char *funcname, int nargs, Oid *oid_array,
Oid *funcid, Oid *rettype, bool *retset, Oid **true_typeids);
extern Oid typeid_get_retinfunc(Oid type_id);
extern Oid typeid_get_retoutfunc(Oid type_id);
extern Oid typeid_get_relid(Oid type_id);
extern Oid get_typrelid(Type typ);
extern Oid get_typelem(Oid type_id);
extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
extern void agg_error(char *caller, char *aggname, Oid basetypeID);
#endif /* CATALOG_UTILS_H */

View File

@ -0,0 +1,38 @@
/*-------------------------------------------------------------------------
*
* parse_agg.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_agg.h,v 1.1 1997/11/25 22:06:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_AGG_H
#define PARSE_AGG_H
#include <nodes/nodes.h>
#include <nodes/parsenodes.h>
#include <nodes/primnodes.h>
#include <parser/parse_node.h>
void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
void finalizeAggregates(ParseState *pstate, Query *qry);
bool contain_agg_clause(Node *clause);
bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
void parseCheckAggregates(ParseState *pstate, Query *qry);
Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
void agg_error(char *caller, char *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */

View File

@ -0,0 +1,39 @@
/*-------------------------------------------------------------------------
*
* parse_clause.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_clause.h,v 1.1 1997/11/25 22:06:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_CLAUSE_H
#define PARSE_CLAUSE_H
#include <nodes/pg_list.h>
#include <nodes/nodes.h>
#include <nodes/parsenodes.h>
#include <nodes/primnodes.h>
#include <parser/parse_node.h>
void parseFromClause(ParseState *pstate, List *frmList);
void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
Node *transformWhereClause(ParseState *pstate, Node *a_expr);
TargetEntry *find_targetlist_entry(ParseState *pstate,
SortGroupBy *sortgroupby, List *tlist);
List *transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist);
List *transformSortClause(ParseState *pstate,
List *orderlist, List *targetlist,
char *uniqueFlag);
#endif /* PARSE_CLAUSE_H */

View File

@ -0,0 +1,34 @@
/*-------------------------------------------------------------------------
*
* parse_exer.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_expr.h,v 1.1 1997/11/25 22:06:55 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_EXPR_H
#define PARSE_EXPR_H
#include <nodes/nodes.h>
#include <nodes/parsenodes.h>
#include <nodes/primnodes.h>
#include <parser/parse_node.h>
Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
Oid exprType(Node *expr);
Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
Node *parser_typecast(Value *expr, TypeName *typename, int typlen);
Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
#endif /* PARSE_EXPR_H */

View File

@ -0,0 +1,97 @@
/*-------------------------------------------------------------------------
*
* catalog_utils.h--
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_func.h,v 1.1 1997/11/25 22:06:56 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSER_FUNC_H
#define PARSER_FUNC_H
#include <nodes/nodes.h>
#include <nodes/pg_list.h>
#include <nodes/parsenodes.h>
#include <nodes/primnodes.h>
#include <parser/parse_func.h>
#include <parser/parse_node.h>
/*
* This structure is used to explore the inheritance hierarchy above
* nodes in the type tree in order to disambiguate among polymorphic
* functions.
*/
typedef struct _InhPaths
{
int nsupers; /* number of superclasses */
Oid self; /* this class */
Oid *supervec; /* vector of superclasses */
} InhPaths;
/*
* This structure holds a list of possible functions or operators that
* agree with the known name and argument types of the function/operator.
*/
typedef struct _CandidateList
{
Oid *args;
struct _CandidateList *next;
} *CandidateList;
Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs,
int *curr_resno);
Oid funcid_get_rettype(Oid funcid);
CandidateList func_get_candidates(char *funcname, int nargs);
bool can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids);
int match_argtypes(int nargs,
Oid *input_typeids,
CandidateList function_typeids,
CandidateList *candidates);
Oid * func_select_candidate(int nargs,
Oid *input_typeids,
CandidateList candidates);
bool func_get_detail(char *funcname,
int nargs,
Oid *oid_array,
Oid *funcid, /* return value */
Oid *rettype, /* return value */
bool *retset, /* return value */
Oid **true_typeids);
Oid ** argtype_inherit(int nargs, Oid *oid_array);
int findsupers(Oid relid, Oid **supervec);
Oid **genxprod(InhPaths *arginh, int nargs);
void make_arguments(int nargs,
List *fargs,
Oid *input_typeids,
Oid *function_typeids);
List *setup_tlist(char *attname, Oid relid);
List *setup_base_tlist(Oid typeid);
Node *ParseComplexProjection(ParseState *pstate,
char *funcname,
Node *first_arg,
bool *attisset);
void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
#endif /* PARSE_FUNC_H */

View File

@ -0,0 +1,67 @@
/*-------------------------------------------------------------------------
*
* parse_node.h
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_node.h,v 1.1 1997/11/25 22:06:57 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_NODE_H
#define PARSE_NODE_H
#include <nodes/nodes.h>
#include <nodes/pg_list.h>
#include <nodes/primnodes.h>
#include <nodes/parsenodes.h>
#include <parser/parse_type.h>
#include <utils/rel.h>
typedef struct QueryTreeList
{
int len; /* number of queries */
Query **qtrees;
} QueryTreeList;
/* state information used during parse analysis */
typedef struct ParseState
{
int p_last_resno;
List *p_rtable;
int p_numAgg;
List *p_aggs;
bool p_is_insert;
List *p_insert_columns;
bool p_is_update;
bool p_is_rule;
bool p_in_where_clause;
Relation p_target_relation;
RangeTblEntry *p_target_rangetblentry;
} ParseState;
ParseState *make_parsestate(void);
Node *make_operand(char *opname,
Node *tree,
Oid orig_typeId,
Oid true_typeId);
void disallow_setop(char *op, Type optype, Node *operand);
Expr *make_op(char *opname, Node *ltree, Node *rtree);
Var *make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id);
ArrayRef *make_array_ref(Node *expr,
List *indirection);
ArrayRef *make_array_set(Expr *target_expr,
List *upperIndexpr,
List *lowerIndexpr,
Expr *expr);
Const *make_const(Value *value);
#endif /* PARSE_NODE_H */

View File

@ -0,0 +1,50 @@
/*-------------------------------------------------------------------------
*
* catalog_utils.h--
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_oper.h,v 1.1 1997/11/25 22:06:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_OPER_H
#define PARSE_OPER_H
#include <parser/parse_func.h>
#include <parser/parse_node.h>
typedef HeapTuple Operator;
Oid any_ordering_op(int restype);
Oid oprid(Operator op);
int binary_oper_get_candidates(char *opname,
Oid leftTypeId,
Oid rightTypeId,
CandidateList *candidates);
bool equivalentOpersAfterPromotion(CandidateList candidates);
CandidateList binary_oper_select_candidate(Oid arg1,
Oid arg2,
CandidateList candidates);
Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
int
unary_oper_get_candidates(char *op,
Oid typeId,
CandidateList *candidates,
char rightleft);
Operator right_oper(char *op, Oid arg);
Operator left_oper(char *op, Oid arg);
void op_error(char *op, Oid arg1, Oid arg2);
#endif /* PARSE_OPER_H */

View File

@ -1,70 +0,0 @@
/*-------------------------------------------------------------------------
*
* parse_query.h--
* prototypes for parse_query.c.
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_query.h,v 1.14 1997/11/20 23:23:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_QUERY_H
#define PARSE_QUERY_H
#include <parser/catalog_utils.h>
#include <parser/parse_state.h>
#include <nodes/parsenodes.h>
typedef struct QueryTreeList
{
int len; /* number of queries */
Query **qtrees;
} QueryTreeList;
extern RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
extern RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
extern int refnameRangeTablePosn(List *rtable, char *refname);
extern RangeTblEntry *
addRangeTableEntry(ParseState *pstate,
char *relname, char *refname,
bool inh, bool inFromCl);
extern List *
expandAll(ParseState *pstate, char *relname, char *refname,
int *this_resno);
extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
extern Oid find_atttype(Oid relid, char *attrname);
extern Var *
make_var(ParseState *pstate,
char *relname, char *attrname, Oid *type_id);
extern ArrayRef *make_array_ref(Node *array, List *indirection);
extern ArrayRef *
make_array_set(Expr *target_expr, List *upperIndexpr,
List *lowerIndexpr, Expr *expr);
extern Const *make_const(Value *value);
extern void param_type_init(Oid *typev, int nargs);
extern Oid param_type(int t);
extern QueryTreeList *parser(char *str, Oid *typev, int nargs);
extern void handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname);
/*
* analyze.c
*/
Oid exprType(Node *expr);
QueryTreeList *parse_analyze(List *querytree_list);
/* define in parse_query.c, used in gram.y */
extern Oid *param_type_info;
extern int pfunc_num_args;
/* useful macros */
#define ISCOMPLEX(type) (typeid_get_relid(type) ? true : false)
#endif /* PARSE_QUERY_H */

View File

@ -0,0 +1,56 @@
/*-------------------------------------------------------------------------
*
* parse_query.h--
* prototypes for parse_query.c.
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_relation.h,v 1.1 1997/11/25 22:07:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_QUERY_H
#define PARSE_RANGE_H
#include <nodes/nodes.h>
#include <nodes/parsenodes.h>
#include <nodes/pg_list.h>
#include <nodes/primnodes.h>
#include <parser/parse_node.h>
#include <utils/rel.h>
RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
int refnameRangeTablePosn(List *rtable, char *refname);
RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
RangeTblEntry *addRangeTableEntry(ParseState *pstate,
char *relname,
char *refname,
bool inh,
bool inFromCl);
List *expandAll(ParseState *pstate, char *relname, char *refname,
int *this_resno);
int attnameAttNum(Relation rd, char *a);
bool attnameIsSet(Relation rd, char *name);
char *attnumAttName(Relation rd, int attrno);
int attnumAttNelems(Relation rd, int attid);
Oid attnameTypeId(Oid relid, char *attrname);
Oid attnumTypeId(Relation rd, int attid);
void handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname);
void checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname);
#endif /* PARSE_RANGE_H */

View File

@ -1,34 +0,0 @@
/*-------------------------------------------------------------------------
*
* parse_state.h--
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_state.h,v 1.8 1997/09/08 21:53:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_STATE_H
#define PARSE_STATE_H
#include <nodes/parsenodes.h>
#include <utils/rel.h>
/* state information used during parse analysis */
typedef struct ParseState
{
int p_last_resno;
List *p_rtable;
int p_numAgg;
List *p_aggs;
bool p_is_insert;
List *p_insert_columns;
bool p_is_update;
bool p_is_rule;
Relation p_target_relation;
RangeTblEntry *p_target_rangetblentry;
} ParseState;
#endif /* PARSE_QUERY_H */

View File

@ -0,0 +1,39 @@
/*-------------------------------------------------------------------------
*
* parse_target.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_target.h,v 1.1 1997/11/25 22:07:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_TARGET_H
#define PARSE_TARGET_H
#include <nodes/pg_list.h>
#include <nodes/nodes.h>
#include <nodes/parsenodes.h>
#include <nodes/primnodes.h>
#include <parser/parse_node.h>
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
List *transformTargetList(ParseState *pstate, List *targetlist);
TargetEntry *make_targetlist_expr(ParseState *pstate,
char *colname,
Node *expr,
List *arrayRef);
List *expandAllTables(ParseState *pstate);
char *figureColname(Node *expr, Node *resval);
List *makeTargetNames(ParseState *pstate, List *cols);
#endif /* PARSE_TARGET_H */

View File

@ -0,0 +1,37 @@
/*-------------------------------------------------------------------------
*
* parse_type.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_type.h,v 1.1 1997/11/25 22:07:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_TYPE_H
#define PARSE_TYPE_H
#include "access/htup.h"
typedef HeapTuple Type;
bool typeidIsValid(Oid id);
Type typeidType(Oid id);
Type typenameType(char *s);
char *typeidTypeName(Oid id);
Oid typeTypeId(Type tp);
int16 typeLen(Type t);
bool typeByVal(Type t);
char *typeTypeName(Type t);
char typeTypeFlag(Type t);
char *stringTypeString(Type tp, char *string, int typlen);
Oid typeidRetoutfunc(Oid type_id);
Oid typeidTypeRelid(Oid type_id);
Oid typeTypeRelid(Type typ);
Oid typeidTypElem(Oid type_id);
Oid GetArrayElementType(Oid typearray);
Oid typeidRetinfunc(Oid type_id);
#endif /* PARSE_TYPE_H */

View File

@ -0,0 +1,21 @@
/*-------------------------------------------------------------------------
*
* parser.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parser.h,v 1.1 1997/11/25 22:07:08 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSER_H
#define PARSER_H
#include <parser/parse_node.h>
QueryTreeList *parser(char *str, Oid *typev, int nargs);
#endif /* PARSER_H */

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: tcopprot.h,v 1.7 1997/09/08 21:54:42 momjian Exp $
* $Id: tcopprot.h,v 1.8 1997/11/25 22:07:10 momjian Exp $
*
* OLD COMMENTS
* This file was created so that other c files could get the two
@ -19,7 +19,7 @@
#define TCOPPROT_H
#include <executor/execdesc.h>
#include <parser/parse_query.h>
#include <parser/parse_node.h>
#ifndef BOOTSTRAP_INCLUDE
extern List *

View File

@ -1,6 +1,8 @@
#!/bin/sh
# check regression tests
# usage: checkresults < results.out
# usage: checkresults [ regress.out ]
[ "$#" -eq 0 ] && set regress.out
for file in `cat "$@" | grep 'failed$' | cut -d " " -f 1`
do