aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c4324
-rw-r--r--src/backend/parser/catalog_utils.c2457
-rw-r--r--src/backend/parser/dbcommands.c409
-rw-r--r--src/backend/parser/keywords.c366
-rw-r--r--src/backend/parser/parse_query.c1340
-rw-r--r--src/backend/parser/parser.c844
-rw-r--r--src/backend/parser/scansup.c173
-rw-r--r--src/backend/parser/sysfunc.c51
8 files changed, 5282 insertions, 4682 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index a78d2c5c70e..8f63522812e 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* analyze.c--
- * transform the parse tree into a query tree
+ * transform the parse tree into a query tree
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.38 1997/09/05 19:32:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.39 1997/09/07 04:44:38 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,11 +20,11 @@
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "nodes/relation.h"
-#include "parse.h" /* for AND, OR, etc. */
+#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/builtins.h" /* namecmp(), textout() */
#include "utils/lsyscache.h"
#include "utils/palloc.h"
#include "utils/mcxt.h"
@@ -41,502 +41,519 @@
#include "miscadmin.h"
-#include "port-protos.h" /* strdup() */
+#include "port-protos.h" /* strdup() */
/* convert the parse tree into a query tree */
-static Query *transformStmt(ParseState *pstate, Node *stmt);
-
-static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
-static Query *transformInsertStmt(ParseState *pstate, AppendStmt *stmt);
-static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
-static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
-static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
-static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
-static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
-static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
-static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
-
-#define EXPR_COLUMN_FIRST 1
+static Query *transformStmt(ParseState * pstate, Node * stmt);
+
+static Query *transformDeleteStmt(ParseState * pstate, DeleteStmt * stmt);
+static Query *transformInsertStmt(ParseState * pstate, AppendStmt * stmt);
+static Query *transformIndexStmt(ParseState * pstate, IndexStmt * stmt);
+static Query *transformExtendStmt(ParseState * pstate, ExtendStmt * stmt);
+static Query *transformRuleStmt(ParseState * query, RuleStmt * stmt);
+static Query *transformSelectStmt(ParseState * pstate, RetrieveStmt * stmt);
+static Query *transformUpdateStmt(ParseState * pstate, ReplaceStmt * stmt);
+static Query *transformCursorStmt(ParseState * pstate, CursorStmt * stmt);
+static Node *handleNestedDots(ParseState * pstate, Attr * attr, int *curr_resno);
+
+#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
-static Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
-static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
-
-static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
-static List *expandAllTables(ParseState *pstate);
-static char *figureColname(Node *expr, Node *resval);
-static List *makeTargetNames(ParseState *pstate, List *cols);
-static List *transformTargetList(ParseState *pstate, List *targetlist);
-static TargetEntry *make_targetlist_expr(ParseState *pstate,
- char *colname, Node *expr,
- List *arrayRef);
-static bool inWhereClause = false;
-static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
-static List *transformGroupClause(ParseState *pstate, List *grouplist,
- List *targetlist);
-static List *transformSortClause(ParseState *pstate,
- List *orderlist, List *targetlist,
- char* uniqueFlag);
-
-static void parseFromClause(ParseState *pstate, List *frmList);
-static Node *ParseFunc(ParseState *pstate, char *funcname,
- List *fargs, int *curr_resno);
-static List *setup_tlist(char *attname, Oid relid);
-static List *setup_base_tlist(Oid typeid);
-static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
- Oid *function_typeids);
-static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
-static void finalizeAggregates(ParseState *pstate, Query *qry);
-static void parseCheckAggregates(ParseState *pstate, Query *qry);
-static ParseState* makeParseState(void);
+static Node *transformExpr(ParseState * pstate, Node * expr, int precedence);
+static Node *transformIdent(ParseState * pstate, Node * expr, int precedence);
+
+static void makeRangeTable(ParseState * pstate, char *relname, List * frmList);
+static List *expandAllTables(ParseState * pstate);
+static char *figureColname(Node * expr, Node * resval);
+static List *makeTargetNames(ParseState * pstate, List * cols);
+static List *transformTargetList(ParseState * pstate, List * targetlist);
+static TargetEntry *
+make_targetlist_expr(ParseState * pstate,
+ char *colname, Node * expr,
+ List * arrayRef);
+static bool inWhereClause = false;
+static Node *transformWhereClause(ParseState * pstate, Node * a_expr);
+static List *
+transformGroupClause(ParseState * pstate, List * grouplist,
+ List * targetlist);
+static List *
+transformSortClause(ParseState * pstate,
+ List * orderlist, List * targetlist,
+ char *uniqueFlag);
+
+static void parseFromClause(ParseState * pstate, List * frmList);
+static Node *
+ParseFunc(ParseState * pstate, char *funcname,
+ List * fargs, int *curr_resno);
+static List *setup_tlist(char *attname, Oid relid);
+static List *setup_base_tlist(Oid typeid);
+static void
+make_arguments(int nargs, List * fargs, Oid * input_typeids,
+ Oid * function_typeids);
+static void AddAggToParseState(ParseState * pstate, Aggreg * aggreg);
+static void finalizeAggregates(ParseState * pstate, Query * qry);
+static void parseCheckAggregates(ParseState * pstate, Query * qry);
+static ParseState *makeParseState(void);
/*****************************************************************************
*
*****************************************************************************/
/*
- * makeParseState() --
- * allocate and initialize a new ParseState.
- * the CALLERS is responsible for freeing the ParseState* returned
+ * makeParseState() --
+ * allocate and initialize a new ParseState.
+ * the CALLERS is responsible for freeing the ParseState* returned
*
*/
-static ParseState*
+static ParseState *
makeParseState(void)
{
- ParseState *pstate;
-
- 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_target_relation = NULL;
- pstate->p_target_rangetblentry = NULL;
-
- return (pstate);
+ ParseState *pstate;
+
+ 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_target_relation = NULL;
+ pstate->p_target_rangetblentry = NULL;
+
+ return (pstate);
}
/*
* parse_analyze -
- * analyze a list of parse trees and transform them if necessary.
+ * analyze a list of parse trees and transform them if necessary.
*
* Returns a list of transformed parse trees. Optimizable statements are
* all transformed to Query while the rest stays the same.
*
* CALLER is responsible for freeing the QueryTreeList* returned
*/
-QueryTreeList *
-parse_analyze(List *pl)
+QueryTreeList *
+parse_analyze(List * pl)
{
- QueryTreeList *result;
- ParseState *pstate;
- int i = 0;
-
- result = malloc(sizeof(QueryTreeList));
- result->len = length(pl);
- result->qtrees = (Query**)malloc(result->len * sizeof(Query*));
-
- inWhereClause = false; /* to avoid nextval(sequence) in WHERE */
-
- while(pl!=NIL) {
- pstate = makeParseState();
- result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
- pl = lnext(pl);
- if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation);
- free(pstate);
- }
-
- return result;
+ QueryTreeList *result;
+ ParseState *pstate;
+ int i = 0;
+
+ result = malloc(sizeof(QueryTreeList));
+ result->len = length(pl);
+ result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
+
+ inWhereClause = false; /* to avoid nextval(sequence) in WHERE */
+
+ while (pl != NIL)
+ {
+ pstate = makeParseState();
+ result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
+ pl = lnext(pl);
+ if (pstate->p_target_relation != NULL)
+ heap_close(pstate->p_target_relation);
+ free(pstate);
+ }
+
+ return result;
}
/*
* transformStmt -
- * transform a Parse tree. If it is an optimizable statement, turn it
- * into a Query tree.
+ * transform a Parse tree. If it is an optimizable statement, turn it
+ * into a Query tree.
*/
-static Query *
-transformStmt(ParseState* pstate, Node *parseTree)
+static Query *
+transformStmt(ParseState * pstate, Node * parseTree)
{
- Query* result = NULL;
-
- switch(nodeTag(parseTree)) {
- /*------------------------
- * Non-optimizable statements
- *------------------------
- */
- case T_IndexStmt:
- result = transformIndexStmt(pstate, (IndexStmt *)parseTree);
- break;
-
- case T_ExtendStmt:
- result = transformExtendStmt(pstate, (ExtendStmt *)parseTree);
- break;
-
- case T_RuleStmt:
- result = transformRuleStmt(pstate, (RuleStmt *)parseTree);
- break;
-
- case T_ViewStmt:
- {
- ViewStmt *n = (ViewStmt *)parseTree;
- n->query = (Query *)transformStmt(pstate, (Node*)n->query);
- result = makeNode(Query);
- result->commandType = CMD_UTILITY;
- result->utilityStmt = (Node*)n;
- }
- break;
-
- case T_VacuumStmt:
- {
- MemoryContext oldcontext;
- /* make sure that this Query is allocated in TopMemory context
- because vacuum spans transactions and we don't want to lose
- the vacuum Query due to end-of-transaction free'ing*/
- oldcontext = MemoryContextSwitchTo(TopMemoryContext);
- result = makeNode(Query);
- result->commandType = CMD_UTILITY;
- result->utilityStmt = (Node*)parseTree;
- MemoryContextSwitchTo(oldcontext);
- break;
-
- }
- case T_ExplainStmt:
- {
- ExplainStmt *n = (ExplainStmt *)parseTree;
- result = makeNode(Query);
- result->commandType = CMD_UTILITY;
- n->query = transformStmt(pstate, (Node*)n->query);
- result->utilityStmt = (Node*)parseTree;
- }
- break;
-
- /*------------------------
- * Optimizable statements
- *------------------------
- */
- case T_AppendStmt:
- result = transformInsertStmt(pstate, (AppendStmt *)parseTree);
- break;
-
- case T_DeleteStmt:
- result = transformDeleteStmt(pstate, (DeleteStmt *)parseTree);
- break;
-
- case T_ReplaceStmt:
- result = transformUpdateStmt(pstate, (ReplaceStmt *)parseTree);
- break;
-
- case T_CursorStmt:
- result = transformCursorStmt(pstate, (CursorStmt *)parseTree);
- break;
-
- case T_RetrieveStmt:
- result = transformSelectStmt(pstate, (RetrieveStmt *)parseTree);
- break;
-
- default:
- /*
- * other statments don't require any transformation-- just
- * return the original parsetree
- */
- result = makeNode(Query);
- result->commandType = CMD_UTILITY;
- result->utilityStmt = (Node*)parseTree;
- break;
- }
- return result;
+ Query *result = NULL;
+
+ switch (nodeTag(parseTree))
+ {
+ /*------------------------
+ * Non-optimizable statements
+ *------------------------
+ */
+ case T_IndexStmt:
+ result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
+ break;
+
+ case T_ExtendStmt:
+ result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
+ break;
+
+ case T_RuleStmt:
+ result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
+ break;
+
+ case T_ViewStmt:
+ {
+ ViewStmt *n = (ViewStmt *) parseTree;
+
+ n->query = (Query *) transformStmt(pstate, (Node *) n->query);
+ result = makeNode(Query);
+ result->commandType = CMD_UTILITY;
+ result->utilityStmt = (Node *) n;
+ }
+ break;
+
+ case T_VacuumStmt:
+ {
+ MemoryContext oldcontext;
+
+ /*
+ * make sure that this Query is allocated in TopMemory context
+ * because vacuum spans transactions and we don't want to lose
+ * the vacuum Query due to end-of-transaction free'ing
+ */
+ oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ result = makeNode(Query);
+ result->commandType = CMD_UTILITY;
+ result->utilityStmt = (Node *) parseTree;
+ MemoryContextSwitchTo(oldcontext);
+ break;
+
+ }
+ case T_ExplainStmt:
+ {
+ ExplainStmt *n = (ExplainStmt *) parseTree;
+
+ result = makeNode(Query);
+ result->commandType = CMD_UTILITY;
+ n->query = transformStmt(pstate, (Node *) n->query);
+ result->utilityStmt = (Node *) parseTree;
+ }
+ break;
+
+ /*------------------------
+ * Optimizable statements
+ *------------------------
+ */
+ case T_AppendStmt:
+ result = transformInsertStmt(pstate, (AppendStmt *) parseTree);
+ break;
+
+ case T_DeleteStmt:
+ result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
+ break;
+
+ case T_ReplaceStmt:
+ result = transformUpdateStmt(pstate, (ReplaceStmt *) parseTree);
+ break;
+
+ case T_CursorStmt:
+ result = transformCursorStmt(pstate, (CursorStmt *) parseTree);
+ break;
+
+ case T_RetrieveStmt:
+ result = transformSelectStmt(pstate, (RetrieveStmt *) parseTree);
+ break;
+
+ default:
+
+ /*
+ * other statments don't require any transformation-- just return
+ * the original parsetree
+ */
+ result = makeNode(Query);
+ result->commandType = CMD_UTILITY;
+ result->utilityStmt = (Node *) parseTree;
+ break;
+ }
+ return result;
}
/*
* transformDeleteStmt -
- * transforms a Delete Statement
+ * transforms a Delete Statement
*/
-static Query *
-transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
+static Query *
+transformDeleteStmt(ParseState * pstate, DeleteStmt * stmt)
{
- Query *qry = makeNode(Query);
+ Query *qry = makeNode(Query);
- qry->commandType = CMD_DELETE;
+ qry->commandType = CMD_DELETE;
- /* set up a range table */
- makeRangeTable(pstate, stmt->relname, NULL);
-
- qry->uniqueFlag = NULL;
+ /* set up a range table */
+ makeRangeTable(pstate, stmt->relname, NULL);
- /* fix where clause */
- qry->qual = transformWhereClause(pstate, stmt->whereClause);
+ qry->uniqueFlag = NULL;
- qry->rtable = pstate->p_rtable;
- qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+ /* fix where clause */
+ qry->qual = transformWhereClause(pstate, stmt->whereClause);
- /* make sure we don't have aggregates in the where clause */
- if (pstate->p_numAgg > 0)
- parseCheckAggregates(pstate, qry);
+ qry->rtable = pstate->p_rtable;
+ qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+
+ /* make sure we don't have aggregates in the where clause */
+ if (pstate->p_numAgg > 0)
+ parseCheckAggregates(pstate, qry);
- return (Query *)qry;
+ return (Query *) qry;
}
/*
* transformInsertStmt -
- * transform an Insert Statement
+ * transform an Insert Statement
*/
-static Query *
-transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
+static Query *
+transformInsertStmt(ParseState * pstate, AppendStmt * stmt)
{
- Query *qry = makeNode(Query); /* make a new query tree */
+ Query *qry = makeNode(Query); /* make a new query tree */
- qry->commandType = CMD_INSERT;
- pstate->p_is_insert = true;
+ qry->commandType = CMD_INSERT;
+ pstate->p_is_insert = true;
- /* set up a range table */
- makeRangeTable(pstate, stmt->relname, stmt->fromClause);
+ /* set up a range table */
+ makeRangeTable(pstate, stmt->relname, stmt->fromClause);
- qry->uniqueFlag = NULL;
+ qry->uniqueFlag = NULL;
- /* fix the target list */
- pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
+ /* fix the target list */
+ pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
- qry->targetList = transformTargetList(pstate, stmt->targetList);
+ qry->targetList = transformTargetList(pstate, stmt->targetList);
- /* fix where clause */
- qry->qual = transformWhereClause(pstate, stmt->whereClause);
+ /* fix where clause */
+ qry->qual = transformWhereClause(pstate, stmt->whereClause);
- /* now the range table will not change */
- qry->rtable = pstate->p_rtable;
- qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+ /* now the range table will not change */
+ qry->rtable = pstate->p_rtable;
+ qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
- if (pstate->p_numAgg > 0)
- finalizeAggregates(pstate, qry);
+ if (pstate->p_numAgg > 0)
+ finalizeAggregates(pstate, qry);
- return (Query *)qry;
+ return (Query *) qry;
}
/*
* transformIndexStmt -
- * transforms the qualification of the index statement
+ * transforms the qualification of the index statement
*/
-static Query *
-transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
+static Query *
+transformIndexStmt(ParseState * pstate, IndexStmt * stmt)
{
- Query* q;
+ Query *q;
- q = makeNode(Query);
- q->commandType = CMD_UTILITY;
-
- /* take care of the where clause */
- stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
- stmt->rangetable = pstate->p_rtable;
+ q = makeNode(Query);
+ q->commandType = CMD_UTILITY;
- q->utilityStmt = (Node*)stmt;
+ /* take care of the where clause */
+ stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
+ stmt->rangetable = pstate->p_rtable;
- return q;
+ q->utilityStmt = (Node *) stmt;
+
+ return q;
}
/*
* transformExtendStmt -
- * transform the qualifications of the Extend Index Statement
+ * transform the qualifications of the Extend Index Statement
*
*/
-static Query *
-transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
+static Query *
+transformExtendStmt(ParseState * pstate, ExtendStmt * stmt)
{
- Query *q;
+ Query *q;
- q = makeNode(Query);
- q->commandType = CMD_UTILITY;
+ q = makeNode(Query);
+ q->commandType = CMD_UTILITY;
- /* take care of the where clause */
- stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
- stmt->rangetable = pstate->p_rtable;
+ /* take care of the where clause */
+ stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
+ stmt->rangetable = pstate->p_rtable;
- q->utilityStmt = (Node*)stmt;
- return q;
+ q->utilityStmt = (Node *) stmt;
+ return q;
}
/*
* transformRuleStmt -
- * transform a Create Rule Statement. The actions is a list of parse
- * trees which is transformed into a list of query trees.
+ * transform a Create Rule Statement. The actions is a list of parse
+ * trees which is transformed into a list of query trees.
*/
-static Query *
-transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
+static Query *
+transformRuleStmt(ParseState * pstate, RuleStmt * stmt)
{
- Query *q;
- List *actions;
-
- q = makeNode(Query);
- q->commandType = CMD_UTILITY;
-
- actions = stmt->actions;
- /*
- * transform each statment, like parse_analyze()
- */
- while (actions != NIL) {
+ Query *q;
+ List *actions;
+
+ q = makeNode(Query);
+ q->commandType = CMD_UTILITY;
+
+ actions = stmt->actions;
+
/*
- * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
- * equal to 2.
+ * transform each statment, like parse_analyze()
*/
- addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
- FALSE, FALSE, NULL);
- addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
- FALSE, FALSE, NULL);
+ while (actions != NIL)
+ {
- pstate->p_last_resno = 1;
- pstate->p_is_rule = true; /* for expand all */
- pstate->p_numAgg = 0;
- pstate->p_aggs = NULL;
-
- lfirst(actions) = transformStmt(pstate, lfirst(actions));
- actions = lnext(actions);
- }
+ /*
+ * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
+ * equal to 2.
+ */
+ addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
+ FALSE, FALSE, NULL);
+ addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
+ FALSE, FALSE, NULL);
+
+ pstate->p_last_resno = 1;
+ pstate->p_is_rule = true; /* for expand all */
+ pstate->p_numAgg = 0;
+ pstate->p_aggs = NULL;
+
+ lfirst(actions) = transformStmt(pstate, lfirst(actions));
+ actions = lnext(actions);
+ }
- /* take care of the where clause */
- stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
+ /* take care of the where clause */
+ stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
- q->utilityStmt = (Node*)stmt;
- return q;
+ q->utilityStmt = (Node *) stmt;
+ return q;
}
/*
* transformSelectStmt -
- * transforms a Select Statement
+ * transforms a Select Statement
*
*/
-static Query *
-transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
+static Query *
+transformSelectStmt(ParseState * pstate, RetrieveStmt * stmt)
{
- Query *qry = makeNode(Query);
+ Query *qry = makeNode(Query);
+
+ qry->commandType = CMD_SELECT;
- qry->commandType = CMD_SELECT;
+ /* set up a range table */
+ makeRangeTable(pstate, NULL, stmt->fromClause);
- /* set up a range table */
- makeRangeTable(pstate, NULL, stmt->fromClause);
+ qry->uniqueFlag = stmt->unique;
- qry->uniqueFlag = stmt->unique;
+ qry->into = stmt->into;
+ qry->isPortal = FALSE;
- qry->into = stmt->into;
- qry->isPortal = FALSE;
+ /* fix the target list */
+ qry->targetList = transformTargetList(pstate, stmt->targetList);
- /* fix the target list */
- qry->targetList = transformTargetList(pstate, stmt->targetList);
+ /* fix where clause */
+ qry->qual = transformWhereClause(pstate, stmt->whereClause);
- /* fix where clause */
- qry->qual = transformWhereClause(pstate,stmt->whereClause);
+ /* check subselect clause */
+ if (stmt->selectClause)
+ elog(NOTICE, "UNION not yet supported; using first SELECT only", NULL);
- /* check subselect clause */
- if (stmt->selectClause)
- elog(NOTICE,"UNION not yet supported; using first SELECT only",NULL);
+ /* check subselect clause */
+ if (stmt->havingClause)
+ elog(NOTICE, "HAVING not yet supported; ignore clause", NULL);
- /* check subselect clause */
- if (stmt->havingClause)
- elog(NOTICE,"HAVING not yet supported; ignore clause",NULL);
+ /* fix order clause */
+ qry->sortClause = transformSortClause(pstate,
+ stmt->sortClause,
+ qry->targetList,
+ qry->uniqueFlag);
- /* fix order clause */
- qry->sortClause = transformSortClause(pstate,
- stmt->sortClause,
- qry->targetList,
- qry->uniqueFlag);
+ /* fix group by clause */
+ qry->groupClause = transformGroupClause(pstate,
+ stmt->groupClause,
+ qry->targetList);
+ qry->rtable = pstate->p_rtable;
- /* fix group by clause */
- qry->groupClause = transformGroupClause(pstate,
- stmt->groupClause,
- qry->targetList);
- qry->rtable = pstate->p_rtable;
+ if (pstate->p_numAgg > 0)
+ finalizeAggregates(pstate, qry);
- if (pstate->p_numAgg > 0)
- finalizeAggregates(pstate, qry);
-
- return (Query *)qry;
+ return (Query *) qry;
}
/*
* transformUpdateStmt -
- * transforms an update statement
+ * transforms an update statement
*
*/
-static Query *
-transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
+static Query *
+transformUpdateStmt(ParseState * pstate, ReplaceStmt * stmt)
{
- Query *qry = makeNode(Query);
+ Query *qry = makeNode(Query);
+
+ qry->commandType = CMD_UPDATE;
+ pstate->p_is_update = true;
- qry->commandType = CMD_UPDATE;
- pstate->p_is_update = true;
- /*
- * the FROM clause is non-standard SQL syntax. We used to be able to
- * do this with REPLACE in POSTQUEL so we keep the feature.
- */
- makeRangeTable(pstate, stmt->relname, stmt->fromClause);
+ /*
+ * the FROM clause is non-standard SQL syntax. We used to be able to
+ * do this with REPLACE in POSTQUEL so we keep the feature.
+ */
+ makeRangeTable(pstate, stmt->relname, stmt->fromClause);
- /* fix the target list */
- qry->targetList = transformTargetList(pstate, stmt->targetList);
+ /* fix the target list */
+ qry->targetList = transformTargetList(pstate, stmt->targetList);
- /* fix where clause */
- qry->qual = transformWhereClause(pstate,stmt->whereClause);
+ /* fix where clause */
+ qry->qual = transformWhereClause(pstate, stmt->whereClause);
- qry->rtable = pstate->p_rtable;
- qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+ qry->rtable = pstate->p_rtable;
+ qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
- /* make sure we don't have aggregates in the where clause */
- if (pstate->p_numAgg > 0)
- parseCheckAggregates(pstate, qry);
+ /* make sure we don't have aggregates in the where clause */
+ if (pstate->p_numAgg > 0)
+ parseCheckAggregates(pstate, qry);
- return (Query *)qry;
+ return (Query *) qry;
}
/*
* transformCursorStmt -
- * transform a Create Cursor Statement
+ * transform a Create Cursor Statement
*
*/
-static Query *
-transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
+static Query *
+transformCursorStmt(ParseState * pstate, CursorStmt * stmt)
{
- Query *qry = makeNode(Query);
+ Query *qry = makeNode(Query);
- /*
- * in the old days, a cursor statement is a 'retrieve into portal';
- * If you change the following, make sure you also go through the code
- * in various places that tests the kind of operation.
- */
- qry->commandType = CMD_SELECT;
+ /*
+ * in the old days, a cursor statement is a 'retrieve into portal'; If
+ * you change the following, make sure you also go through the code in
+ * various places that tests the kind of operation.
+ */
+ qry->commandType = CMD_SELECT;
- /* set up a range table */
- makeRangeTable(pstate, NULL, stmt->fromClause);
+ /* set up a range table */
+ makeRangeTable(pstate, NULL, stmt->fromClause);
- qry->uniqueFlag = stmt->unique;
+ qry->uniqueFlag = stmt->unique;
- qry->into = stmt->portalname;
- qry->isPortal = TRUE;
- qry->isBinary = stmt->binary; /* internal portal */
+ qry->into = stmt->portalname;
+ qry->isPortal = TRUE;
+ qry->isBinary = stmt->binary; /* internal portal */
- /* fix the target list */
- qry->targetList = transformTargetList(pstate, stmt->targetList);
+ /* fix the target list */
+ qry->targetList = transformTargetList(pstate, stmt->targetList);
- /* fix where clause */
- qry->qual = transformWhereClause(pstate,stmt->whereClause);
+ /* fix where clause */
+ qry->qual = transformWhereClause(pstate, stmt->whereClause);
- /* fix order clause */
- qry->sortClause = transformSortClause(pstate,
- stmt->sortClause,
- qry->targetList,
- qry->uniqueFlag);
- /* fix group by clause */
- qry->groupClause = transformGroupClause(pstate,
- stmt->groupClause,
- qry->targetList);
+ /* fix order clause */
+ qry->sortClause = transformSortClause(pstate,
+ stmt->sortClause,
+ qry->targetList,
+ qry->uniqueFlag);
+ /* fix group by clause */
+ qry->groupClause = transformGroupClause(pstate,
+ stmt->groupClause,
+ qry->targetList);
- qry->rtable = pstate->p_rtable;
+ qry->rtable = pstate->p_rtable;
- if (pstate->p_numAgg > 0)
- finalizeAggregates(pstate, qry);
+ if (pstate->p_numAgg > 0)
+ finalizeAggregates(pstate, qry);
- return (Query *)qry;
+ return (Query *) qry;
}
/*****************************************************************************
@@ -547,236 +564,278 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
/*
* 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.
+ * 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.
*/
-static Node *
-transformExpr(ParseState *pstate, Node *expr, int precedence)
+static Node *
+transformExpr(ParseState * pstate, Node * expr, int precedence)
{
- Node *result = NULL;
+ 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 (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);
+ 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",
- tname(get_id_type(exprType(lexpr))));
- if (exprType(rexpr) != BOOLOID)
- elog(WARN,
- "right-hand side of AND is type '%s', not bool",
- tname(get_id_type(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",
- tname(get_id_type(exprType(lexpr))));
- if (exprType(rexpr) != BOOLOID)
- elog(WARN,
- "right-hand side of OR is type '%s', not bool",
- tname(get_id_type(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",
- tname(get_id_type(exprType(rexpr))));
- expr->typeOid = BOOLOID;
- expr->opType = NOT_EXPR;
- expr->args = makeList(rexpr, -1);
- result = (Node *)expr;
- }
- break;
+ 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",
+ tname(get_id_type(exprType(lexpr))));
+ if (exprType(rexpr) != BOOLOID)
+ elog(WARN,
+ "right-hand side of AND is type '%s', not bool",
+ tname(get_id_type(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",
+ tname(get_id_type(exprType(lexpr))));
+ if (exprType(rexpr) != BOOLOID)
+ elog(WARN,
+ "right-hand side of OR is type '%s', not bool",
+ tname(get_id_type(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",
+ tname(get_id_type(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;
}
- 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;
+
+ return result;
}
-static Node *
-transformIdent(ParseState *pstate, Node *expr, int precedence)
+static 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;
+ 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
- result = column_result;
- }
+ {
+ if (relation_result)
+ result = relation_result;
+ else
+ result = column_result;
+ }
+
+ if (result == NULL)
+ elog(WARN, "attribute \"%s\" not found", ident->name);
- if(result == NULL)
- elog(WARN, "attribute \"%s\" not found", ident->name);
-
- return result;
+ return result;
}
/*****************************************************************************
@@ -787,201 +846,210 @@ transformIdent(ParseState *pstate, Node *expr, int precedence)
/*
* 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)
+ * 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)
*
*/
static void
-parseFromClause(ParseState *pstate, List *frmList)
+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;
+ List *fl;
- /*
- * 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,
- baserel->timeRange);
- }
+ 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,
+ baserel->timeRange);
+ }
}
/*
* makeRangeTable -
- * make a range table with the specified relation (optional) and the
- * from-clause.
+ * make a range table with the specified relation (optional) and the
+ * from-clause.
*/
static void
-makeRangeTable(ParseState *pstate, char *relname, List *frmList)
+makeRangeTable(ParseState * pstate, char *relname, List * frmList)
{
- RangeTblEntry *rte;
+ RangeTblEntry *rte;
- parseFromClause(pstate, frmList);
+ parseFromClause(pstate, frmList);
- if (relname == NULL)
- return;
-
- if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
- rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE, NULL);
- 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);
+ if (relname == NULL)
+ return;
+
+ if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
+ rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE, NULL);
+ 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 */
}
/*
- * exprType -
- * returns the Oid of the type of the expression. (Used for typechecking.)
+ * exprType -
+ * returns the Oid of the type of the expression. (Used for typechecking.)
*/
Oid
-exprType(Node *expr)
+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;
+ 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;
}
/*
* expandAllTables -
- * turns '*' (in the target list) into a list of attributes (of all
- * relations in the range table)
+ * turns '*' (in the target list) into a list of attributes (of all
+ * relations in the range table)
*/
-static List *
-expandAllTables(ParseState *pstate)
+static List *
+expandAllTables(ParseState * pstate)
{
- List *target= NIL;
- List *legit_rtable=NIL;
- List *rt, *rtable;
+ 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);
+ 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");
/*
- * 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;")
+ * go through the range table and make a list of range table entries
+ * which we will expand.
*/
- 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);
+ 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;
+ return target;
}
/*
* figureColname -
- * if the name of the resulting column is not specified in the target
- * list, we have to guess.
+ * if the name of the resulting column is not specified in the target
+ * list, we have to guess.
*
*/
-static char *
-figureColname(Node *expr, Node *resval)
+static 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;
+ 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;
}
- break;
- default:
- break;
- }
-
- return "?column?";
+
+ return "?column?";
}
/*****************************************************************************
@@ -992,452 +1060,531 @@ figureColname(Node *expr, Node *resval)
/*
* 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)
+ * 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)
*/
-static List *
-makeTargetNames(ParseState *pstate, List *cols)
+static 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-1);
- id->indirection = NIL;
- id->isRel = false;
- if (tl == NIL)
- cols = tl = lcons(id, NIL);
- else {
- lnext(tl) = lcons(id,NIL);
- tl = lnext(tl);
- }
+ 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 - 1);
+ 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)
- /* elog on failure */
- varattno(pstate->p_target_relation,((Ident *)lfirst(tl))->name);
+ else
+ foreach(tl, cols)
+ /* elog on failure */
+ varattno(pstate->p_target_relation, ((Ident *) lfirst(tl))->name);
- return cols;
+ return cols;
}
/*
* transformTargetList -
- * turns a list of ResTarget's into a list of TargetEntry's
+ * turns a list of ResTarget's into a list of TargetEntry's
*/
-static List *
-transformTargetList(ParseState *pstate, List *targetlist)
+static 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 = tlen(get_id_type(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))
+ 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 = tlen(get_id_type(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 = varattno(rd, res->name);
+ ndims = att_attnelems(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 = tlen(get_id_type(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,
- "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 = varattno(rd, res->name);
- ndims = att_attnelems(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);
- }
+ "internal error: do not know how to transform targetlist");
+ break;
}
- 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);
+ if (p_target == NIL)
+ {
+ p_target = tail_p_target = lcons(tent, NIL);
+ }
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);
+ {
+ lnext(tail_p_target) = lcons(tent, NIL);
+ tail_p_target = lnext(tail_p_target);
}
- result = (Node*)make_array_ref(result, att->indirection);
- }
- type_id = exprType(result);
- type_len = tlen(get_id_type(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);
}
- targetlist = lnext(targetlist);
- }
- return p_target;
+ return p_target;
}
/*
* make_targetlist_expr -
- * make a TargetEntry from an expression
+ * make a TargetEntry from an expression
*
* arrayRef is a list of transformed A_Indices
*/
static TargetEntry *
-make_targetlist_expr(ParseState *pstate,
- char *colname,
- Node *expr,
- List *arrayRef)
+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 = tlen(get_id_type(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 = varattno(rd,colname);
- attrisset = varisset(rd,colname);
- attrtype = att_typeid(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 = tlen(get_id_type(attrtype));
- }
+ 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 = tlen(get_id_type(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 = varattno(rd, colname);
+ attrisset = varisset(rd, colname);
+ attrtype = att_typeid(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 = tlen(get_id_type(attrtype));
+ }
#if 0
- if(Input_is_string && Typecast_ok){
- Datum val;
- if (type_id == typeid(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(typeid_get_retinfunc(attrtype),
- val,get_typelem(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, get_id_type(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;
+ if (Input_is_string && Typecast_ok)
+ {
+ Datum val;
+
+ if (type_id == typeid(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(typeid_get_retinfunc(attrtype),
+ val, get_typelem(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, get_id_type(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 = get_typelem(attrtype);
- expr = (Node*)parser_typecast2(expr,
- type_id,
- get_id_type(typelem),
- attrlen);
- } else
- expr = (Node*)parser_typecast2(expr,
- type_id,
- get_id_type(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,
- get_id_typname(attrtype),
- get_id_typname(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 = att_typeid(rd,resdomno);
- attrlen = tlen(get_id_type(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;
+ 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 = get_typelem(attrtype);
+
+ expr = (Node *) parser_typecast2(expr,
+ type_id,
+ get_id_type(typelem),
+ attrlen);
+ }
+ else
+ expr = (Node *) parser_typecast2(expr,
+ type_id,
+ get_id_type(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,
+ get_id_typname(attrtype),
+ get_id_typname(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 = att_typeid(rd, resdomno);
+ attrlen = tlen(get_id_type(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;
}
@@ -1449,26 +1596,27 @@ make_targetlist_expr(ParseState *pstate,
/*
* transformWhereClause -
- * transforms the qualification and make sure it is of type Boolean
+ * transforms the qualification and make sure it is of type Boolean
*
*/
-static Node *
-transformWhereClause(ParseState *pstate, Node *a_expr)
+static Node *
+transformWhereClause(ParseState * pstate, Node * a_expr)
{
- Node *qual;
-
- if (a_expr == NULL)
- return (Node *)NULL; /* no qualifiers */
-
- inWhereClause = true;
- qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
- inWhereClause = false;
- if (exprType(qual) != BOOLOID) {
- elog(WARN,
- "where clause must return type bool, not %s",
- tname(get_id_type(exprType(qual))));
- }
- return qual;
+ Node *qual;
+
+ if (a_expr == NULL)
+ return (Node *) NULL; /* no qualifiers */
+
+ inWhereClause = true;
+ qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
+ inWhereClause = false;
+ if (exprType(qual) != BOOLOID)
+ {
+ elog(WARN,
+ "where clause must return type bool, not %s",
+ tname(get_id_type(exprType(qual))));
+ }
+ return qual;
}
/*****************************************************************************
@@ -1478,203 +1626,237 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
*****************************************************************************/
/*
- * find_targetlist_entry -
- * returns the Resdom in the target list matching the specified varname
- * and range
+ * find_targetlist_entry -
+ * returns the Resdom in the target list matching the specified varname
+ * and range
*
*/
static TargetEntry *
-find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
+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;
+ 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);
+ 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;
- }
- }
+ 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;
+ return target_result;
}
-static Oid
+static 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;
+ Operator order_op;
+ Oid order_opid;
+
+ order_op = oper("<", restype, restype, false);
+ order_opid = oprid(order_op);
+
+ return order_opid;
}
/*
* transformGroupClause -
- * transform a Group By clause
+ * transform a Group By clause
*
*/
-static List *
-transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
+static 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 {
- lnext(gl) = lcons(grpcl, NIL);
- gl = lnext(gl);
+ 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
+ {
+ lnext(gl) = lcons(grpcl, NIL);
+ gl = lnext(gl);
+ }
+ grouplist = lnext(grouplist);
}
- grouplist = lnext(grouplist);
- }
- return glist;
+ return glist;
}
/*
* transformSortClause -
- * transform an Order By clause
+ * transform an Order By clause
*
*/
-static List *
-transformSortClause(ParseState *pstate,
- List *orderlist, List *targetlist,
- char* uniqueFlag)
+static List *
+transformSortClause(ParseState * pstate,
+ List * orderlist, List * targetlist,
+ char *uniqueFlag)
{
- List *sortlist = NIL;
- List *s = NIL, *i;
-
- 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 {
- lnext(s) = lcons(sortcl, NIL);
- s = lnext(s);
+ List *sortlist = NIL;
+ List *s = NIL,
+ *i;
+
+ 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
+ {
+ lnext(s) = lcons(sortcl, NIL);
+ s = lnext(s);
+ }
+ orderlist = lnext(orderlist);
}
- orderlist = lnext(orderlist);
- }
-
- if (uniqueFlag) {
- 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);
- }
+
+ if (uniqueFlag)
+ {
+ 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;
+ return sortlist;
}
/*
@@ -1682,578 +1864,645 @@ transformSortClause(ParseState *pstate,
** Given a nested dot expression (i.e. (relation func ... attr), build up
** a tree with of Iter and Func nodes.
*/
-static Node*
-handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
+static 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);
+ 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);
}
/*
** make_arguments --
- ** Given the number and types of arguments to a function, and the
+ ** Given the number and types of arguments to a function, and the
** actual arguments and argument types, do the necessary typecasting.
*/
static void
make_arguments(int nargs,
- List *fargs,
- Oid *input_typeids,
- Oid *function_typeids)
+ List * fargs,
+ Oid * input_typeids,
+ Oid * function_typeids)
{
- /*
- * there are two ways an input typeid can differ from a function typeid :
- * either the input type inherits the function type, so no typecasting is
- * necessary, or the input type can be typecast into the function type.
- * right now, we only typecast unknowns, and that is all we check for.
- */
-
- List *current_fargs;
- int i;
-
- for (i=0, current_fargs = fargs;
- i<nargs;
- i++, current_fargs = lnext(current_fargs)) {
-
- if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid) {
- lfirst(current_fargs) =
- parser_typecast2(lfirst(current_fargs),
- input_typeids[i],
- get_id_type(function_typeids[i]),
- -1);
+
+ /*
+ * there are two ways an input typeid can differ from a function
+ * typeid : either the input type inherits the function type, so no
+ * typecasting is necessary, or the input type can be typecast into
+ * the function type. right now, we only typecast unknowns, and that
+ * is all we check for.
+ */
+
+ List *current_fargs;
+ int i;
+
+ for (i = 0, current_fargs = fargs;
+ i < nargs;
+ i++, current_fargs = lnext(current_fargs))
+ {
+
+ if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
+ {
+ lfirst(current_fargs) =
+ parser_typecast2(lfirst(current_fargs),
+ input_typeids[i],
+ get_id_type(function_typeids[i]),
+ -1);
+ }
}
- }
}
/*
** setup_tlist --
- ** Build a tlist that says which attribute to project to.
- ** This routine is called by ParseFunc() to set up a target list
- ** on a tuple parameter or return value. Due to a bug in 4.0,
- ** it's not possible to refer to system attributes in this case.
+ ** Build a tlist that says which attribute to project to.
+ ** This routine is called by ParseFunc() to set up a target list
+ ** on a tuple parameter or return value. Due to a bug in 4.0,
+ ** it's not possible to refer to system attributes in this case.
*/
-static List *
+static List *
setup_tlist(char *attname, Oid relid)
{
- TargetEntry *tle;
- Resdom *resnode;
- Var *varnode;
- Oid typeid;
- int attno;
-
- attno = get_attnum(relid, attname);
- if (attno < 0)
- elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
-
- typeid = find_atttype(relid, attname);
- resnode = makeResdom(1,
- typeid,
- tlen(get_id_type(typeid)),
- get_attname(relid, attno),
- 0,
- (Oid)0,
- 0);
- varnode = makeVar(-1, attno, typeid, -1, attno);
-
- tle = makeNode(TargetEntry);
- tle->resdom = resnode;
- tle->expr = (Node*)varnode;
- return (lcons(tle, NIL));
+ TargetEntry *tle;
+ Resdom *resnode;
+ Var *varnode;
+ Oid typeid;
+ int attno;
+
+ attno = get_attnum(relid, attname);
+ if (attno < 0)
+ elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
+
+ typeid = find_atttype(relid, attname);
+ resnode = makeResdom(1,
+ typeid,
+ tlen(get_id_type(typeid)),
+ get_attname(relid, attno),
+ 0,
+ (Oid) 0,
+ 0);
+ varnode = makeVar(-1, attno, typeid, -1, attno);
+
+ tle = makeNode(TargetEntry);
+ tle->resdom = resnode;
+ tle->expr = (Node *) varnode;
+ return (lcons(tle, NIL));
}
/*
** setup_base_tlist --
- ** Build a tlist that extracts a base type from the tuple
- ** returned by the executor.
+ ** Build a tlist that extracts a base type from the tuple
+ ** returned by the executor.
*/
-static List *
+static List *
setup_base_tlist(Oid typeid)
{
- TargetEntry *tle;
- Resdom *resnode;
- Var *varnode;
-
- resnode = makeResdom(1,
- typeid,
- tlen(get_id_type(typeid)),
- "<noname>",
- 0,
- (Oid)0,
- 0);
- varnode = makeVar(-1, 1, typeid, -1, 1);
- tle = makeNode(TargetEntry);
- tle->resdom = resnode;
- tle->expr = (Node*)varnode;
-
- return (lcons(tle, NIL));
+ TargetEntry *tle;
+ Resdom *resnode;
+ Var *varnode;
+
+ resnode = makeResdom(1,
+ typeid,
+ tlen(get_id_type(typeid)),
+ "<noname>",
+ 0,
+ (Oid) 0,
+ 0);
+ varnode = makeVar(-1, 1, typeid, -1, 1);
+ tle = makeNode(TargetEntry);
+ tle->resdom = resnode;
+ tle->expr = (Node *) varnode;
+
+ return (lcons(tle, NIL));
}
/*
* ParseComplexProjection -
- * handles function calls with a single argument that is of complex type.
- * This routine returns NULL if it can't handle the projection (eg. sets).
+ * handles function calls with a single argument that is of complex type.
+ * This routine returns NULL if it can't handle the projection (eg. sets).
*/
-static Node *
-ParseComplexProjection(ParseState *pstate,
- char *funcname,
- Node *first_arg,
- bool *attisset)
+static Node *
+ParseComplexProjection(ParseState * pstate,
+ char *funcname,
+ Node * first_arg,
+ bool * attisset)
{
- Oid argtype;
- Oid argrelid;
- Name relname;
- Relation rd;
- Oid relid;
- int attnum;
-
- switch (nodeTag(first_arg)) {
- case T_Iter:
+ Oid argtype;
+ Oid argrelid;
+ Name relname;
+ Relation rd;
+ Oid relid;
+ int attnum;
+
+ switch (nodeTag(first_arg))
{
- Func *func;
- Iter *iter;
-
- iter = (Iter*)first_arg;
- func = (Func *)((Expr*)iter->iterexpr)->oper;
- argtype = funcid_get_rettype(func->funcid);
- argrelid = typeid_get_relid(argtype);
- if (argrelid &&
- ((attnum = get_attnum(argrelid, funcname))
- != InvalidAttrNumber)) {
-
- /* the argument is a function returning a tuple, so funcname
- may be a projection */
-
- /* add a tlist to the func node and return the Iter */
- rd = heap_openr(tname(get_id_type(argtype)));
- if (RelationIsValid(rd)) {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
+ case T_Iter:
+ {
+ Func *func;
+ Iter *iter;
+
+ iter = (Iter *) first_arg;
+ func = (Func *) ((Expr *) iter->iterexpr)->oper;
+ argtype = funcid_get_rettype(func->funcid);
+ argrelid = typeid_get_relid(argtype);
+ if (argrelid &&
+ ((attnum = get_attnum(argrelid, funcname))
+ != InvalidAttrNumber))
+ {
+
+ /*
+ * the argument is a function returning a tuple, so
+ * funcname may be a projection
+ */
+
+ /* add a tlist to the func node and return the Iter */
+ rd = heap_openr(tname(get_id_type(argtype)));
+ if (RelationIsValid(rd))
+ {
+ relid = RelationGetRelationId(rd);
+ relname = RelationGetRelationName(rd);
+ heap_close(rd);
+ }
+ if (RelationIsValid(rd))
+ {
+ func->func_tlist =
+ setup_tlist(funcname, argrelid);
+ iter->itertype = att_typeid(rd, attnum);
+ return ((Node *) iter);
+ }
+ else
+ {
+ elog(WARN,
+ "Function %s has bad returntype %d",
+ funcname, argtype);
+ }
+ }
+ else
+ {
+ /* drop through */
+ ;
+ }
+ break;
}
- if (RelationIsValid(rd)) {
- func->func_tlist =
- setup_tlist(funcname, argrelid);
- iter->itertype = att_typeid(rd,attnum);
- return ((Node*)iter);
- }else {
- elog(WARN,
- "Function %s has bad returntype %d",
- funcname, argtype);
+ case T_Var:
+ {
+
+ /*
+ * The argument is a set, so this is either a projection or a
+ * function call on this set.
+ */
+ *attisset = true;
+ break;
}
- }else {
- /* drop through */
- ;
- }
- break;
+ case T_Expr:
+ {
+ Expr *expr = (Expr *) first_arg;
+ Func *funcnode;
+
+ if (expr->opType != FUNC_EXPR)
+ break;
+
+ funcnode = (Func *) expr->oper;
+ argtype = funcid_get_rettype(funcnode->funcid);
+ argrelid = typeid_get_relid(argtype);
+
+ /*
+ * the argument is a function returning a tuple, so funcname
+ * may be a projection
+ */
+ if (argrelid &&
+ (attnum = get_attnum(argrelid, funcname))
+ != InvalidAttrNumber)
+ {
+
+ /* add a tlist to the func node */
+ rd = heap_openr(tname(get_id_type(argtype)));
+ if (RelationIsValid(rd))
+ {
+ relid = RelationGetRelationId(rd);
+ relname = RelationGetRelationName(rd);
+ heap_close(rd);
+ }
+ if (RelationIsValid(rd))
+ {
+ Expr *newexpr;
+
+ funcnode->func_tlist =
+ setup_tlist(funcname, argrelid);
+ funcnode->functype = att_typeid(rd, attnum);
+
+ newexpr = makeNode(Expr);
+ newexpr->typeOid = funcnode->functype;
+ newexpr->opType = FUNC_EXPR;
+ newexpr->oper = (Node *) funcnode;
+ newexpr->args = lcons(first_arg, NIL);
+
+ return ((Node *) newexpr);
+ }
+
+ }
+
+ elog(WARN, "Function %s has bad returntype %d",
+ funcname, argtype);
+ break;
+ }
+ case T_Param:
+ {
+ Param *param = (Param *) first_arg;
+
+ /*
+ * If the Param is a complex type, this could be a projection
+ */
+ rd = heap_openr(tname(get_id_type(param->paramtype)));
+ if (RelationIsValid(rd))
+ {
+ relid = RelationGetRelationId(rd);
+ relname = RelationGetRelationName(rd);
+ heap_close(rd);
+ }
+ if (RelationIsValid(rd) &&
+ (attnum = get_attnum(relid, funcname))
+ != InvalidAttrNumber)
+ {
+
+ param->paramtype = att_typeid(rd, attnum);
+ param->param_tlist = setup_tlist(funcname, relid);
+ return ((Node *) param);
+ }
+ break;
+ }
+ default:
+ break;
}
- case T_Var:
+
+ return NULL;
+}
+
+static Node *
+ParseFunc(ParseState * pstate, char *funcname, List * fargs, int *curr_resno)
+{
+ Oid rettype = (Oid) 0;
+ Oid argrelid = (Oid) 0;
+ Oid funcid = (Oid) 0;
+ List *i = NIL;
+ Node *first_arg = NULL;
+ char *relname = NULL;
+ char *refname = NULL;
+ Relation rd;
+ Oid relid;
+ int nargs;
+ Func *funcnode;
+ Oid oid_array[8];
+ Oid *true_oid_array;
+ Node *retval;
+ bool retset;
+ bool exists;
+ bool attisset = false;
+ Oid toid = (Oid) 0;
+ Expr *expr;
+
+ if (fargs)
{
- /*
- * The argument is a set, so this is either a projection
- * or a function call on this set.
- */
- *attisset = true;
- break;
+ first_arg = lfirst(fargs);
+ if (first_arg == NULL)
+ elog(WARN, "function %s does not allow NULL input", funcname);
}
- case T_Expr:
+
+ /*
+ * * check for projection methods: if function takes one argument, and *
+ * that argument is a relation, param, or PQ function returning a
+ * complex * type, then the function could be a projection.
+ */
+ if (length(fargs) == 1)
{
- Expr *expr = (Expr*)first_arg;
- Func *funcnode;
- if (expr->opType != FUNC_EXPR)
- break;
+ if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
+ {
+ RangeTblEntry *rte;
+ Ident *ident = (Ident *) first_arg;
+
+ /*
+ * first arg is a relation. This could be a projection.
+ */
+ refname = ident->name;
+
+ rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+ if (rte == NULL)
+ rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
+
+ relname = rte->relname;
+ relid = rte->relid;
+
+ /*
+ * If the attr isn't a set, just make a var for it. If it is
+ * a set, treat it like a function and drop through.
+ */
+ if (get_attnum(relid, funcname) != InvalidAttrNumber)
+ {
+ Oid dummyTypeId;
+
+ return
+ ((Node *) make_var(pstate,
+ refname,
+ funcname,
+ &dummyTypeId));
+ }
+ else
+ {
+ /* drop through - attr is a set */
+ ;
+ }
+ }
+ else if (ISCOMPLEX(exprType(first_arg)))
+ {
+
+ /*
+ * Attempt to handle projection of a complex argument. If
+ * ParseComplexProjection can't handle the projection, we have
+ * to keep going.
+ */
+ retval = ParseComplexProjection(pstate,
+ funcname,
+ first_arg,
+ &attisset);
+ if (attisset)
+ {
+ toid = exprType(first_arg);
+ rd = heap_openr(tname(get_id_type(toid)));
+ if (RelationIsValid(rd))
+ {
+ relname = RelationGetRelationName(rd)->data;
+ heap_close(rd);
+ }
+ else
+ elog(WARN,
+ "Type %s is not a relation type",
+ tname(get_id_type(toid)));
+ argrelid = typeid_get_relid(toid);
+
+ /*
+ * A projection contains either an attribute name or the
+ * "*".
+ */
+ if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
+ && strcmp(funcname, "*"))
+ {
+ elog(WARN, "Functions on sets are not yet supported");
+ }
+ }
+
+ if (retval)
+ return retval;
+ }
+ else
+ {
+
+ /*
+ * Parsing aggregates.
+ */
+ Oid basetype;
+
+ /*
+ * the aggregate count is a special case, ignore its base
+ * type. Treat it as zero
+ */
+ if (strcmp(funcname, "count") == 0)
+ basetype = 0;
+ else
+ basetype = exprType(lfirst(fargs));
+ if (SearchSysCacheTuple(AGGNAME,
+ PointerGetDatum(funcname),
+ ObjectIdGetDatum(basetype),
+ 0, 0))
+ {
+ Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
+
+ AddAggToParseState(pstate, aggreg);
+ return (Node *) aggreg;
+ }
+ }
+ }
- funcnode= (Func *) expr->oper;
- argtype = funcid_get_rettype(funcnode->funcid);
- argrelid = typeid_get_relid(argtype);
- /*
- * the argument is a function returning a tuple, so funcname
- * may be a projection
- */
- if (argrelid &&
- (attnum = get_attnum(argrelid, funcname))
- != InvalidAttrNumber) {
-
- /* add a tlist to the func node */
- rd = heap_openr(tname(get_id_type(argtype)));
- if (RelationIsValid(rd)) {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
+
+ /*
+ * * If we dropped through to here it's really a function (or a set,
+ * which * is implemented as a function.) * extract arg type info and
+ * transform relation name arguments into * varnodes of the
+ * appropriate form.
+ */
+ memset(&oid_array[0], 0, 8 * sizeof(Oid));
+
+ nargs = 0;
+ foreach(i, fargs)
+ {
+ int vnum;
+ RangeTblEntry *rte;
+ Node *pair = lfirst(i);
+
+ if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
+ {
+
+ /*
+ * a relation
+ */
+ refname = ((Ident *) pair)->name;
+
+ rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+ if (rte == NULL)
+ rte = addRangeTableEntry(pstate, refname, refname,
+ FALSE, FALSE, NULL);
+ relname = rte->relname;
+
+ vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
+
+ /*
+ * for func(relname), the param to the function is the tuple
+ * under consideration. we build a special VarNode to reflect
+ * this -- it has varno set to the correct range table entry,
+ * but has varattno == 0 to signal that the whole tuple is the
+ * argument.
+ */
+ toid = typeid(type(relname));
+ /* replace it in the arg list */
+ lfirst(fargs) =
+ makeVar(vnum, 0, toid, vnum, 0);
}
- if (RelationIsValid(rd)) {
- Expr *newexpr;
-
- funcnode->func_tlist =
- setup_tlist(funcname, argrelid);
- funcnode->functype = att_typeid(rd,attnum);
-
- newexpr = makeNode(Expr);
- newexpr->typeOid = funcnode->functype;
- newexpr->opType = FUNC_EXPR;
- newexpr->oper = (Node *)funcnode;
- newexpr->args = lcons(first_arg, NIL);
-
- return ((Node*)newexpr);
+ else if (!attisset)
+ { /* set functions don't have parameters */
+
+ /*
+ * any functiona args which are typed "unknown", but aren't
+ * constants, we don't know what to do with, because we can't
+ * cast them - jolly
+ */
+ if (exprType(pair) == UNKNOWNOID &&
+ !IsA(pair, Const))
+ {
+ elog(WARN, "ParseFunc: no function named %s that takes in an unknown type as argument #%d", funcname, nargs);
+ }
+ else
+ toid = exprType(pair);
}
-
- }
- elog(WARN, "Function %s has bad returntype %d",
- funcname, argtype);
- break;
+ oid_array[nargs++] = toid;
+ }
+
+ /*
+ * func_get_detail looks up the function in the catalogs, does
+ * disambiguation for polymorphic functions, handles inheritance, and
+ * returns the funcid and type and set or singleton status of the
+ * function's return value. it also returns the true argument types
+ * to the function. if func_get_detail returns true, the function
+ * exists. otherwise, there was an error.
+ */
+ if (attisset)
+ { /* we know all of these fields already */
+
+ /*
+ * We create a funcnode with a placeholder function SetEval.
+ * SetEval() never actually gets executed. When the function
+ * evaluation routines see it, they use the funcid projected out
+ * from the relation as the actual function to call. Example:
+ * retrieve (emp.mgr.name) The plan for this will scan the emp
+ * relation, projecting out the mgr attribute, which is a funcid.
+ * This function is then called (instead of SetEval) and "name" is
+ * projected from its result.
+ */
+ funcid = SetEvalRegProcedure;
+ rettype = toid;
+ retset = true;
+ true_oid_array = oid_array;
+ exists = true;
}
- case T_Param:
+ else
{
- Param *param = (Param*)first_arg;
- /*
- * If the Param is a complex type, this could be a projection
- */
- rd = heap_openr(tname(get_id_type(param->paramtype)));
- if (RelationIsValid(rd)) {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
- }
- if (RelationIsValid(rd) &&
- (attnum = get_attnum(relid, funcname))
- != InvalidAttrNumber) {
-
- param->paramtype = att_typeid(rd, attnum);
- param->param_tlist = setup_tlist(funcname, relid);
- return ((Node*)param);
- }
- break;
+ exists = func_get_detail(funcname, nargs, oid_array, &funcid,
+ &rettype, &retset, &true_oid_array);
}
- default:
- break;
- }
- return NULL;
-}
-
-static Node *
-ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
-{
- Oid rettype = (Oid)0;
- Oid argrelid = (Oid)0;
- Oid funcid = (Oid)0;
- List *i = NIL;
- Node *first_arg= NULL;
- char *relname = NULL;
- char *refname = NULL;
- Relation rd;
- Oid relid;
- int nargs;
- Func *funcnode;
- Oid oid_array[8];
- Oid *true_oid_array;
- Node *retval;
- bool retset;
- bool exists;
- bool attisset = false;
- Oid toid = (Oid)0;
- Expr *expr;
-
- if (fargs) {
- first_arg = lfirst(fargs);
- if (first_arg == NULL)
- elog (WARN,"function %s does not allow NULL input",funcname);
- }
-
- /*
- ** check for projection methods: if function takes one argument, and
- ** that argument is a relation, param, or PQ function returning a complex
- ** type, then the function could be a projection.
- */
- if (length(fargs) == 1) {
-
- if (nodeTag(first_arg)==T_Ident && ((Ident*)first_arg)->isRel) {
- RangeTblEntry *rte;
- Ident *ident = (Ident*)first_arg;
-
- /*
- * first arg is a relation. This could be a projection.
- */
- refname = ident->name;
-
- rte = refnameRangeTableEntry(pstate->p_rtable, refname);
- if (rte == NULL)
- rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE,NULL);
-
- relname = rte->relname;
- relid = rte->relid;
-
- /* If the attr isn't a set, just make a var for it. If
- * it is a set, treat it like a function and drop through.
- */
- if (get_attnum(relid, funcname) != InvalidAttrNumber) {
- Oid dummyTypeId;
-
- return
- ((Node*)make_var(pstate,
- refname,
- funcname,
- &dummyTypeId));
- } else {
- /* drop through - attr is a set */
- ;
- }
- } else if (ISCOMPLEX(exprType(first_arg))) {
- /*
- * Attempt to handle projection of a complex argument. If
- * ParseComplexProjection can't handle the projection, we
- * have to keep going.
- */
- retval = ParseComplexProjection(pstate,
- funcname,
- first_arg,
- &attisset);
- if (attisset) {
- toid = exprType(first_arg);
- rd = heap_openr(tname(get_id_type(toid)));
- if (RelationIsValid(rd)) {
- relname = RelationGetRelationName(rd)->data;
- heap_close(rd);
- } else
- elog(WARN,
- "Type %s is not a relation type",
- tname(get_id_type(toid)));
- argrelid = typeid_get_relid(toid);
- /* A projection contains either an attribute name or the
- * "*".
- */
- if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
- && strcmp(funcname, "*")) {
- elog(WARN, "Functions on sets are not yet supported");
+ if (!exists)
+ elog(WARN, "no such attribute or function %s", funcname);
+
+ /* got it */
+ funcnode = makeNode(Func);
+ funcnode->funcid = funcid;
+ funcnode->functype = rettype;
+ funcnode->funcisindex = false;
+ funcnode->funcsize = 0;
+ funcnode->func_fcache = NULL;
+ funcnode->func_tlist = NIL;
+ funcnode->func_planlist = NIL;
+
+ /* perform the necessary typecasting */
+ make_arguments(nargs, fargs, oid_array, true_oid_array);
+
+ /*
+ * for functions returning base types, we want to project out the
+ * return value. set up a target list to do that. the executor will
+ * ignore these for c functions, and do the right thing for postquel
+ * functions.
+ */
+
+ if (typeid_get_relid(rettype) == InvalidOid)
+ funcnode->func_tlist = setup_base_tlist(rettype);
+
+ /*
+ * For sets, we want to make a targetlist to project out this
+ * attribute of the set tuples.
+ */
+ if (attisset)
+ {
+ if (!strcmp(funcname, "*"))
+ {
+ funcnode->func_tlist =
+ expandAll(pstate, relname, refname, curr_resno);
+ }
+ else
+ {
+ funcnode->func_tlist = setup_tlist(funcname, argrelid);
+ rettype = find_atttype(argrelid, funcname);
}
- }
-
- if (retval)
- return retval;
- } else {
- /*
- * Parsing aggregates.
- */
- Oid basetype;
- /* the aggregate count is a special case,
- ignore its base type. Treat it as zero */
- if (strcmp(funcname, "count") == 0)
- basetype = 0;
- else
- basetype = exprType(lfirst(fargs));
- if (SearchSysCacheTuple(AGGNAME,
- PointerGetDatum(funcname),
- ObjectIdGetDatum(basetype),
- 0, 0)) {
- Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
-
- AddAggToParseState(pstate, aggreg);
- return (Node*)aggreg;
- }
}
- }
-
-
- /*
- ** If we dropped through to here it's really a function (or a set, which
- ** is implemented as a function.)
- ** extract arg type info and transform relation name arguments into
- ** varnodes of the appropriate form.
- */
- memset(&oid_array[0], 0, 8 * sizeof(Oid));
-
- nargs=0;
- foreach ( i , fargs ) {
- int vnum;
- RangeTblEntry *rte;
- Node *pair = lfirst(i);
-
- if (nodeTag(pair)==T_Ident && ((Ident*)pair)->isRel) {
- /*
- * a relation
- */
- refname = ((Ident*)pair)->name;
-
- rte = refnameRangeTableEntry(pstate->p_rtable, refname);
- if (rte == NULL)
- rte = addRangeTableEntry(pstate, refname, refname,
- FALSE, FALSE, NULL);
- relname = rte->relname;
-
- vnum = refnameRangeTablePosn (pstate->p_rtable, rte->refname);
-
- /*
- * for func(relname), the param to the function
- * is the tuple under consideration. we build a special
- * VarNode to reflect this -- it has varno set to the
- * correct range table entry, but has varattno == 0 to
- * signal that the whole tuple is the argument.
- */
- toid = typeid(type(relname));
- /* replace it in the arg list */
- lfirst(fargs) =
- makeVar(vnum, 0, toid, vnum, 0);
- }else if (!attisset) { /* set functions don't have parameters */
-
- /* any functiona args which are typed "unknown", but aren't
- constants, we don't know what to do with, because we
- can't cast them - jolly*/
- if (exprType(pair) == UNKNOWNOID &&
- !IsA(pair, Const))
- {
- elog(WARN, "ParseFunc: no function named %s that takes in an unknown type as argument #%d", funcname, nargs);
- }
- else
- toid = exprType(pair);
+
+ /*
+ * Sequence handling.
+ */
+ if (funcid == SeqNextValueRegProcedure ||
+ funcid == SeqCurrValueRegProcedure)
+ {
+ Const *seq;
+ char *seqrel;
+ int32 aclcheck_result = -1;
+
+ Assert(length(fargs) == 1);
+ seq = (Const *) lfirst(fargs);
+ if (!IsA((Node *) seq, Const))
+ elog(WARN, "%s: only constant sequence names are acceptable", funcname);
+ seqrel = textout((struct varlena *) (seq->constvalue));
+
+ if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
+ ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)))
+ != ACLCHECK_OK)
+ elog(WARN, "%s.%s: %s",
+ seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
+
+ pfree(seqrel);
+
+ if (funcid == SeqNextValueRegProcedure && inWhereClause)
+ elog(WARN, "nextval of a sequence in WHERE disallowed");
}
-
- oid_array[nargs++] = toid;
- }
-
- /*
- * func_get_detail looks up the function in the catalogs, does
- * disambiguation for polymorphic functions, handles inheritance,
- * and returns the funcid and type and set or singleton status of
- * the function's return value. it also returns the true argument
- * types to the function. if func_get_detail returns true,
- * the function exists. otherwise, there was an error.
- */
- if (attisset) { /* we know all of these fields already */
- /* We create a funcnode with a placeholder function SetEval.
- * SetEval() never actually gets executed. When the function
- * evaluation routines see it, they use the funcid projected
- * out from the relation as the actual function to call.
- * Example: retrieve (emp.mgr.name)
- * The plan for this will scan the emp relation, projecting
- * out the mgr attribute, which is a funcid. This function
- * is then called (instead of SetEval) and "name" is projected
- * from its result.
+
+ expr = makeNode(Expr);
+ expr->typeOid = rettype;
+ expr->opType = FUNC_EXPR;
+ expr->oper = (Node *) funcnode;
+ expr->args = fargs;
+ retval = (Node *) expr;
+
+ /*
+ * if the function returns a set of values, then we need to iterate
+ * over all the returned values in the executor, so we stick an iter
+ * node here. if it returns a singleton, then we don't need the iter
+ * node.
*/
- funcid = SetEvalRegProcedure;
- rettype = toid;
- retset = true;
- true_oid_array = oid_array;
- exists = true;
- } else {
- exists = func_get_detail(funcname, nargs, oid_array, &funcid,
- &rettype, &retset, &true_oid_array);
- }
-
- if (!exists)
- elog(WARN, "no such attribute or function %s", funcname);
-
- /* got it */
- funcnode = makeNode(Func);
- funcnode->funcid = funcid;
- funcnode->functype = rettype;
- funcnode->funcisindex = false;
- funcnode->funcsize = 0;
- funcnode->func_fcache = NULL;
- funcnode->func_tlist = NIL;
- funcnode->func_planlist = NIL;
-
- /* perform the necessary typecasting */
- make_arguments(nargs, fargs, oid_array, true_oid_array);
-
- /*
- * for functions returning base types, we want to project out the
- * return value. set up a target list to do that. the executor
- * will ignore these for c functions, and do the right thing for
- * postquel functions.
- */
-
- if (typeid_get_relid(rettype) == InvalidOid)
- funcnode->func_tlist = setup_base_tlist(rettype);
-
- /* For sets, we want to make a targetlist to project out this
- * attribute of the set tuples.
- */
- if (attisset) {
- if (!strcmp(funcname, "*")) {
- funcnode->func_tlist =
- expandAll(pstate, relname, refname, curr_resno);
- } else {
- funcnode->func_tlist = setup_tlist(funcname,argrelid);
- rettype = find_atttype(argrelid, funcname);
+
+ if (retset)
+ {
+ Iter *iter = makeNode(Iter);
+
+ iter->itertype = rettype;
+ iter->iterexpr = retval;
+ retval = (Node *) iter;
}
- }
-
- /*
- * Sequence handling.
- */
- if ( funcid == SeqNextValueRegProcedure ||
- funcid == SeqCurrValueRegProcedure )
- {
- Const *seq;
- char *seqrel;
- int32 aclcheck_result = -1;
-
- Assert ( length(fargs) == 1 );
- seq = (Const*)lfirst(fargs);
- if ( ! IsA ((Node*)seq, Const) )
- elog (WARN, "%s: only constant sequence names are acceptable", funcname);
- seqrel = textout ((struct varlena *) (seq->constvalue));
-
- if ( ( aclcheck_result = pg_aclcheck (seqrel, GetPgUserName(),
- ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)) )
- != ACLCHECK_OK )
- elog (WARN, "%s.%s: %s",
- seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
-
- pfree (seqrel);
-
- if ( funcid == SeqNextValueRegProcedure && inWhereClause )
- elog (WARN, "nextval of a sequence in WHERE disallowed");
- }
-
- expr = makeNode(Expr);
- expr->typeOid = rettype;
- expr->opType = FUNC_EXPR;
- expr->oper = (Node *)funcnode;
- expr->args = fargs;
- retval = (Node*)expr;
-
- /*
- * if the function returns a set of values, then we need to iterate
- * over all the returned values in the executor, so we stick an
- * iter node here. if it returns a singleton, then we don't need
- * the iter node.
- */
-
- if (retset) {
- Iter *iter = makeNode(Iter);
- iter->itertype = rettype;
- iter->iterexpr = retval;
- retval = (Node*)iter;
- }
-
- return(retval);
+
+ return (retval);
}
/*****************************************************************************
@@ -2262,232 +2511,243 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
/*
* AddAggToParseState -
- * add the aggregate to the list of unique aggregates in pstate.
+ * add the aggregate to the list of unique aggregates in pstate.
*
* SIDE EFFECT: aggno in target list entry will be modified
*/
static void
-AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
+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;
+ 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++;
}
- i++;
- }
-
- /* not found, new aggregate */
- aggreg->aggno = i;
- pstate->p_numAgg++;
- pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
- return;
+
+ /* 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.
+ * fill in qry_aggs from pstate. Also checks to make sure that aggregates
+ * are used in the proper place.
*/
static 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);
+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.
+ * Recursively find aggreg nodes from a clause.
+ *
+ * Returns true if any aggregate found.
*/
-static bool
-contain_agg_clause(Node *clause)
+static 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)))
+ if (clause == NULL)
+ return FALSE;
+ else if (IsA(clause, Aggreg))
return TRUE;
- return FALSE;
- } else if (is_funcclause (clause)) {
- List *temp;
+ 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 (IsA(clause,ArrayRef)) {
- 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, ((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)));
+ 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;
+ return FALSE;
}
/*
* exprIsAggOrGroupCol -
- * returns true if the expression does not contain non-group columns.
+ * returns true if the expression does not contain non-group columns.
*/
-static bool
-exprIsAggOrGroupCol(Node *expr, List *groupClause)
+static 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) )
+ List *gl;
+
+ if (expr == NULL || IsA(expr, Const) ||
+ IsA(expr, Param) || IsA(expr, Aggreg))
return TRUE;
- }
- if ( IsA (expr, Expr) )
- {
- List *temp;
+ foreach(gl, groupClause)
+ {
+ GroupClause *grpcl = lfirst(gl);
- foreach (temp, ((Expr*)expr)->args)
- if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
- return FALSE;
- return TRUE;
- }
+ 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;
+ return FALSE;
}
/*
* tleIsAggOrGroupCol -
- * returns true if the TargetEntry is Agg or GroupCol.
+ * returns true if the TargetEntry is Agg or GroupCol.
*/
-static bool
-tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
+static 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;
+ 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, Aggreg))
+ return TRUE;
- if ( IsA (expr, Expr) )
- {
- List *temp;
+ if (IsA(expr, Expr))
+ {
+ List *temp;
- foreach (temp, ((Expr*)expr)->args)
- if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
- return FALSE;
- return TRUE;
- }
+ foreach(temp, ((Expr *) expr)->args)
+ if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+ return FALSE;
+ return TRUE;
+ }
- return FALSE;
+ 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.
+ * 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.
*/
static void
-parseCheckAggregates(ParseState *pstate, Query *qry)
+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.
- */
+ 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;
+ * 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;
}
diff --git a/src/backend/parser/catalog_utils.c b/src/backend/parser/catalog_utils.c
index 043c2865060..41e6fffac9b 100644
--- a/src/backend/parser/catalog_utils.c
+++ b/src/backend/parser/catalog_utils.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.22 1997/08/22 00:02:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.23 1997/09/07 04:44:42 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,83 +48,110 @@
#include "utils/lsyscache.h"
#include "storage/lmgr.h"
-#include "port-protos.h" /* strdup() */
-
-struct {
- char *field;
- int code;
-} special_attr[] = {
- { "ctid", SelfItemPointerAttributeNumber },
- { "oid", ObjectIdAttributeNumber },
- { "xmin", MinTransactionIdAttributeNumber },
- { "cmin", MinCommandIdAttributeNumber },
- { "xmax", MaxTransactionIdAttributeNumber },
- { "cmax", MaxCommandIdAttributeNumber },
- { "chain", ChainItemPointerAttributeNumber },
- { "anchor", AnchorItemPointerAttributeNumber },
- { "tmin", MinAbsoluteTimeAttributeNumber },
- { "tmax", MaxAbsoluteTimeAttributeNumber },
- { "vtype", VersionTypeAttributeNumber }
+#include "port-protos.h" /* strdup() */
+
+struct
+{
+ char *field;
+ int code;
+} special_attr[] =
+
+{
+ {
+ "ctid", SelfItemPointerAttributeNumber
+ },
+ {
+ "oid", ObjectIdAttributeNumber
+ },
+ {
+ "xmin", MinTransactionIdAttributeNumber
+ },
+ {
+ "cmin", MinCommandIdAttributeNumber
+ },
+ {
+ "xmax", MaxTransactionIdAttributeNumber
+ },
+ {
+ "cmax", MaxCommandIdAttributeNumber
+ },
+ {
+ "chain", ChainItemPointerAttributeNumber
+ },
+ {
+ "anchor", AnchorItemPointerAttributeNumber
+ },
+ {
+ "tmin", MinAbsoluteTimeAttributeNumber
+ },
+ {
+ "tmax", MaxAbsoluteTimeAttributeNumber
+ },
+ {
+ "vtype", VersionTypeAttributeNumber
+ }
};
#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
-
-static char *attnum_type[SPECIALS] = {
- "tid",
- "oid",
- "xid",
- "cid",
- "xid",
- "cid",
- "tid",
- "tid",
- "abstime",
- "abstime",
- "char"
- };
-
-#define MAXFARGS 8 /* max # args to a c or postquel function */
+
+static char *attnum_type[SPECIALS] = {
+ "tid",
+ "oid",
+ "xid",
+ "cid",
+ "xid",
+ "cid",
+ "tid",
+ "tid",
+ "abstime",
+ "abstime",
+ "char"
+};
+
+#define MAXFARGS 8 /* max # args to a c or postquel function */
/*
- * This structure is used to explore the inheritance hierarchy above
- * nodes in the type tree in order to disambiguate among polymorphic
- * functions.
+ * 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;
+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.
+ * 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;
-
-static Oid **argtype_inherit(int nargs, Oid *oid_array);
-static Oid **genxprod(InhPaths *arginh, int nargs);
-static int findsupers(Oid relid, Oid **supervec);
-static bool check_typeid(Oid id);
-static char *instr1(TypeTupleForm tp, char *string, int typlen);
-static void op_error(char *op, Oid arg1, Oid arg2);
+typedef struct _CandidateList
+{
+ Oid *args;
+ struct _CandidateList *next;
+} *CandidateList;
+
+static Oid **argtype_inherit(int nargs, Oid * oid_array);
+static Oid **genxprod(InhPaths * arginh, int nargs);
+static int findsupers(Oid relid, Oid ** supervec);
+static bool check_typeid(Oid id);
+static char *instr1(TypeTupleForm tp, char *string, int typlen);
+static void op_error(char *op, Oid arg1, Oid arg2);
/* check to see if a type id is valid,
- * returns true if it is. By using this call before calling
+ * returns true if it is. By using this call before calling
* get_id_type or get_id_typname, more meaningful error messages
* can be produced because the caller typically has more context of
- * what's going on - jolly
+ * what's going on - jolly
*/
-static bool
+static bool
check_typeid(Oid id)
{
- return (SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(id),
- 0,0,0) != NULL);
+ return (SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(id),
+ 0, 0, 0) != NULL);
}
@@ -132,46 +159,50 @@ check_typeid(Oid id)
Type
get_id_type(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);
+ 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 name, given a typeid */
-char*
+char *
get_id_typname(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;
+ 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 type name */
Type
type(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);
+ 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 attribute id, return type of that attribute */
@@ -179,297 +210,327 @@ type(char *s)
Oid
att_typeid(Relation rd, int attid)
{
-
- if (attid < 0) {
- return(typeid(type(attnum_type[-attid-1])));
- }
- /* -1 because varattno (where attid comes from) returns one
- more than index */
- return(rd->rd_att->attrs[attid-1]->atttypid);
+
+ if (attid < 0)
+ {
+ return (typeid(type(attnum_type[-attid - 1])));
+ }
+
+ /*
+ * -1 because varattno (where attid comes from) returns one more than
+ * index
+ */
+ return (rd->rd_att->attrs[attid - 1]->atttypid);
}
int
att_attnelems(Relation rd, int attid)
{
- return(rd->rd_att->attrs[attid-1]->attnelems);
+ return (rd->rd_att->attrs[attid - 1]->attnelems);
}
/* given type, return the type OID */
Oid
typeid(Type tp)
{
- if (tp == NULL) {
- elog ( WARN , "typeid() called with NULL type struct");
- }
- return(tp->t_oid);
+ if (tp == NULL)
+ {
+ elog(WARN, "typeid() called with NULL type struct");
+ }
+ return (tp->t_oid);
}
/* given type (as type struct), return the length of type */
int16
tlen(Type t)
{
- TypeTupleForm typ;
-
- typ = (TypeTupleForm)GETSTRUCT(t);
- return(typ->typlen);
+ TypeTupleForm typ;
+
+ typ = (TypeTupleForm) GETSTRUCT(t);
+ return (typ->typlen);
}
/* given type (as type struct), return the value of its 'byval' attribute.*/
bool
tbyval(Type t)
{
- TypeTupleForm typ;
-
- typ = (TypeTupleForm)GETSTRUCT(t);
- return(typ->typbyval);
+ TypeTupleForm typ;
+
+ typ = (TypeTupleForm) GETSTRUCT(t);
+ return (typ->typbyval);
}
/* given type (as type struct), return the name of type */
-char*
+char *
tname(Type t)
{
- TypeTupleForm typ;
-
- typ = (TypeTupleForm)GETSTRUCT(t);
- return (typ->typname).data;
+ TypeTupleForm typ;
+
+ typ = (TypeTupleForm) GETSTRUCT(t);
+ return (typ->typname).data;
}
/* given type (as type struct), return wether type is passed by value */
int
tbyvalue(Type t)
{
- TypeTupleForm typ;
-
- typ = (TypeTupleForm) GETSTRUCT(t);
- return(typ->typbyval);
+ TypeTupleForm typ;
+
+ typ = (TypeTupleForm) GETSTRUCT(t);
+ return (typ->typbyval);
}
/* given a type, return its typetype ('c' for 'c'atalog types) */
static char
typetypetype(Type t)
{
- TypeTupleForm typ;
-
- typ = (TypeTupleForm) GETSTRUCT(t);
- return(typ->typtype);
+ TypeTupleForm typ;
+
+ typ = (TypeTupleForm) GETSTRUCT(t);
+ return (typ->typtype);
}
/* given operator, return the operator OID */
Oid
oprid(Operator op)
{
- return(op->t_oid);
+ 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
+ * 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
*/
static int
binary_oper_get_candidates(char *opname,
- Oid leftTypeId,
- Oid rightTypeId,
- CandidateList *candidates)
+ 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,
- SelfTimeQual,
- 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);
+ 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));
}
- } while(HeapTupleIsValid(tup));
-
- heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
-
- return ncandidates;
+ else
+ {
+ /* currently only "unknown" can be coerced */
+ return 0;
+ }
+
+ pg_operator_desc = heap_openr(OperatorRelationName);
+ pg_operator_scan = heap_beginscan(pg_operator_desc,
+ 0,
+ SelfTimeQual,
+ 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).
+ * 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).
*/
-static bool
+static 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;
+ 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;
}
- 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;
+
+ /*
+ * 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;
}
- 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;
+
+ /*
+ * 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
+ * given a choice of argument type pairs for a binary operator,
+ * try to choose a default pair
*/
-static CandidateList
+static CandidateList
binary_oper_select_candidate(Oid arg1,
- Oid arg2,
- CandidateList candidates)
+ 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);
+ 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;
+ }
- /*
- * 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);
+ return (NULL);
}
/* Given operator, types of arg1, and arg2, return oper struct */
@@ -477,135 +538,158 @@ binary_oper_select_candidate(Oid arg1,
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 = get_id_type(arg1);
- tp2 = get_id_type(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",
- tname(tp1), tname(tp2));
- elog(WARN, "using an explicit cast");
+ 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 = get_id_type(arg1);
+ tp2 = get_id_type(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",
+ tname(tp1), tname(tp2));
+ elog(WARN, "using an explicit cast");
+ }
+ return (NULL);
+ }
}
- return(NULL);
- }
}
- }
- return((Operator) tup);
+ 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
+ * 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
*/
static int
unary_oper_get_candidates(char *op,
- Oid typeId,
- CandidateList *candidates,
- char rightleft)
+ 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,
- SelfTimeQual,
- 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);
+ 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;
}
- } while(HeapTupleIsValid(tup));
-
- heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
-
- return ncandidates;
+
+ pg_operator_desc = heap_openr(OperatorRelationName);
+ pg_operator_scan = heap_beginscan(pg_operator_desc,
+ 0,
+ SelfTimeQual,
+ 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 */
@@ -613,42 +697,44 @@ unary_oper_get_candidates(char *op,
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);
+ 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);
+ return ((Operator) tup);
}
/* Given unary left-side operator (operator on left), return oper struct */
@@ -656,42 +742,44 @@ right_oper(char *op, Oid arg)
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);
+ 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);
+ return ((Operator) tup);
}
/* given range variable, return id of variable */
@@ -699,22 +787,26 @@ left_oper(char *op, Oid arg)
int
varattno(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);
+ 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);
+ for (i = 0; i < SPECIALS; i++)
+ {
+ if (!strcmp(special_attr[i].field, a))
+ {
+ return (special_attr[i].code);
+ }
}
- }
-
- elog(WARN,"Relation %s does not have attribute %s\n",
- RelationGetRelationName(rd), a );
- return(-1);
+
+ elog(WARN, "Relation %s does not have attribute %s\n",
+ RelationGetRelationName(rd), a);
+ return (-1);
}
/* Given range variable, return whether attribute of this name
@@ -725,104 +817,118 @@ varattno(Relation rd, char *a)
bool
varisset(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 */
+ 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));
+ return (get_attisset(rd->rd_id, name));
}
/* given range variable, return id of variable */
int
nf_varattno(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);
+ 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);
+ for (i = 0; i < SPECIALS; i++)
+ {
+ if (!strcmp(special_attr[i].field, a))
+ {
+ return (special_attr[i].code);
+ }
}
- }
- return InvalidAttrNumber;
+ return InvalidAttrNumber;
}
/*-------------
* given an attribute number and a relation, return its relation name
*/
-char*
+char *
getAttrName(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);
- }
+ 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\n",
+ 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\n",
+ attrno, RelationGetRelationName(rd));
}
- elog(WARN, "Illegal attr no %d for relation %s\n",
- 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\n",
- attrno, RelationGetRelationName(rd));
- }
-
- /*
- * Shouldn't get here, but we want lint to be happy...
- */
-
- return(NULL);
+
+ /*
+ * Shouldn't get here, but we want lint to be happy...
+ */
+
+ return (NULL);
}
/* 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 */
+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));
+ TypeTupleForm tp;
+ Oid op;
+
+ tp = (TypeTupleForm) GETSTRUCT(type(typename));
+ op = tp->typoutput;
+ return ((char *) fmgr(op, value));
}
+
#endif
/* Given a Type and a string, return the internal form of that string */
-char *
+char *
instr2(Type tp, char *string, int typlen)
{
- return(instr1((TypeTupleForm ) GETSTRUCT(tp), string, typlen));
+ return (instr1((TypeTupleForm) GETSTRUCT(tp), string, typlen));
}
/* Given a type structure and a string, returns the internal form of
that string */
-static char *
+static char *
instr1(TypeTupleForm tp, char *string, int typlen)
{
- Oid op;
- Oid typelem;
-
- op = tp->typinput;
- typelem = tp->typelem; /* XXX - used for array_in */
- /* typlen is for bpcharin() and varcharin() */
- return((char *) fmgr(op, string, typelem, typlen));
+ Oid op;
+ Oid typelem;
+
+ op = tp->typinput;
+ typelem = tp->typelem; /* XXX - used for array_in */
+ /* typlen is for bpcharin() and varcharin() */
+ return ((char *) fmgr(op, string, typelem, typlen));
}
/* Given the attribute type of an array return the arrtribute type of
@@ -831,151 +937,160 @@ instr1(TypeTupleForm tp, char *string, int typlen)
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\n",
- 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);
+ 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\n",
+ 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);
}
Oid
funcid_get_rettype(Oid funcid)
{
- HeapTuple func_tuple = NULL;
- Oid funcrettype = (Oid)0;
-
- func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
- 0,0,0);
-
- if ( !HeapTupleIsValid ( func_tuple ))
- elog (WARN, "function %d does not exist", funcid);
-
- funcrettype = (Oid)
- ((Form_pg_proc)GETSTRUCT(func_tuple))->prorettype ;
-
- return (funcrettype);
+ HeapTuple func_tuple = NULL;
+ Oid funcrettype = (Oid) 0;
+
+ func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(func_tuple))
+ elog(WARN, "function %d does not exist", funcid);
+
+ funcrettype = (Oid)
+ ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
+
+ return (funcrettype);
}
/*
* get a list of all argument type vectors for which a function named
* funcname taking nargs arguments exists
*/
-static CandidateList
+static CandidateList
func_get_candidates(char *funcname, int nargs)
{
- Relation heapRelation;
- Relation idesc;
- ScanKeyData skey;
- HeapTuple tuple;
- IndexScanDesc sd;
- RetrieveIndexResult indexRes;
- Buffer buffer;
- Form_pg_proc pgProcP;
- bool bufferUsed = FALSE;
- CandidateList candidates = NULL;
- CandidateList current_candidate;
- int i;
-
- heapRelation = heap_openr(ProcedureRelationName);
- ScanKeyEntryInitialize(&skey,
- (bits16)0x0,
- (AttrNumber)1,
- (RegProcedure)NameEqualRegProcedure,
- (Datum)funcname);
-
- idesc = index_openr(ProcedureNameIndex);
-
- sd = index_beginscan(idesc, false, 1, &skey);
-
- do {
- tuple = (HeapTuple)NULL;
- if (bufferUsed) {
- ReleaseBuffer(buffer);
- bufferUsed = FALSE;
- }
-
- indexRes = index_getnext(sd, ForwardScanDirection);
- if (indexRes) {
- ItemPointer iptr;
-
- iptr = &indexRes->heap_iptr;
- tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
- pfree(indexRes);
- if (HeapTupleIsValid(tuple)) {
- pgProcP = (Form_pg_proc)GETSTRUCT(tuple);
- bufferUsed = TRUE;
- if (pgProcP->pronargs == nargs) {
- current_candidate = (CandidateList)
- palloc(sizeof(struct _CandidateList));
- current_candidate->args = (Oid *)
- palloc(8 * sizeof(Oid));
- memset(current_candidate->args, 0, 8 * sizeof(Oid));
- for (i=0; i<nargs; i++) {
- current_candidate->args[i] =
- pgProcP->proargtypes[i];
- }
-
- current_candidate->next = candidates;
- candidates = current_candidate;
+ Relation heapRelation;
+ Relation idesc;
+ ScanKeyData skey;
+ HeapTuple tuple;
+ IndexScanDesc sd;
+ RetrieveIndexResult indexRes;
+ Buffer buffer;
+ Form_pg_proc pgProcP;
+ bool bufferUsed = FALSE;
+ CandidateList candidates = NULL;
+ CandidateList current_candidate;
+ int i;
+
+ heapRelation = heap_openr(ProcedureRelationName);
+ ScanKeyEntryInitialize(&skey,
+ (bits16) 0x0,
+ (AttrNumber) 1,
+ (RegProcedure) NameEqualRegProcedure,
+ (Datum) funcname);
+
+ idesc = index_openr(ProcedureNameIndex);
+
+ sd = index_beginscan(idesc, false, 1, &skey);
+
+ do
+ {
+ tuple = (HeapTuple) NULL;
+ if (bufferUsed)
+ {
+ ReleaseBuffer(buffer);
+ bufferUsed = FALSE;
}
- }
- }
- } while (indexRes);
-
- index_endscan(sd);
- index_close(idesc);
- heap_close(heapRelation);
-
- return candidates;
+
+ indexRes = index_getnext(sd, ForwardScanDirection);
+ if (indexRes)
+ {
+ ItemPointer iptr;
+
+ iptr = &indexRes->heap_iptr;
+ tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
+ pfree(indexRes);
+ if (HeapTupleIsValid(tuple))
+ {
+ pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
+ bufferUsed = TRUE;
+ if (pgProcP->pronargs == nargs)
+ {
+ current_candidate = (CandidateList)
+ palloc(sizeof(struct _CandidateList));
+ current_candidate->args = (Oid *)
+ palloc(8 * sizeof(Oid));
+ memset(current_candidate->args, 0, 8 * sizeof(Oid));
+ for (i = 0; i < nargs; i++)
+ {
+ current_candidate->args[i] =
+ pgProcP->proargtypes[i];
+ }
+
+ current_candidate->next = candidates;
+ candidates = current_candidate;
+ }
+ }
+ }
+ } while (indexRes);
+
+ index_endscan(sd);
+ index_close(idesc);
+ heap_close(heapRelation);
+
+ return candidates;
}
/*
* can input_typeids be coerced to func_typeids?
*/
-static bool
-can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
+static bool
+can_coerce(int nargs, Oid * input_typeids, Oid * func_typeids)
{
- int i;
- Type tp;
-
- /*
- * right now, we only coerce "unknown", and we cannot coerce it to a
- * relation type
- */
- for (i=0; i<nargs; i++) {
- if (input_typeids[i] != func_typeids[i]) {
- if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
- (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
- (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
- (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
- (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
- (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
- ; /* these are OK */
- else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
- return false;
-
- tp = get_id_type(input_typeids[i]);
- if (typetypetype(tp) == 'c' )
- return false;
+ int i;
+ Type tp;
+
+ /*
+ * right now, we only coerce "unknown", and we cannot coerce it to a
+ * relation type
+ */
+ for (i = 0; i < nargs; i++)
+ {
+ if (input_typeids[i] != func_typeids[i])
+ {
+ if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
+ (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
+ (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
+ (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
+ (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
+ (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
+ ; /* these are OK */
+ else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
+ return false;
+
+ tp = get_id_type(input_typeids[i]);
+ if (typetypetype(tp) == 'c')
+ return false;
+ }
}
- }
-
- return true;
+
+ return true;
}
/*
@@ -986,32 +1101,34 @@ can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
*/
static int
match_argtypes(int nargs,
- Oid *input_typeids,
- CandidateList function_typeids,
- CandidateList *candidates) /* return value */
+ Oid * input_typeids,
+ CandidateList function_typeids,
+ CandidateList * candidates) /* return value */
{
- CandidateList current_candidate;
- CandidateList matching_candidate;
- Oid *current_typeids;
- int ncandidates = 0;
-
- *candidates = NULL;
-
- for (current_candidate = function_typeids;
- current_candidate != NULL;
- current_candidate = current_candidate->next) {
- current_typeids = current_candidate->args;
- if (can_coerce(nargs, input_typeids, current_typeids)) {
- matching_candidate = (CandidateList)
- palloc(sizeof(struct _CandidateList));
- matching_candidate->args = current_typeids;
- matching_candidate->next = *candidates;
- *candidates = matching_candidate;
- ncandidates++;
+ CandidateList current_candidate;
+ CandidateList matching_candidate;
+ Oid *current_typeids;
+ int ncandidates = 0;
+
+ *candidates = NULL;
+
+ for (current_candidate = function_typeids;
+ current_candidate != NULL;
+ current_candidate = current_candidate->next)
+ {
+ current_typeids = current_candidate->args;
+ if (can_coerce(nargs, input_typeids, current_typeids))
+ {
+ matching_candidate = (CandidateList)
+ palloc(sizeof(struct _CandidateList));
+ matching_candidate->args = current_typeids;
+ matching_candidate->next = *candidates;
+ *candidates = matching_candidate;
+ ncandidates++;
+ }
}
- }
-
- return ncandidates;
+
+ return ncandidates;
}
/*
@@ -1020,442 +1137,483 @@ match_argtypes(int nargs,
* returns the selected argtype array if the conflict can be resolved,
* otherwise returns NULL
*/
-static Oid *
+static Oid *
func_select_candidate(int nargs,
- Oid *input_typeids,
- CandidateList candidates)
+ Oid * input_typeids,
+ CandidateList candidates)
{
- /* XXX no conflict resolution implemeneted yet */
- return (NULL);
+ /* XXX no conflict resolution implemeneted yet */
+ return (NULL);
}
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) /* return value */
+ int nargs,
+ Oid * oid_array,
+ Oid * funcid, /* return value */
+ Oid * rettype, /* return value */
+ bool * retset, /* return value */
+ Oid ** true_typeids) /* return value */
{
- Oid **input_typeid_vector;
- Oid *current_input_typeids;
- CandidateList function_typeids;
- CandidateList current_function_typeids;
- HeapTuple ftup;
- Form_pg_proc pform;
-
- /*
- * attempt to find named function in the system catalogs
- * with arguments exactly as specified - so that the normal
- * case is just as quick as before
- */
- ftup = SearchSysCacheTuple(PRONAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(oid_array),
- 0);
- *true_typeids = oid_array;
-
- /*
- * If an exact match isn't found :
- * 1) get a vector of all possible input arg type arrays constructed
- * from the superclasses of the original input arg types
- * 2) get a list of all possible argument type arrays to the
- * function with given name and number of arguments
- * 3) for each input arg type array from vector #1 :
- * a) find how many of the function arg type arrays from list #2
- * it can be coerced to
- * b) - if the answer is one, we have our function
- * - if the answer is more than one, attempt to resolve the
- * conflict
- * - if the answer is zero, try the next array from vector #1
- */
- if (!HeapTupleIsValid(ftup)) {
- function_typeids = func_get_candidates(funcname, nargs);
-
- if (function_typeids != NULL) {
- int ncandidates = 0;
-
- input_typeid_vector = argtype_inherit(nargs, oid_array);
- current_input_typeids = oid_array;
-
- do {
- ncandidates = match_argtypes(nargs, current_input_typeids,
- function_typeids,
- &current_function_typeids);
- if (ncandidates == 1) {
- *true_typeids = current_function_typeids->args;
- ftup = SearchSysCacheTuple(PRONAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(*true_typeids),
- 0);
- Assert(HeapTupleIsValid(ftup));
+ Oid **input_typeid_vector;
+ Oid *current_input_typeids;
+ CandidateList function_typeids;
+ CandidateList current_function_typeids;
+ HeapTuple ftup;
+ Form_pg_proc pform;
+
+ /*
+ * attempt to find named function in the system catalogs with
+ * arguments exactly as specified - so that the normal case is just as
+ * quick as before
+ */
+ ftup = SearchSysCacheTuple(PRONAME,
+ PointerGetDatum(funcname),
+ Int32GetDatum(nargs),
+ PointerGetDatum(oid_array),
+ 0);
+ *true_typeids = oid_array;
+
+ /*
+ * If an exact match isn't found : 1) get a vector of all possible
+ * input arg type arrays constructed from the superclasses of the
+ * original input arg types 2) get a list of all possible argument
+ * type arrays to the function with given name and number of arguments
+ * 3) for each input arg type array from vector #1 : a) find how many
+ * of the function arg type arrays from list #2 it can be coerced to
+ * b) - if the answer is one, we have our function - if the answer is
+ * more than one, attempt to resolve the conflict - if the answer is
+ * zero, try the next array from vector #1
+ */
+ if (!HeapTupleIsValid(ftup))
+ {
+ function_typeids = func_get_candidates(funcname, nargs);
+
+ if (function_typeids != NULL)
+ {
+ int ncandidates = 0;
+
+ input_typeid_vector = argtype_inherit(nargs, oid_array);
+ current_input_typeids = oid_array;
+
+ do
+ {
+ ncandidates = match_argtypes(nargs, current_input_typeids,
+ function_typeids,
+ &current_function_typeids);
+ if (ncandidates == 1)
+ {
+ *true_typeids = current_function_typeids->args;
+ ftup = SearchSysCacheTuple(PRONAME,
+ PointerGetDatum(funcname),
+ Int32GetDatum(nargs),
+ PointerGetDatum(*true_typeids),
+ 0);
+ Assert(HeapTupleIsValid(ftup));
+ }
+ else if (ncandidates > 1)
+ {
+ *true_typeids =
+ func_select_candidate(nargs,
+ current_input_typeids,
+ current_function_typeids);
+ if (*true_typeids == NULL)
+ {
+ elog(NOTICE, "there is more than one function named \"%s\"",
+ funcname);
+ elog(NOTICE, "that satisfies the given argument types. you will have to");
+ elog(NOTICE, "retype your query using explicit typecasts.");
+ func_error("func_get_detail", funcname, nargs, oid_array);
+ }
+ else
+ {
+ ftup = SearchSysCacheTuple(PRONAME,
+ PointerGetDatum(funcname),
+ Int32GetDatum(nargs),
+ PointerGetDatum(*true_typeids),
+ 0);
+ Assert(HeapTupleIsValid(ftup));
+ }
+ }
+ current_input_typeids = *input_typeid_vector++;
+ }
+ while (current_input_typeids !=
+ InvalidOid && ncandidates == 0);
}
- else if (ncandidates > 1) {
- *true_typeids =
- func_select_candidate(nargs,
- current_input_typeids,
- current_function_typeids);
- if (*true_typeids == NULL) {
- elog(NOTICE, "there is more than one function named \"%s\"",
- funcname);
- elog(NOTICE, "that satisfies the given argument types. you will have to");
- elog(NOTICE, "retype your query using explicit typecasts.");
- func_error("func_get_detail", funcname, nargs, oid_array);
- }
- else {
- ftup = SearchSysCacheTuple(PRONAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(*true_typeids),
- 0);
- Assert(HeapTupleIsValid(ftup));
- }
+ }
+
+ if (!HeapTupleIsValid(ftup))
+ {
+ Type tp;
+
+ if (nargs == 1)
+ {
+ tp = get_id_type(oid_array[0]);
+ if (typetypetype(tp) == 'c')
+ elog(WARN, "no such attribute or function \"%s\"",
+ funcname);
}
- current_input_typeids = *input_typeid_vector++;
- }
- while (current_input_typeids !=
- InvalidOid && ncandidates == 0);
+ func_error("func_get_detail", funcname, nargs, oid_array);
}
- }
-
- if (!HeapTupleIsValid(ftup)) {
- Type tp;
-
- if (nargs == 1) {
- tp = get_id_type(oid_array[0]);
- if (typetypetype(tp) == 'c')
- elog(WARN, "no such attribute or function \"%s\"",
- funcname);
+ else
+ {
+ pform = (Form_pg_proc) GETSTRUCT(ftup);
+ *funcid = ftup->t_oid;
+ *rettype = pform->prorettype;
+ *retset = pform->proretset;
+
+ return (true);
}
- func_error("func_get_detail", funcname, nargs, oid_array);
- } else {
- pform = (Form_pg_proc) GETSTRUCT(ftup);
- *funcid = ftup->t_oid;
- *rettype = pform->prorettype;
- *retset = pform->proretset;
-
- return (true);
- }
/* shouldn't reach here */
- return (false);
+ return (false);
}
/*
- * argtype_inherit() -- Construct an argtype vector reflecting the
- * inheritance properties of the supplied argv.
+ * argtype_inherit() -- Construct an argtype vector reflecting the
+ * inheritance properties of the supplied argv.
*
- * This function is used to disambiguate among functions with the
- * same name but different signatures. It takes an array of eight
- * type ids. For each type id in the array that's a complex type
- * (a class), it walks up the inheritance tree, finding all
- * superclasses of that type. A vector of new Oid type arrays
- * is returned to the caller, reflecting the structure of the
- * inheritance tree above the supplied arguments.
+ * This function is used to disambiguate among functions with the
+ * same name but different signatures. It takes an array of eight
+ * type ids. For each type id in the array that's a complex type
+ * (a class), it walks up the inheritance tree, finding all
+ * superclasses of that type. A vector of new Oid type arrays
+ * is returned to the caller, reflecting the structure of the
+ * inheritance tree above the supplied arguments.
*
- * The order of this vector is as follows: all superclasses of the
- * rightmost complex class are explored first. The exploration
- * continues from right to left. This policy means that we favor
- * keeping the leftmost argument type as low in the inheritance tree
- * as possible. This is intentional; it is exactly what we need to
- * do for method dispatch. The last type array we return is all
- * zeroes. This will match any functions for which return types are
- * not defined. There are lots of these (mostly builtins) in the
- * catalogs.
+ * The order of this vector is as follows: all superclasses of the
+ * rightmost complex class are explored first. The exploration
+ * continues from right to left. This policy means that we favor
+ * keeping the leftmost argument type as low in the inheritance tree
+ * as possible. This is intentional; it is exactly what we need to
+ * do for method dispatch. The last type array we return is all
+ * zeroes. This will match any functions for which return types are
+ * not defined. There are lots of these (mostly builtins) in the
+ * catalogs.
*/
-static Oid **
-argtype_inherit(int nargs, Oid *oid_array)
+static Oid **
+argtype_inherit(int nargs, Oid * oid_array)
{
- Oid relid;
- int i;
- InhPaths arginh[MAXFARGS];
-
- for (i = 0; i < MAXFARGS; i++) {
- if (i < nargs) {
- arginh[i].self = oid_array[i];
- if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid) {
- arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
- } else {
- arginh[i].nsupers = 0;
- arginh[i].supervec = (Oid *) NULL;
- }
- } else {
- arginh[i].self = InvalidOid;
- arginh[i].nsupers = 0;
- arginh[i].supervec = (Oid *) NULL;
+ Oid relid;
+ int i;
+ InhPaths arginh[MAXFARGS];
+
+ for (i = 0; i < MAXFARGS; i++)
+ {
+ if (i < nargs)
+ {
+ arginh[i].self = oid_array[i];
+ if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid)
+ {
+ arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
+ }
+ else
+ {
+ arginh[i].nsupers = 0;
+ arginh[i].supervec = (Oid *) NULL;
+ }
+ }
+ else
+ {
+ arginh[i].self = InvalidOid;
+ arginh[i].nsupers = 0;
+ arginh[i].supervec = (Oid *) NULL;
+ }
}
- }
-
- /* return an ordered cross-product of the classes involved */
- return (genxprod(arginh, nargs));
+
+ /* return an ordered cross-product of the classes involved */
+ return (genxprod(arginh, nargs));
}
-typedef struct _SuperQE {
- Oid sqe_relid;
-} SuperQE;
+typedef struct _SuperQE
+{
+ Oid sqe_relid;
+} SuperQE;
static int
-findsupers(Oid relid, Oid **supervec)
+findsupers(Oid relid, Oid ** supervec)
{
- Oid *relidvec;
- Relation inhrel;
- HeapScanDesc inhscan;
- ScanKeyData skey;
- HeapTuple inhtup;
- TupleDesc inhtupdesc;
- int nvisited;
- SuperQE *qentry, *vnode;
- Dllist *visited, *queue;
- Dlelem *qe, *elt;
-
- Relation rd;
- Buffer buf;
- Datum d;
- bool newrelid;
- char isNull;
-
- nvisited = 0;
- queue = DLNewList();
- visited = DLNewList();
-
-
- inhrel = heap_openr(InheritsRelationName);
- RelationSetLockForRead(inhrel);
- inhtupdesc = RelationGetTupleDescriptor(inhrel);
-
- /*
- * Use queue to do a breadth-first traversal of the inheritance
- * graph from the relid supplied up to the root.
- */
- do {
- ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
- ObjectIdEqualRegProcedure,
- ObjectIdGetDatum(relid));
-
- inhscan = heap_beginscan(inhrel, 0, NowTimeQual, 1, &skey);
-
- while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf))) {
- qentry = (SuperQE *) palloc(sizeof(SuperQE));
-
- d = (Datum) fastgetattr(inhtup, Anum_pg_inherits_inhparent,
- inhtupdesc, &isNull);
- qentry->sqe_relid = DatumGetObjectId(d);
-
- /* put this one on the queue */
- DLAddTail(queue, DLNewElem(qentry));
-
- ReleaseBuffer(buf);
+ Oid *relidvec;
+ Relation inhrel;
+ HeapScanDesc inhscan;
+ ScanKeyData skey;
+ HeapTuple inhtup;
+ TupleDesc inhtupdesc;
+ int nvisited;
+ SuperQE *qentry,
+ *vnode;
+ Dllist *visited,
+ *queue;
+ Dlelem *qe,
+ *elt;
+
+ Relation rd;
+ Buffer buf;
+ Datum d;
+ bool newrelid;
+ char isNull;
+
+ nvisited = 0;
+ queue = DLNewList();
+ visited = DLNewList();
+
+
+ inhrel = heap_openr(InheritsRelationName);
+ RelationSetLockForRead(inhrel);
+ inhtupdesc = RelationGetTupleDescriptor(inhrel);
+
+ /*
+ * Use queue to do a breadth-first traversal of the inheritance graph
+ * from the relid supplied up to the root.
+ */
+ do
+ {
+ ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
+ ObjectIdEqualRegProcedure,
+ ObjectIdGetDatum(relid));
+
+ inhscan = heap_beginscan(inhrel, 0, NowTimeQual, 1, &skey);
+
+ while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf)))
+ {
+ qentry = (SuperQE *) palloc(sizeof(SuperQE));
+
+ d = (Datum) fastgetattr(inhtup, Anum_pg_inherits_inhparent,
+ inhtupdesc, &isNull);
+ qentry->sqe_relid = DatumGetObjectId(d);
+
+ /* put this one on the queue */
+ DLAddTail(queue, DLNewElem(qentry));
+
+ ReleaseBuffer(buf);
+ }
+
+ heap_endscan(inhscan);
+
+ /* pull next unvisited relid off the queue */
+ do
+ {
+ qe = DLRemHead(queue);
+ qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
+
+ if (qentry == (SuperQE *) NULL)
+ break;
+
+ relid = qentry->sqe_relid;
+ newrelid = true;
+
+ for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+ {
+ vnode = (SuperQE *) DLE_VAL(elt);
+ if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
+ {
+ newrelid = false;
+ break;
+ }
+ }
+ } while (!newrelid);
+
+ if (qentry != (SuperQE *) NULL)
+ {
+
+ /* save the type id, rather than the relation id */
+ if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
+ elog(WARN, "relid %d does not exist", qentry->sqe_relid);
+ qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data));
+ heap_close(rd);
+
+ DLAddTail(visited, qe);
+
+ nvisited++;
+ }
+ } while (qentry != (SuperQE *) NULL);
+
+ RelationUnsetLockForRead(inhrel);
+ heap_close(inhrel);
+
+ if (nvisited > 0)
+ {
+ relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
+ *supervec = relidvec;
+
+ for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+ {
+ vnode = (SuperQE *) DLE_VAL(elt);
+ *relidvec++ = vnode->sqe_relid;
+ }
+
}
-
- heap_endscan(inhscan);
-
- /* pull next unvisited relid off the queue */
- do {
- qe = DLRemHead(queue);
- qentry = qe ? (SuperQE*)DLE_VAL(qe) : NULL;
-
- if (qentry == (SuperQE *) NULL)
- break;
-
- relid = qentry->sqe_relid;
- newrelid = true;
-
- for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) {
- vnode = (SuperQE*)DLE_VAL(elt);
- if (vnode && (qentry->sqe_relid == vnode->sqe_relid)) {
- newrelid = false;
- break;
- }
- }
- } while (!newrelid);
-
- if (qentry != (SuperQE *) NULL) {
-
- /* save the type id, rather than the relation id */
- if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
- elog(WARN, "relid %d does not exist", qentry->sqe_relid);
- qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data));
- heap_close(rd);
-
- DLAddTail(visited, qe);
-
- nvisited++;
+ else
+ {
+ *supervec = (Oid *) NULL;
}
- } while (qentry != (SuperQE *) NULL);
-
- RelationUnsetLockForRead(inhrel);
- heap_close(inhrel);
-
- if (nvisited > 0) {
- relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
- *supervec = relidvec;
-
- for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) {
- vnode = (SuperQE*)DLE_VAL(elt);
- *relidvec++ = vnode->sqe_relid;
- }
-
- } else {
- *supervec = (Oid *) NULL;
- }
-
- return (nvisited);
+
+ return (nvisited);
}
-static Oid **
-genxprod(InhPaths *arginh, int nargs)
+static Oid **
+genxprod(InhPaths * arginh, int nargs)
{
- int nanswers;
- Oid **result, **iter;
- Oid *oneres;
- int i, j;
- int cur[MAXFARGS];
-
- nanswers = 1;
- for (i = 0; i < nargs; i++) {
- nanswers *= (arginh[i].nsupers + 2);
- cur[i] = 0;
- }
-
- iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
-
- /* compute the cross product from right to left */
- for (;;) {
- oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
- memset(oneres, 0, MAXFARGS * sizeof(Oid));
-
- for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
- continue;
-
- /* if we're done, terminate with NULL pointer */
- if (i < 0) {
- *iter = NULL;
- return (result);
+ int nanswers;
+ Oid **result,
+ **iter;
+ Oid *oneres;
+ int i,
+ j;
+ int cur[MAXFARGS];
+
+ nanswers = 1;
+ for (i = 0; i < nargs; i++)
+ {
+ nanswers *= (arginh[i].nsupers + 2);
+ cur[i] = 0;
}
-
- /* no, increment this column and zero the ones after it */
- cur[i] = cur[i] + 1;
- for (j = nargs - 1; j > i; j--)
- cur[j] = 0;
-
- for (i = 0; i < nargs; i++) {
- if (cur[i] == 0)
- oneres[i] = arginh[i].self;
- else if (cur[i] > arginh[i].nsupers)
- oneres[i] = 0; /* wild card */
- else
- oneres[i] = arginh[i].supervec[cur[i] - 1];
+
+ iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
+
+ /* compute the cross product from right to left */
+ for (;;)
+ {
+ oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
+ memset(oneres, 0, MAXFARGS * sizeof(Oid));
+
+ for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
+ continue;
+
+ /* if we're done, terminate with NULL pointer */
+ if (i < 0)
+ {
+ *iter = NULL;
+ return (result);
+ }
+
+ /* no, increment this column and zero the ones after it */
+ cur[i] = cur[i] + 1;
+ for (j = nargs - 1; j > i; j--)
+ cur[j] = 0;
+
+ for (i = 0; i < nargs; i++)
+ {
+ if (cur[i] == 0)
+ oneres[i] = arginh[i].self;
+ else if (cur[i] > arginh[i].nsupers)
+ oneres[i] = 0; /* wild card */
+ else
+ oneres[i] = arginh[i].supervec[cur[i] - 1];
+ }
+
+ *iter++ = oneres;
}
-
- *iter++ = oneres;
- }
}
/* Given a type id, returns the in-conversion function of the type */
Oid
typeid_get_retinfunc(Oid type_id)
{
- HeapTuple typeTuple;
- TypeTupleForm type;
- Oid infunc;
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type_id),
- 0,0,0);
- if ( !HeapTupleIsValid ( typeTuple ))
- elog(WARN,
- "typeid_get_retinfunc: Invalid type - oid = %u",
- type_id);
-
- type = (TypeTupleForm) GETSTRUCT(typeTuple);
- infunc = type->typinput;
- return(infunc);
+ HeapTuple typeTuple;
+ TypeTupleForm type;
+ Oid infunc;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type_id),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(typeTuple))
+ elog(WARN,
+ "typeid_get_retinfunc: Invalid type - oid = %u",
+ type_id);
+
+ type = (TypeTupleForm) GETSTRUCT(typeTuple);
+ infunc = type->typinput;
+ return (infunc);
}
/* Given a type id, returns the out-conversion function of the type */
Oid
typeid_get_retoutfunc(Oid type_id)
{
- HeapTuple typeTuple;
- TypeTupleForm type;
- Oid outfunc;
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type_id),
- 0,0,0);
- if ( !HeapTupleIsValid ( typeTuple ))
- elog(WARN,
- "typeid_get_retoutfunc: Invalid type - oid = %u",
- type_id);
-
- type = (TypeTupleForm) GETSTRUCT(typeTuple);
- outfunc = type->typoutput;
- return(outfunc);
+ HeapTuple typeTuple;
+ TypeTupleForm type;
+ Oid outfunc;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type_id),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(typeTuple))
+ elog(WARN,
+ "typeid_get_retoutfunc: Invalid type - oid = %u",
+ type_id);
+
+ type = (TypeTupleForm) GETSTRUCT(typeTuple);
+ outfunc = type->typoutput;
+ return (outfunc);
}
Oid
typeid_get_relid(Oid type_id)
{
- HeapTuple typeTuple;
- TypeTupleForm type;
- Oid infunc;
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type_id),
- 0,0,0);
- if ( !HeapTupleIsValid ( typeTuple ))
- elog(WARN, "typeid_get_relid: Invalid type - oid = %u ", type_id);
-
- type = (TypeTupleForm) GETSTRUCT(typeTuple);
- infunc = type->typrelid;
- return(infunc);
+ HeapTuple typeTuple;
+ TypeTupleForm type;
+ Oid infunc;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type_id),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(typeTuple))
+ elog(WARN, "typeid_get_relid: Invalid type - oid = %u ", type_id);
+
+ type = (TypeTupleForm) GETSTRUCT(typeTuple);
+ infunc = type->typrelid;
+ return (infunc);
}
Oid
get_typrelid(Type typ)
{
- TypeTupleForm typtup;
-
- typtup = (TypeTupleForm) GETSTRUCT(typ);
-
- return (typtup->typrelid);
+ TypeTupleForm typtup;
+
+ typtup = (TypeTupleForm) GETSTRUCT(typ);
+
+ return (typtup->typrelid);
}
Oid
get_typelem(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);
+ 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);
}
#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);
+ 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
/*
@@ -1465,26 +1623,33 @@ FindDelimiter(char *typename)
static void
op_error(char *op, Oid arg1, Oid arg2)
{
- Type tp1 = NULL, tp2 = NULL;
-
- if (check_typeid(arg1)) {
- tp1 = get_id_type(arg1);
- } else {
- elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
- }
-
- if (check_typeid(arg2)) {
- tp2 = get_id_type(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, tname(tp1),tname(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, tname(tp1),tname(tp2));
+ Type tp1 = NULL,
+ tp2 = NULL;
+
+ if (check_typeid(arg1))
+ {
+ tp1 = get_id_type(arg1);
+ }
+ else
+ {
+ elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
+ }
+
+ if (check_typeid(arg2))
+ {
+ tp2 = get_id_type(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, tname(tp1), tname(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, tname(tp1), tname(tp2));
}
/*
@@ -1492,27 +1657,32 @@ op_error(char *op, Oid arg1, Oid arg2)
* argument types
*/
void
-func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
+func_error(char *caller, char *funcname, int nargs, Oid * argtypes)
{
- char p[(NAMEDATALEN+2)*MAXFMGRARGS], *ptr;
- int i;
-
- ptr = p;
- *ptr = '\0';
- for (i=0; i<nargs; i++) {
- if (i) {
- *ptr++ = ',';
- *ptr++ = ' ';
+ char p[(NAMEDATALEN + 2) * MAXFMGRARGS],
+ *ptr;
+ int i;
+
+ ptr = p;
+ *ptr = '\0';
+ for (i = 0; i < nargs; i++)
+ {
+ if (i)
+ {
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ }
+ if (argtypes[i] != 0)
+ {
+ strcpy(ptr, tname(get_id_type(argtypes[i])));
+ *(ptr + NAMEDATALEN) = '\0';
+ }
+ else
+ strcpy(ptr, "opaque");
+ ptr += strlen(ptr);
}
- if (argtypes[i] != 0) {
- strcpy(ptr, tname(get_id_type(argtypes[i])));
- *(ptr + NAMEDATALEN) = '\0';
- } else
- strcpy(ptr, "opaque");
- ptr += strlen(ptr);
- }
-
- elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
+
+ elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
}
/*
@@ -1522,12 +1692,19 @@ func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
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,
- tname(get_id_type(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,
+ tname(get_id_type(basetypeID)));
+ }
}
diff --git a/src/backend/parser/dbcommands.c b/src/backend/parser/dbcommands.c
index f975937b5ad..158e033b6e7 100644
--- a/src/backend/parser/dbcommands.c
+++ b/src/backend/parser/dbcommands.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* dbcommands.c--
- *
+ *
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/dbcommands.c,v 1.6 1997/08/19 21:32:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/dbcommands.c,v 1.7 1997/09/07 04:44:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,7 +16,7 @@
#include <signal.h>
#include "postgres.h"
-#include "miscadmin.h" /* for DataDir */
+#include "miscadmin.h" /* for DataDir */
#include "access/heapam.h"
#include "access/htup.h"
#include "access/relscan.h"
@@ -35,228 +35,253 @@
/* non-export function prototypes */
-static void check_permissions(char *command, char *dbname,
- Oid *dbIdP, Oid *userIdP);
+static void
+check_permissions(char *command, char *dbname,
+ Oid * dbIdP, Oid * userIdP);
static HeapTuple get_pg_dbtup(char *command, char *dbname, Relation dbrel);
-static void stop_vacuum(char *dbname);
+static void stop_vacuum(char *dbname);
void
createdb(char *dbname)
{
- Oid db_id, user_id;
- char buf[512];
-
- /*
- * If this call returns, the database does not exist and we're allowed
- * to create databases.
- */
- check_permissions("createdb", dbname, &db_id, &user_id);
-
- /* close virtual file descriptors so we can do system() calls */
- closeAllVfds();
-
- sprintf(buf, "mkdir %s%cbase%c%s", DataDir, SEP_CHAR, SEP_CHAR, dbname);
- system(buf);
- sprintf(buf, "%s %s%cbase%ctemplate1%c* %s%cbase%c%s",
- COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, DataDir,
- SEP_CHAR, SEP_CHAR, dbname);
- system(buf);
-
-/* sprintf(buf, "insert into pg_database (datname, datdba, datpath) \
+ Oid db_id,
+ user_id;
+ char buf[512];
+
+ /*
+ * If this call returns, the database does not exist and we're allowed
+ * to create databases.
+ */
+ check_permissions("createdb", dbname, &db_id, &user_id);
+
+ /* close virtual file descriptors so we can do system() calls */
+ closeAllVfds();
+
+ sprintf(buf, "mkdir %s%cbase%c%s", DataDir, SEP_CHAR, SEP_CHAR, dbname);
+ system(buf);
+ sprintf(buf, "%s %s%cbase%ctemplate1%c* %s%cbase%c%s",
+ COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, DataDir,
+ SEP_CHAR, SEP_CHAR, dbname);
+ system(buf);
+
+/* sprintf(buf, "insert into pg_database (datname, datdba, datpath) \
values (\'%s\'::char16, \'%d\'::oid, \'%s\'::text);",
- dbname, user_id, dbname);
+ dbname, user_id, dbname);
*/
- sprintf(buf, "insert into pg_database (datname, datdba, datpath) \
+ sprintf(buf, "insert into pg_database (datname, datdba, datpath) \
values (\'%s\', \'%d\', \'%s\');",
- dbname, user_id, dbname);
+ dbname, user_id, dbname);
- pg_eval(buf, (char **) NULL, (Oid *) NULL, 0);
+ pg_eval(buf, (char **) NULL, (Oid *) NULL, 0);
}
void
destroydb(char *dbname)
{
- Oid user_id, db_id;
- char buf[512];
-
- /*
- * If this call returns, the database exists and we're allowed to
- * remove it.
- */
- check_permissions("destroydb", dbname, &db_id, &user_id);
-
- if (!OidIsValid(db_id)) {
- elog(FATAL, "impossible: pg_database instance with invalid OID.");
- }
-
- /* stop the vacuum daemon */
- stop_vacuum(dbname);
-
- /* remove the pg_database tuple FIRST,
- this may fail due to permissions problems*/
- sprintf(buf, "delete from pg_database where pg_database.oid = \'%d\'::oid",
- db_id);
- pg_eval(buf, (char **) NULL, (Oid *) NULL, 0);
-
- /* remove the data directory. If the DELETE above failed, this will
- not be reached */
- sprintf(buf, "rm -r %s/base/%s", DataDir, dbname);
- system(buf);
-
- /* drop pages for this database that are in the shared buffer cache */
- DropBuffers(db_id);
+ Oid user_id,
+ db_id;
+ char buf[512];
+
+ /*
+ * If this call returns, the database exists and we're allowed to
+ * remove it.
+ */
+ check_permissions("destroydb", dbname, &db_id, &user_id);
+
+ if (!OidIsValid(db_id))
+ {
+ elog(FATAL, "impossible: pg_database instance with invalid OID.");
+ }
+
+ /* stop the vacuum daemon */
+ stop_vacuum(dbname);
+
+ /*
+ * remove the pg_database tuple FIRST, this may fail due to
+ * permissions problems
+ */
+ sprintf(buf, "delete from pg_database where pg_database.oid = \'%d\'::oid",
+ db_id);
+ pg_eval(buf, (char **) NULL, (Oid *) NULL, 0);
+
+ /*
+ * remove the data directory. If the DELETE above failed, this will
+ * not be reached
+ */
+ sprintf(buf, "rm -r %s/base/%s", DataDir, dbname);
+ system(buf);
+
+ /* drop pages for this database that are in the shared buffer cache */
+ DropBuffers(db_id);
}
-static HeapTuple
+static HeapTuple
get_pg_dbtup(char *command, char *dbname, Relation dbrel)
{
- HeapTuple dbtup;
- HeapTuple tup;
- Buffer buf;
- HeapScanDesc scan;
- ScanKeyData scanKey;
-
- ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
- NameEqualRegProcedure, NameGetDatum(dbname));
-
- scan = heap_beginscan(dbrel, 0, NowTimeQual, 1, &scanKey);
- if (!HeapScanIsValid(scan))
- elog(WARN, "%s: cannot begin scan of pg_database.", command);
-
- /*
- * since we want to return the tuple out of this proc, and we're
- * going to close the relation, copy the tuple and return the copy.
- */
- tup = heap_getnext(scan, 0, &buf);
-
- if (HeapTupleIsValid(tup)) {
- dbtup = heap_copytuple(tup);
- ReleaseBuffer(buf);
- } else
- dbtup = tup;
-
- heap_endscan(scan);
- return (dbtup);
+ HeapTuple dbtup;
+ HeapTuple tup;
+ Buffer buf;
+ HeapScanDesc scan;
+ ScanKeyData scanKey;
+
+ ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
+ NameEqualRegProcedure, NameGetDatum(dbname));
+
+ scan = heap_beginscan(dbrel, 0, NowTimeQual, 1, &scanKey);
+ if (!HeapScanIsValid(scan))
+ elog(WARN, "%s: cannot begin scan of pg_database.", command);
+
+ /*
+ * since we want to return the tuple out of this proc, and we're going
+ * to close the relation, copy the tuple and return the copy.
+ */
+ tup = heap_getnext(scan, 0, &buf);
+
+ if (HeapTupleIsValid(tup))
+ {
+ dbtup = heap_copytuple(tup);
+ ReleaseBuffer(buf);
+ }
+ else
+ dbtup = tup;
+
+ heap_endscan(scan);
+ return (dbtup);
}
/*
- * check_permissions() -- verify that the user is permitted to do this.
+ * check_permissions() -- verify that the user is permitted to do this.
*
- * If the user is not allowed to carry out this operation, this routine
- * elog(WARN, ...)s, which will abort the xact. As a side effect, the
- * user's pg_user tuple OID is returned in userIdP and the target database's
- * OID is returned in dbIdP.
+ * If the user is not allowed to carry out this operation, this routine
+ * elog(WARN, ...)s, which will abort the xact. As a side effect, the
+ * user's pg_user tuple OID is returned in userIdP and the target database's
+ * OID is returned in dbIdP.
*/
static void
check_permissions(char *command,
- char *dbname,
- Oid *dbIdP,
- Oid *userIdP)
+ char *dbname,
+ Oid * dbIdP,
+ Oid * userIdP)
{
- Relation dbrel;
- HeapTuple dbtup, utup;
- Oid dbowner = (Oid)0;
- char use_createdb;
- bool dbfound;
- bool use_super;
- char *userName;
-
- userName = GetPgUserName();
- utup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName),
- 0,0,0);
- *userIdP = ((Form_pg_user)GETSTRUCT(utup))->usesysid;
- use_super = ((Form_pg_user)GETSTRUCT(utup))->usesuper;
- use_createdb = ((Form_pg_user)GETSTRUCT(utup))->usecreatedb;
-
- /* Check to make sure user has permission to use createdb */
- if (!use_createdb) {
- elog(WARN, "user \"%s\" is not allowed to create/destroy databases",
- userName);
- }
-
- /* Make sure we are not mucking with the template database */
- if (!strcmp(dbname, "template1")) {
- elog(WARN, "%s cannot be executed on the template database.", command);
- }
-
- /* Check to make sure database is not the currently open database */
- if (!strcmp(dbname, GetDatabaseName())) {
- elog(WARN, "%s cannot be executed on an open database", command);
- }
-
- /* Check to make sure database is owned by this user */
-
- /*
- * need the reldesc to get the database owner out of dbtup
- * and to set a write lock on it.
- */
- dbrel = heap_openr(DatabaseRelationName);
-
- if (!RelationIsValid(dbrel))
- elog(FATAL, "%s: cannot open relation \"%-.*s\"",
- command, DatabaseRelationName);
-
- /*
- * Acquire a write lock on pg_database from the beginning to avoid
- * upgrading a read lock to a write lock. Upgrading causes long delays
- * when multiple 'createdb's or 'destroydb's are run simult. -mer 7/3/91
- */
- RelationSetLockForWrite(dbrel);
- dbtup = get_pg_dbtup(command, dbname, dbrel);
- dbfound = HeapTupleIsValid(dbtup);
-
- if (dbfound) {
- dbowner = (Oid) heap_getattr(dbtup, InvalidBuffer,
- Anum_pg_database_datdba,
- RelationGetTupleDescriptor(dbrel),
- (char *) NULL);
- *dbIdP = dbtup->t_oid;
- } else {
- *dbIdP = InvalidOid;
- }
-
- heap_close(dbrel);
-
- /*
- * Now be sure that the user is allowed to do this.
- */
-
- if (dbfound && !strcmp(command, "createdb")) {
-
- elog(WARN, "createdb: database %s already exists.", dbname);
-
- } else if (!dbfound && !strcmp(command, "destroydb")) {
-
- elog(WARN, "destroydb: database %s does not exist.", dbname);
-
- } else if (dbfound && !strcmp(command, "destroydb")
- && dbowner != *userIdP && use_super == false) {
-
- elog(WARN, "%s: database %s is not owned by you.", command, dbname);
-
- }
+ Relation dbrel;
+ HeapTuple dbtup,
+ utup;
+ Oid dbowner = (Oid) 0;
+ char use_createdb;
+ bool dbfound;
+ bool use_super;
+ char *userName;
+
+ userName = GetPgUserName();
+ utup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName),
+ 0, 0, 0);
+ *userIdP = ((Form_pg_user) GETSTRUCT(utup))->usesysid;
+ use_super = ((Form_pg_user) GETSTRUCT(utup))->usesuper;
+ use_createdb = ((Form_pg_user) GETSTRUCT(utup))->usecreatedb;
+
+ /* Check to make sure user has permission to use createdb */
+ if (!use_createdb)
+ {
+ elog(WARN, "user \"%s\" is not allowed to create/destroy databases",
+ userName);
+ }
+
+ /* Make sure we are not mucking with the template database */
+ if (!strcmp(dbname, "template1"))
+ {
+ elog(WARN, "%s cannot be executed on the template database.", command);
+ }
+
+ /* Check to make sure database is not the currently open database */
+ if (!strcmp(dbname, GetDatabaseName()))
+ {
+ elog(WARN, "%s cannot be executed on an open database", command);
+ }
+
+ /* Check to make sure database is owned by this user */
+
+ /*
+ * need the reldesc to get the database owner out of dbtup and to set
+ * a write lock on it.
+ */
+ dbrel = heap_openr(DatabaseRelationName);
+
+ if (!RelationIsValid(dbrel))
+ elog(FATAL, "%s: cannot open relation \"%-.*s\"",
+ command, DatabaseRelationName);
+
+ /*
+ * Acquire a write lock on pg_database from the beginning to avoid
+ * upgrading a read lock to a write lock. Upgrading causes long
+ * delays when multiple 'createdb's or 'destroydb's are run simult.
+ * -mer 7/3/91
+ */
+ RelationSetLockForWrite(dbrel);
+ dbtup = get_pg_dbtup(command, dbname, dbrel);
+ dbfound = HeapTupleIsValid(dbtup);
+
+ if (dbfound)
+ {
+ dbowner = (Oid) heap_getattr(dbtup, InvalidBuffer,
+ Anum_pg_database_datdba,
+ RelationGetTupleDescriptor(dbrel),
+ (char *) NULL);
+ *dbIdP = dbtup->t_oid;
+ }
+ else
+ {
+ *dbIdP = InvalidOid;
+ }
+
+ heap_close(dbrel);
+
+ /*
+ * Now be sure that the user is allowed to do this.
+ */
+
+ if (dbfound && !strcmp(command, "createdb"))
+ {
+
+ elog(WARN, "createdb: database %s already exists.", dbname);
+
+ }
+ else if (!dbfound && !strcmp(command, "destroydb"))
+ {
+
+ elog(WARN, "destroydb: database %s does not exist.", dbname);
+
+ }
+ else if (dbfound && !strcmp(command, "destroydb")
+ && dbowner != *userIdP && use_super == false)
+ {
+
+ elog(WARN, "%s: database %s is not owned by you.", command, dbname);
+
+ }
}
/*
- * stop_vacuum() -- stop the vacuum daemon on the database, if one is
- * running.
+ * stop_vacuum() -- stop the vacuum daemon on the database, if one is
+ * running.
*/
static void
stop_vacuum(char *dbname)
{
- char filename[256];
- FILE *fp;
- int pid;
-
- sprintf(filename, "%s%cbase%c%s%c%s.vacuum", DataDir, SEP_CHAR, SEP_CHAR,
- dbname, SEP_CHAR, dbname);
- if ((fp = AllocateFile(filename, "r")) != NULL) {
- fscanf(fp, "%d", &pid);
- FreeFile(fp);
- if (kill(pid, SIGKILLDAEMON1) < 0) {
- elog(WARN, "can't kill vacuum daemon (pid %d) on %s",
- pid, dbname);
+ char filename[256];
+ FILE *fp;
+ int pid;
+
+ sprintf(filename, "%s%cbase%c%s%c%s.vacuum", DataDir, SEP_CHAR, SEP_CHAR,
+ dbname, SEP_CHAR, dbname);
+ if ((fp = AllocateFile(filename, "r")) != NULL)
+ {
+ fscanf(fp, "%d", &pid);
+ FreeFile(fp);
+ if (kill(pid, SIGKILLDAEMON1) < 0)
+ {
+ elog(WARN, "can't kill vacuum daemon (pid %d) on %s",
+ pid, dbname);
+ }
}
- }
}
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 9aa6da82ca6..b9f1a273398 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* keywords.c--
- * lexical token lookup for reserved words in postgres SQL
+ * lexical token lookup for reserved words in postgres SQL
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.14 1997/09/04 13:24:26 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.15 1997/09/07 04:44:47 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,202 +20,204 @@
#include "parse.h"
#include "utils/elog.h"
#include "parser/keywords.h"
-#include "parser/dbcommands.h" /* createdb, destroydb stop_vacuum */
+#include "parser/dbcommands.h" /* createdb, destroydb stop_vacuum */
/*
* List of (keyword-name, keyword-token-value) pairs.
*
* !!WARNING!!: This list must be sorted, because binary
- * search is used to locate entries.
+ * search is used to locate entries.
*/
static ScanKeyword ScanKeywords[] = {
- /* name value */
- { "abort", ABORT_TRANS },
- { "acl", ACL },
- { "add", ADD },
- { "after", AFTER },
- { "aggregate", AGGREGATE },
- { "all", ALL },
- { "alter", ALTER },
- { "analyze", ANALYZE },
- { "and", AND },
- { "append", APPEND },
- { "archIve", ARCHIVE }, /* XXX crooked: I < _ */
- { "arch_store", ARCH_STORE },
- { "archive", ARCHIVE }, /* XXX crooked: i > _ */
- { "as", AS },
- { "asc", ASC },
- { "backward", BACKWARD },
- { "before", BEFORE },
- { "begin", BEGIN_TRANS },
- { "between", BETWEEN },
- { "binary", BINARY },
- { "both", BOTH },
- { "by", BY },
- { "cast", CAST },
- { "change", CHANGE },
- { "check", CHECK },
- { "close", CLOSE },
- { "cluster", CLUSTER },
- { "column", COLUMN },
- { "commit", COMMIT },
- { "constraint", CONSTRAINT },
- { "copy", COPY },
- { "create", CREATE },
- { "cross", CROSS },
- { "current", CURRENT },
- { "cursor", CURSOR },
- { "database", DATABASE },
- { "day", DAYINTERVAL },
- { "declare", DECLARE },
- { "default", DEFAULT },
- { "delete", DELETE },
- { "delimiters", DELIMITERS },
- { "desc", DESC },
- { "distinct", DISTINCT },
- { "do", DO },
- { "drop", DROP },
- { "end", END_TRANS },
- { "execute", EXECUTE },
- { "exists", EXISTS },
- { "explain", EXPLAIN },
- { "extend", EXTEND },
- { "extract", EXTRACT },
- { "fetch", FETCH },
- { "for", FOR },
- { "forward", FORWARD },
- { "from", FROM },
- { "full", FULL },
- { "function", FUNCTION },
- { "grant", GRANT },
- { "group", GROUP },
- { "having", HAVING },
- { "heavy", HEAVY },
- { "hour", HOURINTERVAL },
- { "in", IN },
- { "index", INDEX },
- { "inherits", INHERITS },
- { "inner", INNERJOIN },
- { "insert", INSERT },
- { "instead", INSTEAD },
- { "interval", INTERVAL },
- { "into", INTO },
- { "is", IS },
- { "isnull", ISNULL },
- { "join", JOIN },
- { "language", LANGUAGE },
- { "leading", LEADING },
- { "left", LEFT },
- { "light", LIGHT },
- { "like", LIKE },
- { "listen", LISTEN },
- { "load", LOAD },
- { "local", LOCAL },
- { "merge", MERGE },
- { "minute", MINUTEINTERVAL },
- { "month", MONTHINTERVAL },
- { "move", MOVE },
- { "natural", NATURAL },
- { "new", NEW },
- { "none", NONE },
- { "not", NOT },
- { "nothing", NOTHING },
- { "notify", NOTIFY },
- { "notnull", NOTNULL },
- { "null", PNULL },
- { "oids", OIDS },
- { "on", ON },
- { "operator", OPERATOR },
- { "option", OPTION },
- { "or", OR },
- { "order", ORDER },
- { "outer", OUTERJOIN },
- { "position", POSITION },
- { "privileges", PRIVILEGES },
- { "procedure", PROCEDURE },
- { "public", PUBLIC },
- { "purge", PURGE },
- { "recipe", RECIPE },
- { "rename", RENAME },
- { "replace", REPLACE },
- { "reset", RESET },
- { "retrieve", RETRIEVE },
- { "returns", RETURNS },
- { "revoke", REVOKE },
- { "right", RIGHT },
- { "rollback", ROLLBACK },
- { "rule", RULE },
- { "second", SECONDINTERVAL },
- { "select", SELECT },
- { "sequence", SEQUENCE },
- { "set", SET },
- { "setof", SETOF },
- { "show", SHOW },
- { "stdin", STDIN },
- { "stdout", STDOUT },
- { "store", STORE },
- { "substring", SUBSTRING },
- { "table", TABLE },
- { "time", TIME },
- { "to", TO },
- { "transaction", TRANSACTION },
- { "trailing", TRAILING },
- { "trigger", TRIGGER },
- { "trim", TRIM },
- { "type", P_TYPE },
- { "union", UNION },
- { "unique", UNIQUE },
- { "update", UPDATE },
- { "using", USING },
- { "vacuum", VACUUM },
- { "values", VALUES },
- { "verbose", VERBOSE },
- { "version", VERSION },
- { "view", VIEW },
- { "where", WHERE },
- { "with", WITH },
- { "work", WORK },
- { "year", YEARINTERVAL },
- { "zone", ZONE },
+ /* name value */
+ {"abort", ABORT_TRANS},
+ {"acl", ACL},
+ {"add", ADD},
+ {"after", AFTER},
+ {"aggregate", AGGREGATE},
+ {"all", ALL},
+ {"alter", ALTER},
+ {"analyze", ANALYZE},
+ {"and", AND},
+ {"append", APPEND},
+ {"archIve", ARCHIVE}, /* XXX crooked: I < _ */
+ {"arch_store", ARCH_STORE},
+ {"archive", ARCHIVE}, /* XXX crooked: i > _ */
+ {"as", AS},
+ {"asc", ASC},
+ {"backward", BACKWARD},
+ {"before", BEFORE},
+ {"begin", BEGIN_TRANS},
+ {"between", BETWEEN},
+ {"binary", BINARY},
+ {"both", BOTH},
+ {"by", BY},
+ {"cast", CAST},
+ {"change", CHANGE},
+ {"check", CHECK},
+ {"close", CLOSE},
+ {"cluster", CLUSTER},
+ {"column", COLUMN},
+ {"commit", COMMIT},
+ {"constraint", CONSTRAINT},
+ {"copy", COPY},
+ {"create", CREATE},
+ {"cross", CROSS},
+ {"current", CURRENT},
+ {"cursor", CURSOR},
+ {"database", DATABASE},
+ {"day", DAYINTERVAL},
+ {"declare", DECLARE},
+ {"default", DEFAULT},
+ {"delete", DELETE},
+ {"delimiters", DELIMITERS},
+ {"desc", DESC},
+ {"distinct", DISTINCT},
+ {"do", DO},
+ {"drop", DROP},
+ {"end", END_TRANS},
+ {"execute", EXECUTE},
+ {"exists", EXISTS},
+ {"explain", EXPLAIN},
+ {"extend", EXTEND},
+ {"extract", EXTRACT},
+ {"fetch", FETCH},
+ {"for", FOR},
+ {"forward", FORWARD},
+ {"from", FROM},
+ {"full", FULL},
+ {"function", FUNCTION},
+ {"grant", GRANT},
+ {"group", GROUP},
+ {"having", HAVING},
+ {"heavy", HEAVY},
+ {"hour", HOURINTERVAL},
+ {"in", IN},
+ {"index", INDEX},
+ {"inherits", INHERITS},
+ {"inner", INNERJOIN},
+ {"insert", INSERT},
+ {"instead", INSTEAD},
+ {"interval", INTERVAL},
+ {"into", INTO},
+ {"is", IS},
+ {"isnull", ISNULL},
+ {"join", JOIN},
+ {"language", LANGUAGE},
+ {"leading", LEADING},
+ {"left", LEFT},
+ {"light", LIGHT},
+ {"like", LIKE},
+ {"listen", LISTEN},
+ {"load", LOAD},
+ {"local", LOCAL},
+ {"merge", MERGE},
+ {"minute", MINUTEINTERVAL},
+ {"month", MONTHINTERVAL},
+ {"move", MOVE},
+ {"natural", NATURAL},
+ {"new", NEW},
+ {"none", NONE},
+ {"not", NOT},
+ {"nothing", NOTHING},
+ {"notify", NOTIFY},
+ {"notnull", NOTNULL},
+ {"null", PNULL},
+ {"oids", OIDS},
+ {"on", ON},
+ {"operator", OPERATOR},
+ {"option", OPTION},
+ {"or", OR},
+ {"order", ORDER},
+ {"outer", OUTERJOIN},
+ {"position", POSITION},
+ {"privileges", PRIVILEGES},
+ {"procedure", PROCEDURE},
+ {"public", PUBLIC},
+ {"purge", PURGE},
+ {"recipe", RECIPE},
+ {"rename", RENAME},
+ {"replace", REPLACE},
+ {"reset", RESET},
+ {"retrieve", RETRIEVE},
+ {"returns", RETURNS},
+ {"revoke", REVOKE},
+ {"right", RIGHT},
+ {"rollback", ROLLBACK},
+ {"rule", RULE},
+ {"second", SECONDINTERVAL},
+ {"select", SELECT},
+ {"sequence", SEQUENCE},
+ {"set", SET},
+ {"setof", SETOF},
+ {"show", SHOW},
+ {"stdin", STDIN},
+ {"stdout", STDOUT},
+ {"store", STORE},
+ {"substring", SUBSTRING},
+ {"table", TABLE},
+ {"time", TIME},
+ {"to", TO},
+ {"transaction", TRANSACTION},
+ {"trailing", TRAILING},
+ {"trigger", TRIGGER},
+ {"trim", TRIM},
+ {"type", P_TYPE},
+ {"union", UNION},
+ {"unique", UNIQUE},
+ {"update", UPDATE},
+ {"using", USING},
+ {"vacuum", VACUUM},
+ {"values", VALUES},
+ {"verbose", VERBOSE},
+ {"version", VERSION},
+ {"view", VIEW},
+ {"where", WHERE},
+ {"with", WITH},
+ {"work", WORK},
+ {"year", YEARINTERVAL},
+ {"zone", ZONE},
};
-ScanKeyword *
+ScanKeyword *
ScanKeywordLookup(char *text)
{
- ScanKeyword *low = &ScanKeywords[0];
- ScanKeyword *high = endof(ScanKeywords) - 1;
- ScanKeyword *middle;
- int difference;
-
- while (low <= high) {
- middle = low + (high - low) / 2;
- difference = strcmp(middle->name, text);
- if (difference == 0)
- return (middle);
- else if (difference < 0)
- low = middle + 1;
- else
- high = middle - 1;
- }
-
- return (NULL);
+ ScanKeyword *low = &ScanKeywords[0];
+ ScanKeyword *high = endof(ScanKeywords) - 1;
+ ScanKeyword *middle;
+ int difference;
+
+ while (low <= high)
+ {
+ middle = low + (high - low) / 2;
+ difference = strcmp(middle->name, text);
+ if (difference == 0)
+ return (middle);
+ else if (difference < 0)
+ low = middle + 1;
+ else
+ high = middle - 1;
+ }
+
+ return (NULL);
}
#ifdef NOT_USED
-char*
+char *
AtomValueGetString(int atomval)
{
- ScanKeyword *low = &ScanKeywords[0];
- ScanKeyword *high = endof(ScanKeywords) - 1;
- int keyword_list_length = (high-low);
- int i;
-
- for (i=0; i < keyword_list_length ; i++ )
- if (ScanKeywords[i].value == atomval )
- return(ScanKeywords[i].name);
-
- elog(WARN,"AtomGetString called with bogus atom # : %d", atomval );
- return(NULL);
+ ScanKeyword *low = &ScanKeywords[0];
+ ScanKeyword *high = endof(ScanKeywords) - 1;
+ int keyword_list_length = (high - low);
+ int i;
+
+ for (i = 0; i < keyword_list_length; i++)
+ if (ScanKeywords[i].value == atomval)
+ return (ScanKeywords[i].name);
+
+ elog(WARN, "AtomGetString called with bogus atom # : %d", atomval);
+ return (NULL);
}
+
#endif
diff --git a/src/backend/parser/parse_query.c b/src/backend/parser/parse_query.c
index b19b291769f..5d144660a48 100644
--- a/src/backend/parser/parse_query.c
+++ b/src/backend/parser/parse_query.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* parse_query.c--
- * take an "optimizable" stmt and make the query tree that
- * the planner requires.
+ * take an "optimizable" stmt and make the query tree that
+ * the planner requires.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.18 1997/08/22 00:02:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.19 1997/09/07 04:44:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,8 +23,8 @@
#include "utils/builtins.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/acl.h" /* for ACL_NO_PRIV_WARNING */
+#include "utils/rel.h" /* Relation stuff */
#include "utils/syscache.h"
#include "catalog/pg_type.h"
@@ -38,680 +38,744 @@
#include "nodes/parsenodes.h"
#include "nodes/makefuncs.h"
-static void checkTargetTypes(ParseState *pstate, char *target_colname,
- char *refname, char *colname);
+static void
+checkTargetTypes(ParseState * pstate, char *target_colname,
+ char *refname, char *colname);
-Oid *param_type_info;
-int pfunc_num_args;
+Oid *param_type_info;
+int pfunc_num_args;
/* given refname, return a pointer to the range table entry */
-RangeTblEntry *
-refnameRangeTableEntry(List *rtable, char *refname)
+RangeTblEntry *
+refnameRangeTableEntry(List * rtable, char *refname)
{
- List *temp;
-
- foreach(temp, rtable) {
- RangeTblEntry *rte = lfirst(temp);
-
- if (!strcmp(rte->refname, refname))
- return rte;
- }
- return NULL;
+ 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)
+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);
+ 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)
+RangeTblEntry *
+colnameRangeTableEntry(ParseState * pstate, char *colname)
{
- List *et;
- List *rtable;
- RangeTblEntry *rte_result;
+ List *et;
+ List *rtable;
+ RangeTblEntry *rte_result;
- if (pstate->p_is_rule)
- rtable = lnext(lnext(pstate->p_rtable));
- else
- rtable = pstate->p_rtable;
+ 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);
+ 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;
+ 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 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,
- TimeRange *timeRange)
+RangeTblEntry *
+addRangeTableEntry(ParseState * pstate,
+ char *relname,
+ char *refname,
+ bool inh, bool inFromCl,
+ TimeRange * timeRange)
{
- 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 archive,inheritance,union,version
- * or recursive (transitive closure)
- * [we don't support them all -- ay 9/94 ]
- */
- rte->inh = inh;
-
- rte->timeRange = timeRange;
-
- /* RelOID */
- rte->relid = RelationGetRelationId(relation);
-
- rte->archive = false;
-
- 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;
+ 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 archive,inheritance,union,version or
+ * recursive (transitive closure) [we don't support them all -- ay
+ * 9/94 ]
+ */
+ rte->inh = inh;
+
+ rte->timeRange = timeRange;
+
+ /* RelOID */
+ rte->relid = RelationGetRelationId(relation);
+
+ rte->archive = false;
+
+ 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
+ * makes a list of attributes
+ * assumes reldesc caching works
*/
-List *
-expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
+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, NULL);
-
- 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);
+ 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, NULL);
+
+ 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);
}
TimeQual
makeTimeRange(char *datestring1,
- char *datestring2,
- int timecode) /* 0 = snapshot , 1 = timerange */
+ char *datestring2,
+ int timecode) /* 0 = snapshot , 1 = timerange */
{
- TimeQual qual = NULL;
- AbsoluteTime t1,t2;
-
- switch (timecode) {
- case 0:
- if (datestring1 == NULL) {
- elog(WARN, "MakeTimeRange: bad snapshot arg");
- }
- t1 = nabstimein(datestring1);
- if (!AbsoluteTimeIsValid(t1)) {
- elog(WARN, "bad snapshot time: \"%s\"",
- datestring1);
- }
- qual = TimeFormSnapshotTimeQual(t1);
- break;
- case 1:
- if (datestring1 == NULL) {
- t1 = NOSTART_ABSTIME;
- } else {
- t1 = nabstimein(datestring1);
- if (!AbsoluteTimeIsValid(t1)) {
- elog(WARN,
- "bad range start time: \"%s\"",
- datestring1);
- }
- }
- if (datestring2 == NULL) {
- t2 = NOEND_ABSTIME;
- } else {
- t2 = nabstimein(datestring2);
- if (!AbsoluteTimeIsValid(t2)) {
- elog(WARN,
- "bad range end time: \"%s\"",
- datestring2);
- }
+ TimeQual qual = NULL;
+ AbsoluteTime t1,
+ t2;
+
+ switch (timecode)
+ {
+ case 0:
+ if (datestring1 == NULL)
+ {
+ elog(WARN, "MakeTimeRange: bad snapshot arg");
+ }
+ t1 = nabstimein(datestring1);
+ if (!AbsoluteTimeIsValid(t1))
+ {
+ elog(WARN, "bad snapshot time: \"%s\"",
+ datestring1);
+ }
+ qual = TimeFormSnapshotTimeQual(t1);
+ break;
+ case 1:
+ if (datestring1 == NULL)
+ {
+ t1 = NOSTART_ABSTIME;
+ }
+ else
+ {
+ t1 = nabstimein(datestring1);
+ if (!AbsoluteTimeIsValid(t1))
+ {
+ elog(WARN,
+ "bad range start time: \"%s\"",
+ datestring1);
+ }
+ }
+ if (datestring2 == NULL)
+ {
+ t2 = NOEND_ABSTIME;
+ }
+ else
+ {
+ t2 = nabstimein(datestring2);
+ if (!AbsoluteTimeIsValid(t2))
+ {
+ elog(WARN,
+ "bad range end time: \"%s\"",
+ datestring2);
+ }
+ }
+ qual = TimeFormRangedTimeQual(t1, t2);
+ break;
+ default:
+ elog(WARN, "MakeTimeRange: internal parser error");
}
- qual = TimeFormRangedTimeQual(t1,t2);
- break;
- default:
- elog(WARN, "MakeTimeRange: internal parser error");
- }
- return qual;
+ return qual;
}
static void
-disallow_setop(char *op, Type optype, Node *operand)
+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);
- }
+ 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 *
+static Node *
make_operand(char *opname,
- Node *tree,
- Oid orig_typeId,
- Oid true_typeId)
+ Node * tree,
+ Oid orig_typeId,
+ Oid true_typeId)
{
- Node *result;
- Type true_type;
- Datum val;
- Oid infunc;
-
- if (tree != NULL) {
- result = tree;
- true_type = get_id_type(true_typeId);
- disallow_setop(opname, true_type, result);
- if (true_typeId != orig_typeId) { /* must coerce */
- Const *con= (Const *)result;
-
- Assert(nodeTag(result)==T_Const);
- val = (Datum)textout((struct varlena *)
- con->constvalue);
- infunc = typeid_get_retinfunc(true_typeId);
- con = makeNode(Const);
- con->consttype = true_typeId;
- con->constlen = tlen(true_type);
- con->constvalue = (Datum)fmgr(infunc,
- val,
- get_typelem(true_typeId),
- -1 /* for varchar() type */);
- con->constisnull = false;
- con->constbyval = true;
- con->constisset = false;
- result = (Node *)con;
+ Node *result;
+ Type true_type;
+ Datum val;
+ Oid infunc;
+
+ if (tree != NULL)
+ {
+ result = tree;
+ true_type = get_id_type(true_typeId);
+ disallow_setop(opname, true_type, result);
+ if (true_typeId != orig_typeId)
+ { /* must coerce */
+ Const *con = (Const *) result;
+
+ Assert(nodeTag(result) == T_Const);
+ val = (Datum) textout((struct varlena *)
+ con->constvalue);
+ infunc = typeid_get_retinfunc(true_typeId);
+ con = makeNode(Const);
+ con->consttype = true_typeId;
+ con->constlen = tlen(true_type);
+ con->constvalue = (Datum) fmgr(infunc,
+ val,
+ get_typelem(true_typeId),
+ -1 /* for varchar() type */ );
+ con->constisnull = false;
+ con->constbyval = true;
+ con->constisset = false;
+ result = (Node *) con;
+ }
+ }
+ else
+ {
+ Const *con = makeNode(Const);
+
+ con->consttype = true_typeId;
+ con->constlen = 0;
+ con->constvalue = (Datum) (struct varlena *) NULL;
+ con->constisnull = true;
+ con->constbyval = true;
+ con->constisset = false;
+ result = (Node *) con;
}
- }else {
- Const *con= makeNode(Const);
-
- con->consttype = true_typeId;
- con->constlen = 0;
- con->constvalue = (Datum)(struct varlena *)NULL;
- con->constisnull = true;
- con->constbyval = true;
- con->constisset = false;
- result = (Node *)con;
- }
-
- return result;
+
+ return result;
}
-Expr *
-make_op(char *opname, Node *ltree, Node *rtree)
+Expr *
+make_op(char *opname, Node * ltree, Node * rtree)
{
- Oid ltypeId, rtypeId;
- Operator temp;
- OperatorTupleForm opform;
- Oper *newop;
- Node *left, *right;
- Expr *result;
-
- if (rtree == NULL) {
-
- /* right operator */
- ltypeId = (ltree==NULL) ? UNKNOWNOID : exprType(ltree);
- temp = right_oper(opname, ltypeId);
- opform = (OperatorTupleForm) GETSTRUCT(temp);
- left = make_operand(opname, ltree, ltypeId, opform->oprleft);
- right = NULL;
-
- }else if (ltree == NULL) {
-
- /* left operator */
- rtypeId = (rtree==NULL) ? UNKNOWNOID : exprType(rtree);
- temp = left_oper(opname, rtypeId);
- opform = (OperatorTupleForm) GETSTRUCT(temp);
- right = make_operand(opname, rtree, rtypeId, opform->oprright);
- left = NULL;
-
- }else {
- char *outstr;
- Oid infunc, outfunc;
- Type newtype;
+ Oid ltypeId,
+ rtypeId;
+ Operator temp;
+ OperatorTupleForm opform;
+ Oper *newop;
+ Node *left,
+ *right;
+ Expr *result;
+
+ if (rtree == NULL)
+ {
+
+ /* right operator */
+ ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
+ temp = right_oper(opname, ltypeId);
+ opform = (OperatorTupleForm) GETSTRUCT(temp);
+ left = make_operand(opname, ltree, ltypeId, opform->oprleft);
+ right = NULL;
+
+ }
+ else if (ltree == NULL)
+ {
+
+ /* left operator */
+ rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
+ temp = left_oper(opname, rtypeId);
+ opform = (OperatorTupleForm) GETSTRUCT(temp);
+ right = make_operand(opname, rtree, rtypeId, opform->oprright);
+ left = NULL;
+
+ }
+ else
+ {
+ char *outstr;
+ Oid infunc,
+ outfunc;
+ Type newtype;
#define CONVERTABLE_TYPE(t) ( (t) == INT2OID || \
- (t) == INT4OID || \
- (t) == OIDOID || \
- (t) == FLOAT4OID || \
- (t) == FLOAT8OID || \
- (t) == CASHOID)
-
- /* binary operator */
- ltypeId = (ltree==NULL) ? UNKNOWNOID : exprType(ltree);
- rtypeId = (rtree==NULL) ? UNKNOWNOID : exprType(rtree);
-
- /* convert constant when using a const of a numeric type
- and a non-const of another numeric type */
- if (CONVERTABLE_TYPE(ltypeId) && nodeTag(ltree) != T_Const &&
- CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
- !((Const *)rtree)->constiscast) {
- outfunc = typeid_get_retoutfunc(rtypeId);
- infunc = typeid_get_retinfunc(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);
+ (t) == INT4OID || \
+ (t) == OIDOID || \
+ (t) == FLOAT4OID || \
+ (t) == FLOAT8OID || \
+ (t) == CASHOID)
+
+ /* binary operator */
+ ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
+ rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
+
+ /*
+ * convert constant when using a const of a numeric type and a
+ * non-const of another numeric type
+ */
+ if (CONVERTABLE_TYPE(ltypeId) && nodeTag(ltree) != T_Const &&
+ CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
+ !((Const *) rtree)->constiscast)
+ {
+ outfunc = typeid_get_retoutfunc(rtypeId);
+ infunc = typeid_get_retinfunc(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);
+ }
+
+ 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);
+ 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);
+ }
+
+ temp = oper(opname, ltypeId, rtypeId, false);
+ opform = (OperatorTupleForm) GETSTRUCT(temp);
+ left = make_operand(opname, ltree, ltypeId, opform->oprleft);
+ right = make_operand(opname, rtree, rtypeId, opform->oprright);
}
- 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);
- 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);
+ newop = makeOper(oprid(temp), /* opno */
+ InvalidOid,/* opid */
+ opform->oprresult, /* operator result type */
+ 0,
+ NULL);
+
+ result = makeNode(Expr);
+ result->typeOid = opform->oprresult;
+ result->opType = OP_EXPR;
+ result->oper = (Node *) newop;
+
+ if (!left)
+ {
+ result->args = lcons(right, NIL);
+ }
+ else if (!right)
+ {
+ result->args = lcons(left, NIL);
+ }
+ else
+ {
+ result->args = lcons(left, lcons(right, NIL));
}
- temp = oper(opname, ltypeId, rtypeId, false);
- opform = (OperatorTupleForm) GETSTRUCT(temp);
- left = make_operand(opname, ltree, ltypeId, opform->oprleft);
- right = make_operand(opname, rtree, rtypeId, opform->oprright);
- }
-
- newop = makeOper(oprid(temp), /* opno */
- InvalidOid, /* opid */
- opform->oprresult, /* operator result type */
- 0,
- NULL);
-
- result = makeNode(Expr);
- result->typeOid = opform->oprresult;
- result->opType = OP_EXPR;
- result->oper = (Node *)newop;
-
- if (!left) {
- result->args = lcons(right, NIL);
- } else if (!right) {
- result->args = lcons(left, NIL);
- } else {
- result->args = lcons(left, lcons(right, NIL));
- }
-
- return result;
+ 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)));
+ int attid;
+ Oid vartype;
+ Relation rd;
+
+ rd = heap_open(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);
+ {
+ 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)
+Var *
+make_var(ParseState * pstate, char *refname, char *attrname, Oid * type_id)
{
- Var *varnode;
- int vnum, attid;
- Oid vartypeid;
- Relation rd;
- RangeTblEntry *rte;
+ Var *varnode;
+ int vnum,
+ attid;
+ Oid vartypeid;
+ Relation rd;
+ RangeTblEntry *rte;
- rte = refnameRangeTableEntry(pstate->p_rtable, refname);
- if (rte == NULL)
- rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
+ rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+ if (rte == NULL)
+ rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
- vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
+ vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
- rd = heap_open(rte->relid);
+ 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 = nf_varattno(rd, attrname);
+ if (attid == InvalidAttrNumber)
+ elog(WARN, "Invalid attribute %s\n", attrname);
+ vartypeid = att_typeid(rd, attid);
- varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
+ varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
- heap_close(rd);
+ heap_close(rd);
- *type_id = vartypeid;
- return varnode;
+ *type_id = vartypeid;
+ return varnode;
}
/*
- * make_array_ref() -- Make an array reference node.
+ * make_array_ref() -- Make an array reference node.
*
- * Array references can hang off of arbitrary nested dot (or
- * function invocation) expressions. This routine takes a
- * tree generated by ParseFunc() and an array index and
- * generates a new array reference tree. We do some simple
- * typechecking to be sure the dereference is valid in the
- * type system, but we don't do any bounds checking here.
+ * Array references can hang off of arbitrary nested dot (or
+ * function invocation) expressions. This routine takes a
+ * tree generated by ParseFunc() and an array index and
+ * generates a new array reference tree. We do some simple
+ * typechecking to be sure the dereference is valid in the
+ * type system, but we don't do any bounds checking here.
*
- * indirection is a list of A_Indices
+ * indirection is a list of A_Indices
*/
-ArrayRef *
-make_array_ref(Node *expr,
- List *indirection)
+ArrayRef *
+make_array_ref(Node * expr,
+ List * indirection)
{
- Oid typearray;
- HeapTuple type_tuple;
- TypeTupleForm type_struct_array, type_struct_element;
- ArrayRef *aref;
- Oid reftype;
- List *upperIndexpr=NIL;
- List *lowerIndexpr=NIL;
-
- typearray = exprType(expr);
-
- type_tuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(typearray),
- 0,0,0);
-
- if (!HeapTupleIsValid(type_tuple))
- elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
- 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, "make_array_ref: type %s is not an array",
- (Name)&(type_struct_array->typname.data[0]));
- }
-
- /* get the type tuple for the element type */
- type_tuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type_struct_array->typelem),
- 0,0,0);
- if (!HeapTupleIsValid(type_tuple))
- elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
- typearray);
-
- type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
-
- while(indirection!=NIL) {
- A_Indices *ind = lfirst(indirection);
- if (ind->lidx) {
- /* XXX assumes all lower indices non null in this case
- */
- lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
+ Oid typearray;
+ HeapTuple type_tuple;
+ TypeTupleForm type_struct_array,
+ type_struct_element;
+ ArrayRef *aref;
+ Oid reftype;
+ List *upperIndexpr = NIL;
+ List *lowerIndexpr = NIL;
+
+ typearray = exprType(expr);
+
+ type_tuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(typearray),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(type_tuple))
+ elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
+ 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, "make_array_ref: type %s is not an array",
+ (Name) & (type_struct_array->typname.data[0]));
+ }
+
+ /* get the type tuple for the element type */
+ type_tuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type_struct_array->typelem),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(type_tuple))
+ elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
+ typearray);
+
+ type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
+
+ while (indirection != NIL)
+ {
+ A_Indices *ind = lfirst(indirection);
+
+ if (ind->lidx)
+ {
+
+ /*
+ * XXX assumes all lower indices non null in this case
+ */
+ lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
+ }
+ upperIndexpr = lappend(upperIndexpr, ind->uidx);
+ indirection = lnext(indirection);
}
- upperIndexpr = lappend(upperIndexpr, ind->uidx);
- indirection = lnext(indirection);
- }
- aref = makeNode(ArrayRef);
- aref->refattrlength = type_struct_array->typlen;
- aref->refelemlength = type_struct_element->typlen;
- aref->refelemtype = type_struct_array->typelem;
- aref->refelembyval = type_struct_element->typbyval;
- aref->refupperindexpr = upperIndexpr;
- aref->reflowerindexpr = lowerIndexpr;
- aref->refexpr = expr;
- aref->refassgnexpr = NULL;
-
- if (lowerIndexpr == NIL) /* accessing a single array element */
- reftype = aref->refelemtype;
- else /* request to clip a part of the array, the result is another array */
- reftype = typearray;
-
- /* we change it to reflect the true type; since the original refelemtype
- * doesn't seem to get used anywhere. - ay 10/94
- */
- aref->refelemtype = reftype;
-
- return aref;
+ aref = makeNode(ArrayRef);
+ aref->refattrlength = type_struct_array->typlen;
+ aref->refelemlength = type_struct_element->typlen;
+ aref->refelemtype = type_struct_array->typelem;
+ aref->refelembyval = type_struct_element->typbyval;
+ aref->refupperindexpr = upperIndexpr;
+ aref->reflowerindexpr = lowerIndexpr;
+ aref->refexpr = expr;
+ aref->refassgnexpr = NULL;
+
+ if (lowerIndexpr == NIL) /* accessing a single array element */
+ reftype = aref->refelemtype;
+ else
+/* request to clip a part of the array, the result is another array */
+ reftype = typearray;
+
+ /*
+ * we change it to reflect the true type; since the original
+ * refelemtype doesn't seem to get used anywhere. - ay 10/94
+ */
+ aref->refelemtype = reftype;
+
+ return aref;
}
-ArrayRef *
-make_array_set(Expr *target_expr,
- List *upperIndexpr,
- List *lowerIndexpr,
- Expr *expr)
+ArrayRef *
+make_array_set(Expr * target_expr,
+ List * upperIndexpr,
+ List * lowerIndexpr,
+ Expr * expr)
{
- Oid typearray;
- HeapTuple type_tuple;
- TypeTupleForm type_struct_array;
- TypeTupleForm type_struct_element;
- ArrayRef *aref;
- Oid reftype;
-
- typearray = exprType((Node*)target_expr);
-
- type_tuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(typearray),
- 0,0,0);
-
- if (!HeapTupleIsValid(type_tuple))
- elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
- 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, "make_array_ref: type %s is not an array",
- (Name)&(type_struct_array->typname.data[0]));
- }
- /* get the type tuple for the element type */
- type_tuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type_struct_array->typelem),
- 0,0,0);
-
- if (!HeapTupleIsValid(type_tuple))
- elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
- typearray);
-
- type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
-
- aref = makeNode(ArrayRef);
- aref->refattrlength = type_struct_array->typlen;
- aref->refelemlength = type_struct_element->typlen;
- aref->refelemtype = type_struct_array->typelem;
- aref->refelembyval = type_struct_element->typbyval;
- aref->refupperindexpr = upperIndexpr;
- aref->reflowerindexpr = lowerIndexpr;
- aref->refexpr = (Node*)target_expr;
- aref->refassgnexpr = (Node*)expr;
-
- if (lowerIndexpr == NIL) /* accessing a single array element */
- reftype = aref->refelemtype;
- else /* request to set a part of the array, by another array */
- reftype = typearray;
-
- aref->refelemtype = reftype;
-
- return aref;
+ Oid typearray;
+ HeapTuple type_tuple;
+ TypeTupleForm type_struct_array;
+ TypeTupleForm type_struct_element;
+ ArrayRef *aref;
+ Oid reftype;
+
+ typearray = exprType((Node *) target_expr);
+
+ type_tuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(typearray),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(type_tuple))
+ elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
+ 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, "make_array_ref: type %s is not an array",
+ (Name) & (type_struct_array->typname.data[0]));
+ }
+ /* get the type tuple for the element type */
+ type_tuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type_struct_array->typelem),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(type_tuple))
+ elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
+ typearray);
+
+ type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
+
+ aref = makeNode(ArrayRef);
+ aref->refattrlength = type_struct_array->typlen;
+ aref->refelemlength = type_struct_element->typlen;
+ aref->refelemtype = type_struct_array->typelem;
+ aref->refelembyval = type_struct_element->typbyval;
+ aref->refupperindexpr = upperIndexpr;
+ aref->reflowerindexpr = lowerIndexpr;
+ aref->refexpr = (Node *) target_expr;
+ aref->refassgnexpr = (Node *) expr;
+
+ if (lowerIndexpr == NIL) /* accessing a single array element */
+ reftype = aref->refelemtype;
+ else
+/* request to set a part of the array, by another array */
+ reftype = typearray;
+
+ aref->refelemtype = reftype;
+
+ return aref;
}
/*
- *
+ *
* make_const -
- *
+ *
* - takes a lispvalue, (as returned to the yacc routine by the lexer)
- * extracts the type, and makes the appropriate type constant
- * by invoking the (c-callable) lisp routine c-make-const
- * via the lisp_call() mechanism
+ * extracts the type, and makes the appropriate type constant
+ * by invoking the (c-callable) lisp routine c-make-const
+ * via the lisp_call() mechanism
*
* eventually, produces a "const" lisp-struct as per nodedefs.cl
- */
-Const *
-make_const(Value *value)
+ */
+Const *
+make_const(Value * value)
{
- Type tp;
- Datum val;
- Const *con;
-
- switch(nodeTag(value)) {
- case T_Integer:
- tp = type("int4");
- val = Int32GetDatum(intVal(value));
- break;
-
- case T_Float:
- {
- float64 dummy;
- tp = type("float8");
-
- dummy = (float64)palloc(sizeof(float64data));
- *dummy = floatVal(value);
-
- val = Float64GetDatum(dummy);
- }
- break;
-
- case T_String:
- tp = type("unknown"); /* unknown for now, will be type coerced */
- val = PointerGetDatum(textin(strVal(value)));
- break;
-
- case T_Null:
- default:
- {
- if (nodeTag(value)!=T_Null)
- elog(NOTICE,"unknown type : %d\n", nodeTag(value));
+ Type tp;
+ Datum val;
+ Const *con;
- /* null const */
- con = makeConst(0, 0, (Datum)NULL, true, false, false, false);
- return con;
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ tp = type("int4");
+ val = Int32GetDatum(intVal(value));
+ break;
+
+ case T_Float:
+ {
+ float64 dummy;
+
+ tp = type("float8");
+
+ dummy = (float64) palloc(sizeof(float64data));
+ *dummy = floatVal(value);
+
+ val = Float64GetDatum(dummy);
+ }
+ break;
+
+ case T_String:
+ tp = type("unknown"); /* unknown for now, will be type coerced */
+ val = PointerGetDatum(textin(strVal(value)));
+ break;
+
+ case T_Null:
+ default:
+ {
+ if (nodeTag(value) != T_Null)
+ elog(NOTICE, "unknown type : %d\n", nodeTag(value));
+
+ /* null const */
+ con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
+ return con;
+ }
}
- }
- con = makeConst(typeid(tp),
- tlen(tp),
- val,
- false,
- tbyval(tp),
- false, /* not a set */
- false);
+ con = makeConst(typeid(tp),
+ tlen(tp),
+ val,
+ false,
+ tbyval(tp),
+ false, /* not a set */
+ false);
- return (con);
+ return (con);
}
/*
@@ -721,87 +785,93 @@ make_const(Value *value)
* used in postquel functions
*/
void
-param_type_init(Oid* typev, int nargs)
+param_type_init(Oid * typev, int nargs)
{
- pfunc_num_args = nargs;
- param_type_info = typev;
+ 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];
+ if ((t > pfunc_num_args) || (t == 0))
+ return InvalidOid;
+ return param_type_info[t - 1];
}
/*
* handleTargetColname -
- * use column names from insert
+ * use column names from insert
*/
void
-handleTargetColname(ParseState *pstate, char **resname,
+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);
+ 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
+ * checks value and target column types
*/
static void
-checkTargetTypes(ParseState *pstate, char *target_colname,
- char *refname, char *colname)
+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;
- }
+ 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);
+ if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
+ elog(WARN, "%s not available in this context", colname);
*/
- rd = heap_open(rte->relid);
+ rd = heap_open(rte->relid);
- resdomno_id = varattno(rd,colname);
- attrtype_id = att_typeid(rd,resdomno_id);
+ 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);
+ 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 != 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);
+ 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);
+ heap_close(rd);
}
-
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index ab4276055cd..99c6ce2bfdb 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -6,14 +6,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.22 1997/08/22 07:12:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.23 1997/09/07 04:44:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <pwd.h>
-#include <sys/param.h> /* for MAXPATHLEN */
+#include <sys/param.h> /* for MAXPATHLEN */
#include "postgres.h"
#include "parser/catalog_utils.h"
@@ -34,456 +34,510 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_type.h"
#include "access/heapam.h"
-#include "optimizer/clauses.h"
+#include "optimizer/clauses.h"
-void init_io(); /* from scan.l */
-void parser_init(Oid *typev, int nargs); /* from gram.y */
-int yyparse(); /* from gram.c */
+void init_io(); /* from scan.l */
+void parser_init(Oid * typev, int nargs); /* from gram.y */
+int yyparse(); /* from gram.c */
-char *parseString; /* the char* which holds the string to be parsed */
-char *parseCh; /* a pointer used during parsing to walk down ParseString*/
+char *parseString; /* the char* which holds the string to be
+ * parsed */
+char *parseCh; /* a pointer used during parsing to walk
+ * down ParseString */
-List *parsetree = NIL;
+List *parsetree = NIL;
#ifdef SETS_FIXED
-static void fixupsets();
-static void define_sets();
+static void fixupsets();
+static void define_sets();
+
#endif
/*
* parser-- returns a list of parse trees
- *
- * CALLER is responsible for free'ing the list returned
+ *
+ * CALLER is responsible for free'ing the list returned
*/
-QueryTreeList *
-parser(char *str, Oid *typev, int nargs)
+QueryTreeList *
+parser(char *str, Oid * typev, int nargs)
{
- QueryTreeList* queryList;
- int yyresult;
+ QueryTreeList *queryList;
+ int yyresult;
#if defined(FLEX_SCANNER)
- extern void DeleteBuffer(void);
-#endif /* FLEX_SCANNER */
-
- init_io();
-
- /* Set things up to read from the string, if there is one */
- parseString = (char *) palloc(strlen(str) + 1);
- memmove(parseString,str,strlen(str)+1);
-
- parser_init(typev, nargs);
- yyresult = yyparse();
+ extern void DeleteBuffer(void);
+
+#endif /* FLEX_SCANNER */
+
+ init_io();
+
+ /* Set things up to read from the string, if there is one */
+ parseString = (char *) palloc(strlen(str) + 1);
+ memmove(parseString, str, strlen(str) + 1);
+
+ parser_init(typev, nargs);
+ yyresult = yyparse();
#if defined(FLEX_SCANNER)
- DeleteBuffer();
-#endif /* FLEX_SCANNER */
-
- clearerr(stdin);
-
- if (yyresult) { /* error */
- return((QueryTreeList*)NULL);
- }
-
- queryList = parse_analyze(parsetree);
-
+ DeleteBuffer();
+#endif /* FLEX_SCANNER */
+
+ clearerr(stdin);
+
+ if (yyresult)
+ { /* error */
+ return ((QueryTreeList *) NULL);
+ }
+
+ queryList = parse_analyze(parsetree);
+
#ifdef SETS_FIXED
- /* Fixing up sets calls the parser, so it reassigns the global
- * variable parsetree. So save the real parsetree.
- */
- savetree = parsetree;
- foreach (parse, savetree) { /* savetree is really a list of parses */
- /* find set definitions embedded in query */
- fixupsets((Query *)lfirst(parse));
+ /*
+ * Fixing up sets calls the parser, so it reassigns the global
+ * variable parsetree. So save the real parsetree.
+ */
+ savetree = parsetree;
+ foreach(parse, savetree)
+ { /* savetree is really a list of parses */
+
+ /* find set definitions embedded in query */
+ fixupsets((Query *) lfirst(parse));
- }
- return savetree;
-#endif
+ }
+ return savetree;
+#endif
- return queryList;
+ return queryList;
}
#ifdef SETS_FIXED
static void
-fixupsets(Query *parse)
+fixupsets(Query * parse)
{
- if (parse == NULL)
- return;
- if (parse->commandType==CMD_UTILITY) /* utility */
- return;
- if (parse->commandType!=CMD_INSERT)
- return;
- define_sets(parse);
+ if (parse == NULL)
+ return;
+ if (parse->commandType == CMD_UTILITY) /* utility */
+ return;
+ if (parse->commandType != CMD_INSERT)
+ return;
+ define_sets(parse);
}
/* Recursively find all of the Consts in the parsetree. Some of
* these may represent a set. The value of the Const will be the
- * query (a string) which defines the set. Call SetDefine to define
+ * query (a string) which defines the set. Call SetDefine to define
* the set, and store the OID of the new set in the Const instead.
*/
static void
-define_sets(Node *clause)
+define_sets(Node * clause)
{
- Oid setoid;
- Type t = type("oid");
- Oid typeoid = typeid(t);
- Size oidsize = tlen(t);
- bool oidbyval = tbyval(t);
-
- if (clause==NULL) {
- return;
- } else if (IsA(clause,LispList)) {
- define_sets(lfirst(clause));
- define_sets(lnext(clause));
- } else if (IsA(clause,Const)) {
- if (get_constisnull((Const)clause) ||
- !get_constisset((Const)clause)) {
- return;
+ Oid setoid;
+ Type t = type("oid");
+ Oid typeoid = typeid(t);
+ Size oidsize = tlen(t);
+ bool oidbyval = tbyval(t);
+
+ if (clause == NULL)
+ {
+ return;
+ }
+ else if (IsA(clause, LispList))
+ {
+ define_sets(lfirst(clause));
+ define_sets(lnext(clause));
+ }
+ else if (IsA(clause, Const))
+ {
+ if (get_constisnull((Const) clause) ||
+ !get_constisset((Const) clause))
+ {
+ return;
+ }
+ setoid = SetDefine(((Const *) clause)->constvalue,
+ get_id_typname(((Const *) clause)->consttype));
+ set_constvalue((Const) clause, setoid);
+ set_consttype((Const) clause, typeoid);
+ set_constlen((Const) clause, oidsize);
+ set_constbyval((Const) clause, oidbyval);
+ }
+ else if (IsA(clause, Iter))
+ {
+ define_sets(((Iter *) clause)->iterexpr);
+ }
+ else if (single_node(clause))
+ {
+ return;
+ }
+ else if (or_clause(clause))
+ {
+ List *temp;
+
+ /* mapcan */
+ foreach(temp, ((Expr *) clause)->args)
+ {
+ define_sets(lfirst(temp));
+ }
}
- setoid = SetDefine(((Const*)clause)->constvalue,
- get_id_typname(((Const*)clause)->consttype));
- set_constvalue((Const)clause, setoid);
- set_consttype((Const)clause,typeoid);
- set_constlen((Const)clause,oidsize);
- set_constbyval((Const)clause,oidbyval);
- } else if ( IsA(clause,Iter) ) {
- define_sets(((Iter*)clause)->iterexpr);
- } else if (single_node (clause)) {
- return;
- } else if (or_clause(clause)) {
- List *temp;
- /* mapcan */
- foreach (temp, ((Expr*)clause)->args) {
- define_sets(lfirst(temp));
+ else if (is_funcclause(clause))
+ {
+ List *temp;
+
+ /* mapcan */
+ foreach(temp, ((Expr *) clause)->args)
+ {
+ define_sets(lfirst(temp));
+ }
}
- } else if (is_funcclause (clause)) {
- List *temp;
- /* mapcan */
- foreach(temp, ((Expr*)clause)->args) {
- define_sets(lfirst(temp));
+ else if (IsA(clause, ArrayRef))
+ {
+ define_sets(((ArrayRef *) clause)->refassgnexpr);
+ }
+ else if (not_clause(clause))
+ {
+ define_sets(get_notclausearg(clause));
+ }
+ else if (is_opclause(clause))
+ {
+ define_sets(get_leftop(clause));
+ define_sets(get_rightop(clause));
}
- } else if (IsA(clause,ArrayRef)) {
- define_sets(((ArrayRef*)clause)->refassgnexpr);
- } else if (not_clause (clause)) {
- define_sets (get_notclausearg (clause));
- } else if (is_opclause (clause)) {
- define_sets(get_leftop (clause));
- define_sets(get_rightop (clause));
- }
}
+
#endif
/* not used
-#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
+#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
*/
-Node *
-parser_typecast(Value *expr, TypeName *typename, int typlen)
+Node *
+parser_typecast(Value * expr, TypeName * typename, int typlen)
{
- /* check for passing non-ints */
- Const *adt;
- Datum lcp;
- Type tp;
- char type_string[16];
- 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, "%d", 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) type(type_string);
- } else {
- tp = (Type) type(typename->name);
- }
-
- len = tlen(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)));
- }
+ /* check for passing non-ints */
+ Const *adt;
+ Datum lcp;
+ Type tp;
+ char type_string[16];
+ 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, "%d", 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) type(type_string);
+ }
+ else
+ {
+ tp = (Type) type(typename->name);
+ }
+
+ len = tlen(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 = instr2 (tp, const_string, typlen);
-
- if (!tbyvalue(tp)) {
+ cp = instr2(tp, const_string, typlen);
+
+ if (!tbyvalue(tp))
+ {
/*
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- memmove(pp, cp, len);
- cp = pp;
- }
+ 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;
+ 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(typeid(tp),
- len,
- (Datum)lcp ,
- false,
- tbyvalue(tp),
- false, /* not a set */
- true /* is cast */);
-
- if (string_palloced)
- pfree(const_string);
-
- return (Node*)adt;
+
+ adt = makeConst(typeid(tp),
+ len,
+ (Datum) lcp,
+ false,
+ tbyvalue(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)
+Node *
+parser_typecast2(Node * expr, Oid exprType, Type tp, int typlen)
{
- /* check for passing non-ints */
- Const *adt;
- Datum lcp;
- int32 len = tlen(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 */
+ /* check for passing non-ints */
+ Const *adt;
+ Datum lcp;
+ int32 len = tlen(tp);
+ char *cp = NULL;
+
+ char *const_string = NULL;
+ bool string_palloced = false;
+
+ Assert(IsA(expr, Const));
+
+ switch (exprType)
{
- float32 floatVal =
- DatumGetFloat32(((Const*)expr)->constvalue);
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", *floatVal);
- break;
+ 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, "%d",
+ (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);
}
- case FLOAT8OID:/* float8 */
+
+ if (!exprType)
{
- float64 floatVal =
- DatumGetFloat64(((Const*)expr)->constvalue);
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", *floatVal);
- break;
+ adt = makeConst(typeid(tp),
+ (Size) 0,
+ (Datum) NULL,
+ true, /* isnull */
+ false, /* was omitted */
+ false, /* not a set */
+ true /* is cast */ );
+ return ((Node *) adt);
}
- case CASHOID: /* money */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d",
- (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(typeid(tp),
- (Size) 0,
- (Datum) NULL,
- true, /* isnull */
- false, /* was omitted */
- false, /* not a set */
- true /* is cast */);
- return ((Node*) adt);
- }
-
- cp = instr2 (tp, const_string, typlen);
-
-
- if (!tbyvalue(tp)) {
+
+ cp = instr2(tp, const_string, typlen);
+
+
+ if (!tbyvalue(tp))
+ {
/*
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- memmove(pp, cp, len);
- cp = pp;
- }
+ 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;
+ 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(typeid(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),typeid(tp) ,
- len,cp);
- */
- if (string_palloced) pfree(const_string);
-
- return ((Node*) adt);
+
+ adt = makeConst(typeid(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),typeid(tp) , len,cp);
+ */
+ if (string_palloced)
+ pfree(const_string);
+
+ return ((Node *) adt);
}
-Aggreg *
-ParseAgg(char *aggname, Oid basetype, Node *target)
+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 = get_id_type(basetype);
- tp2 = get_id_type(vartype);
- elog(NOTICE, "Aggregate type mismatch:");
- elog(WARN, "%s works on %s, not %s", aggname,
- tname(tp1), tname(tp2));
- }
- }
-
- aggreg = makeNode(Aggreg);
- aggreg->aggname = pstrdup(aggname);
- aggreg->basetype = aggform->aggbasetype;
- aggreg->aggtype = fintype;
-
- aggreg->target = target;
-
- return aggreg;
-}
+ 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 = get_id_type(basetype);
+ tp2 = get_id_type(vartype);
+ elog(NOTICE, "Aggregate type mismatch:");
+ elog(WARN, "%s works on %s, not %s", aggname,
+ tname(tp1), tname(tp2));
+ }
+ }
+
+ aggreg = makeNode(Aggreg);
+ aggreg->aggname = pstrdup(aggname);
+ aggreg->basetype = aggform->aggbasetype;
+ aggreg->aggtype = fintype;
+
+ aggreg->target = target;
+
+ return aggreg;
+}
diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c
index 98bf6dba93b..0b944528980 100644
--- a/src/backend/parser/scansup.c
+++ b/src/backend/parser/scansup.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* scansup.c--
- * support routines for the lex/flex scanner, used by both the normal
+ * support routines for the lex/flex scanner, used by both the normal
* backend as well as the bootstrap backend
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.5 1996/11/15 18:38:55 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.6 1997/09/07 04:44:51 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,12 +24,12 @@
#include "parser/scansup.h"
/* ----------------
- * scanstr
- *
+ * scanstr
+ *
* if the string passed in has escaped codes, map the escape codes to actual
* chars
*
- * also, remove leading and ending quotes '"' if any
+ * also, remove leading and ending quotes '"' if any
*
* the string passed in must be non-null
*
@@ -38,88 +38,95 @@
* ----------------
*/
-char*
+char *
scanstr(char *s)
{
- static char newStr[MAX_PARSE_BUFFER];
- int len, i, j;
-
- if (s == NULL || s[0] == '\0')
- return s;
+ static char newStr[MAX_PARSE_BUFFER];
+ int len,
+ i,
+ j;
- len = strlen(s);
+ if (s == NULL || s[0] == '\0')
+ return s;
- for (i = 0, j = 0; i < len ; i++) {
- if (s[i] == '\'') {
- i = i + 1;
- if (s[i] == '\'')
- newStr[j] = '\'';
- }
- else {
- if (s[i] == '\\') {
- i = i + 1;
- switch (s[i]) {
- case '\\':
- newStr[j] = '\\';
- break;
- case 'b':
- newStr[j] = '\b';
- break;
- case 'f':
- newStr[j] = '\f';
- break;
- case 'n':
- newStr[j] = '\n';
- break;
- case 'r':
- newStr[j] = '\r';
- break;
- case 't':
- newStr[j] = '\t';
- break;
- case '"':
- newStr[j] = '"';
- break;
- case '\'':
- newStr[j] = '\'';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- char octal[4];
- int k;
- long octVal;
+ len = strlen(s);
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (s[i] == '\'')
+ {
+ i = i + 1;
+ if (s[i] == '\'')
+ newStr[j] = '\'';
+ }
+ else
+ {
+ if (s[i] == '\\')
+ {
+ i = i + 1;
+ switch (s[i])
+ {
+ case '\\':
+ newStr[j] = '\\';
+ break;
+ case 'b':
+ newStr[j] = '\b';
+ break;
+ case 'f':
+ newStr[j] = '\f';
+ break;
+ case 'n':
+ newStr[j] = '\n';
+ break;
+ case 'r':
+ newStr[j] = '\r';
+ break;
+ case 't':
+ newStr[j] = '\t';
+ break;
+ case '"':
+ newStr[j] = '"';
+ break;
+ case '\'':
+ newStr[j] = '\'';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ char octal[4];
+ int k;
+ long octVal;
- for (k=0;
- s[i+k] >= '0' && s[i+k] <= '7' && k < 3;
- k++)
- octal[k] = s[i+k];
- i += k-1;
- octal[3] = '\0';
-
- octVal = strtol(octal,0,8);
-/* elog (NOTICE, "octal = %s octVal = %d, %od", octal, octVal, octVal);*/
- if (octVal <= 0377) {
- newStr[j] = ((char)octVal);
- break;
- }
- }
- default:
- newStr[j] = s[i];
- } /* switch */
- } /* s[i] == '\\' */
- else
- newStr[j] = s[i];
+ for (k = 0;
+ s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
+ k++)
+ octal[k] = s[i + k];
+ i += k - 1;
+ octal[3] = '\0';
+
+ octVal = strtol(octal, 0, 8);
+/* elog (NOTICE, "octal = %s octVal = %d, %od", octal, octVal, octVal);*/
+ if (octVal <= 0377)
+ {
+ newStr[j] = ((char) octVal);
+ break;
+ }
+ }
+ default:
+ newStr[j] = s[i];
+ } /* switch */
+ } /* s[i] == '\\' */
+ else
+ newStr[j] = s[i];
+ }
+ j++;
}
- j++;
- }
- newStr[j] = '\0';
- return newStr;
+ newStr[j] = '\0';
+ return newStr;
}
-
diff --git a/src/backend/parser/sysfunc.c b/src/backend/parser/sysfunc.c
index fac1b60fd5a..02d6d6b21a7 100644
--- a/src/backend/parser/sysfunc.c
+++ b/src/backend/parser/sysfunc.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
- *
+ *
* sysfunc.c--
- * process system functions and return a string result
- *
+ * process system functions and return a string result
+ *
* Notes:
* 1) I return a string result because most of the functions cannot return any
- * normal type anyway (e.g. SYS_DATE, SYS_TIME, etc...), and the few that
- * might (SYS_UID or whatever) can just return it as a string - no problem.
- * This keeps the function flexible enough to be of good use.
- *
+ * normal type anyway (e.g. SYS_DATE, SYS_TIME, etc...), and the few that
+ * might (SYS_UID or whatever) can just return it as a string - no problem.
+ * This keeps the function flexible enough to be of good use.
+ *
* Written by Chad Robinson, chadr@brttech.com
* Last modified: 04/27/1996
* -------------------------------------------------------------------------
@@ -27,39 +27,42 @@
* Can't get much more obvious than this. Might need to replace localtime()
* on older systems...
*/
-static char *Sysfunc_system_date(void)
+static char *
+Sysfunc_system_date(void)
{
- time_t cur_time_secs;
- struct tm *cur_time_expanded;
- static char buf[12]; /* Just for safety, y'understand... */
-
+ time_t cur_time_secs;
+ struct tm *cur_time_expanded;
+ static char buf[12]; /* Just for safety, y'understand... */
+
time(&cur_time_secs);
cur_time_expanded = localtime(&cur_time_secs);
if (EuroDates == 1)
sprintf(buf, "%2.2d-%2.2d-%4.4d", cur_time_expanded->tm_mday,
- cur_time_expanded->tm_mon+1, cur_time_expanded->tm_year+1900);
+ cur_time_expanded->tm_mon + 1, cur_time_expanded->tm_year + 1900);
else
- sprintf(buf, "%2.2d-%2.2d-%4.4d", cur_time_expanded->tm_mon+1,
- cur_time_expanded->tm_mday, cur_time_expanded->tm_year+1900);
+ sprintf(buf, "%2.2d-%2.2d-%4.4d", cur_time_expanded->tm_mon + 1,
+ cur_time_expanded->tm_mday, cur_time_expanded->tm_year + 1900);
return &buf[0];
}
-static char *Sysfunc_system_time(void)
+static char *
+Sysfunc_system_time(void)
{
- time_t cur_time_secs;
- struct tm *cur_time_expanded;
- static char buf[10]; /* Just for safety, y'understand... */
-
+ time_t cur_time_secs;
+ struct tm *cur_time_expanded;
+ static char buf[10]; /* Just for safety, y'understand... */
+
time(&cur_time_secs);
cur_time_expanded = localtime(&cur_time_secs);
sprintf(buf, "%2.2d:%2.2d:%2.2d", cur_time_expanded->tm_hour,
- cur_time_expanded->tm_min, cur_time_expanded->tm_sec);
+ cur_time_expanded->tm_min, cur_time_expanded->tm_sec);
return &buf[0];
}
-char *SystemFunctionHandler(char *funct)
+char *
+SystemFunctionHandler(char *funct)
{
if (!strcmp(funct, "SYS_DATE"))
return Sysfunc_system_date();
@@ -73,9 +76,11 @@ char *SystemFunctionHandler(char *funct)
* Chad's rule of coding #4 - never delete a test function, even a stupid
* one - you always need it 10 minutes after you delete it.
*/
-void main(void)
+void
+main(void)
{
printf("Current system date: %s\n", SystemFunctionHandler("SYS_DATE"));
return;
}
+
#endif