diff options
Diffstat (limited to 'src/backend')
24 files changed, 739 insertions, 168 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 271dc3ed978..c90516be801 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.122 2000/02/18 09:28:40 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.123 2000/03/14 23:06:06 thomas Exp $ * * * INTERFACE ROUTINES @@ -1719,8 +1719,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, */ rte = makeNode(RangeTblEntry); rte->relname = RelationGetRelationName(rel); +#ifndef DISABLE_EREF rte->ref = makeNode(Attr); rte->ref->relname = RelationGetRelationName(rel); +#endif rte->relid = RelationGetRelid(rel); rte->inh = false; rte->inFromCl = true; @@ -1799,8 +1801,10 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin) */ rte = makeNode(RangeTblEntry); rte->relname = RelationGetRelationName(rel); +#ifndef DISABLE_EREF rte->ref = makeNode(Attr); rte->ref->relname = RelationGetRelationName(rel); +#endif rte->relid = RelationGetRelid(rel); rte->inh = false; rte->inFromCl = true; diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 2a38a349d60..64dc164a0d5 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994-5, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.54 2000/02/15 20:49:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.55 2000/03/14 23:06:12 thomas Exp $ * */ @@ -232,9 +232,33 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) appendStringInfo(str, " on %s", stringStringInfo(rte->relname)); - if (rte->ref && strcmp(rte->ref->relname, rte->relname) != 0) - appendStringInfo(str, " %s", - stringStringInfo(rte->ref->relname)); + if (rte->ref != NULL) + { + if ((strcmp(rte->ref->relname, rte->relname) != 0) + || (length(rte->ref->attrs) > 0)) + { + appendStringInfo(str, " %s", + stringStringInfo(rte->ref->relname)); + + if (length(rte->ref->attrs) > 0) + { + List *c; + int firstEntry = true; + + appendStringInfo(str, " ("); + foreach (c, rte->ref->attrs) + { + if (! firstEntry) + { + appendStringInfo(str, ", "); + firstEntry = false; + } + appendStringInfo(str, "%s", strVal(lfirst(c))); + } + appendStringInfo(str, ")"); + } + } + } } break; default: diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 601b503ec11..6afa4d8549f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.108 2000/02/21 18:47:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.109 2000/03/14 23:06:27 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -1366,6 +1366,7 @@ _copyRangeTblEntry(RangeTblEntry *from) if (from->relname) newnode->relname = pstrdup(from->relname); Node_Copy(from, newnode, ref); + Node_Copy(from, newnode, eref); newnode->relid = from->relid; newnode->inh = from->inh; newnode->inFromCl = from->inFromCl; diff --git a/src/backend/nodes/freefuncs.c b/src/backend/nodes/freefuncs.c index 14a5ed12d9e..96ce56c94c4 100644 --- a/src/backend/nodes/freefuncs.c +++ b/src/backend/nodes/freefuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.38 2000/02/21 18:47:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.39 2000/03/14 23:06:28 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -1031,6 +1031,7 @@ _freeRangeTblEntry(RangeTblEntry *node) if (node->relname) pfree(node->relname); freeObject(node->ref); + freeObject(node->eref); pfree(node); } diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 10a48c666e6..c0e09dc6d9b 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.45 2000/02/15 20:49:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.46 2000/03/14 23:06:29 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -454,8 +454,8 @@ new_rangetable_entry(Oid new_relid, RangeTblEntry *old_entry) RangeTblEntry *new_entry = copyObject(old_entry); /* ??? someone tell me what the following is doing! - ay 11/94 */ - if (!strcmp(new_entry->ref->relname, "*CURRENT*") || - !strcmp(new_entry->ref->relname, "*NEW*")) + if (!strcmp(new_entry->eref->relname, "*CURRENT*") || + !strcmp(new_entry->eref->relname, "*NEW*")) new_entry->ref->relname = get_rel_name(new_relid); else new_entry->relname = get_rel_name(new_relid); diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 612481deabc..c192b4ce7a1 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.139 2000/03/01 05:18:20 tgl Exp $ + * $Id: analyze.c,v 1.140 2000/03/14 23:06:30 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -146,6 +146,34 @@ transformStmt(ParseState *pstate, Node *parseTree) ViewStmt *n = (ViewStmt *) parseTree; n->query = (Query *) transformStmt(pstate, (Node *) n->query); + + /* If a list of column names was given, run through and insert these + * into the actual query tree. - thomas 2000-03-08 + */ + if (n->aliases != NIL) + { + int i; + List *targetList = n->query->targetList; + + if (length(targetList) < length(n->aliases)) + elog(ERROR, "CREATE VIEW specifies %d columns" + " but only %d columns are present", + length(targetList), length(n->aliases)); + + for (i = 0; i < length(n->aliases); i++) + { + Ident *id; + TargetEntry *te; + Resdom *rd; + id = nth(i, n->aliases); + Assert(nodeTag(id) == T_Ident); + te = nth(i, targetList); + Assert(nodeTag(te) == T_TargetEntry); + rd = te->resdom; + Assert(nodeTag(rd) == T_Resdom); + rd->resname = pstrdup(id->name); + } + } result = makeNode(Query); result->commandType = CMD_UTILITY; result->utilityStmt = (Node *) n; @@ -1904,7 +1932,7 @@ transformForUpdate(Query *qry, List *forUpdate) i = 1; foreach(l2, qry->rtable) { - if (strcmp(((RangeTblEntry *) lfirst(l2))->ref->relname, relname) == 0) + if (strcmp(((RangeTblEntry *) lfirst(l2))->eref->relname, relname) == 0) { List *l3; @@ -1925,7 +1953,7 @@ transformForUpdate(Query *qry, List *forUpdate) i++; } if (l2 == NULL) - elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", + elog(ERROR, "FOR UPDATE: relation '%s' not found in FROM clause", relname); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ab69eb4794f..c4d98d203ec 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.155 2000/03/12 20:09:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.156 2000/03/14 23:06:31 thomas Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -307,7 +307,7 @@ static void doNegateFloat(Value *v); ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL, MATCH, MINUTE_P, MONTH_P, NAMES, NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC, - OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P, + OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P, OVERLAPS, PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC, READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK, SCROLL, SECOND_P, SELECT, SESSION_USER, SET, SUBSTRING, @@ -363,6 +363,7 @@ static void doNegateFloat(Value *v); %right '=' %nonassoc '<' '>' %nonassoc LIKE +%nonassoc OVERLAPS %nonassoc BETWEEN %nonassoc IN %left Op /* multi-character ops and user-defined operators */ @@ -1903,7 +1904,7 @@ comment_text: Sconst { $$ = $1; } * *****************************************************************************/ -FetchStmt: FETCH direction fetch_how_many from_in name +FetchStmt: FETCH direction fetch_how_many from_in name { FetchStmt *n = makeNode(FetchStmt); if ($2 == RELATIVE) @@ -1923,7 +1924,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = false; $$ = (Node *)n; } - | FETCH fetch_how_many from_in name + | FETCH fetch_how_many from_in name { FetchStmt *n = makeNode(FetchStmt); if ($2 < 0) @@ -1940,7 +1941,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = false; $$ = (Node *)n; } - | FETCH direction from_in name + | FETCH direction from_in name { FetchStmt *n = makeNode(FetchStmt); if ($2 == RELATIVE) @@ -1953,7 +1954,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = false; $$ = (Node *)n; } - | FETCH from_in name + | FETCH from_in name { FetchStmt *n = makeNode(FetchStmt); n->direction = FORWARD; @@ -1962,7 +1963,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = false; $$ = (Node *)n; } - | FETCH name + | FETCH name { FetchStmt *n = makeNode(FetchStmt); n->direction = FORWARD; @@ -1972,7 +1973,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name $$ = (Node *)n; } - | MOVE direction fetch_how_many from_in name + | MOVE direction fetch_how_many from_in name { FetchStmt *n = makeNode(FetchStmt); if ($3 < 0) @@ -1986,7 +1987,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = TRUE; $$ = (Node *)n; } - | MOVE fetch_how_many from_in name + | MOVE fetch_how_many from_in name { FetchStmt *n = makeNode(FetchStmt); if ($2 < 0) @@ -2003,7 +2004,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = TRUE; $$ = (Node *)n; } - | MOVE direction from_in name + | MOVE direction from_in name { FetchStmt *n = makeNode(FetchStmt); n->direction = $2; @@ -2021,7 +2022,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name n->ismove = TRUE; $$ = (Node *)n; } - | MOVE name + | MOVE name { FetchStmt *n = makeNode(FetchStmt); n->direction = FORWARD; @@ -2659,11 +2660,12 @@ opt_trans: WORK { $$ = TRUE; } * *****************************************************************************/ -ViewStmt: CREATE VIEW name AS SelectStmt +ViewStmt: CREATE VIEW name opt_column_list AS SelectStmt { ViewStmt *n = makeNode(ViewStmt); n->viewname = $3; - n->query = (Query *)$5; + n->aliases = $4; + n->query = (Query *)$6; if (((SelectStmt *)n->query)->sortClause != NULL) elog(ERROR,"ORDER BY and DISTINCT on views are not implemented"); if (((SelectStmt *)n->query)->unionClause != NULL) @@ -2737,7 +2739,7 @@ createdb_opt_encoding: int i; i = pg_char_to_encoding($3); if (i == -1) - elog(ERROR, "%s is not a valid encoding name.", $3); + elog(ERROR, "%s is not a valid encoding name", $3); $$ = i; #else elog(ERROR, "Multi-byte support is not enabled"); @@ -2747,7 +2749,7 @@ createdb_opt_encoding: { #ifdef MULTIBYTE if (!pg_get_encent_by_encoding($3)) - elog(ERROR, "%d is not a valid encoding code.", $3); + elog(ERROR, "%d is not a valid encoding code", $3); $$ = $3; #else elog(ERROR, "Multi-byte support is not enabled"); @@ -3979,10 +3981,13 @@ Datetime: datetime $$->timezone = $2; $$->typmod = -1; } - | TIME + | TIME opt_timezone { $$ = makeNode(TypeName); - $$->name = xlateSqlType("time"); + if ($2) + $$->name = xlateSqlType("timetz"); + else + $$->name = xlateSqlType("time"); $$->typmod = -1; } | INTERVAL opt_interval @@ -4077,6 +4082,27 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { $$ = makeRowExpr($4, $2, $6); } + | '(' row_descriptor ')' OVERLAPS '(' row_descriptor ')' + { + FuncCall *n = makeNode(FuncCall); + List *largs = $2; + List *rargs = $6; + n->funcname = xlateSqlFunc("overlaps"); + if (length(largs) == 1) + largs = lappend(largs, $2); + else if (length(largs) != 2) + elog(ERROR, "Wrong number of parameters" + " on left side of OVERLAPS expression"); + if (length(rargs) == 1) + rargs = lappend(rargs, $6); + else if (length(rargs) != 2) + elog(ERROR, "Wrong number of parameters" + " on right side of OVERLAPS expression"); + n->args = nconc(largs, rargs); + n->agg_star = false; + n->agg_distinct = false; + $$ = (Node *)n; + } ; row_descriptor: row_list ',' a_expr @@ -4579,7 +4605,8 @@ c_expr: attr n->agg_distinct = false; if ($3 != 0) - elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3); + elog(NOTICE,"CURRENT_TIME(%d) precision not implemented" + "; zero used instead",$3); $$ = (Node *)n; } @@ -4632,7 +4659,8 @@ c_expr: attr n->agg_distinct = false; if ($3 != 0) - elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3); + elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented" + "; zero used instead",$3); $$ = (Node *)n; } @@ -5219,6 +5247,7 @@ ColId: IDENT { $$ = $1; } | ONLY { $$ = "only"; } | OPERATOR { $$ = "operator"; } | OPTION { $$ = "option"; } + | OVERLAPS { $$ = "overlaps"; } | PASSWORD { $$ = "password"; } | PENDANT { $$ = "pendant"; } | PRIOR { $$ = "prior"; } @@ -5454,9 +5483,8 @@ mapTargetColumns(List *src, List *dst) static char * xlateSqlFunc(char *name) { - if (!strcasecmp(name,"character_length") - || !strcasecmp(name,"char_length")) - return "length"; + if (!strcasecmp(name,"character_length")) + return "char_length"; else return name; } /* xlateSqlFunc() */ diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index d971e95762d..5bf703703d3 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.67 2000/02/18 09:29:40 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.68 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -184,6 +184,7 @@ static ScanKeyword ScanKeywords[] = { {"or", OR}, {"order", ORDER}, {"outer", OUTER_P}, + {"overlaps", OVERLAPS}, {"partial", PARTIAL}, {"password", PASSWORD}, {"pendant", PENDANT}, diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index afaa55e54f1..17cc026bfde 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.34 2000/02/15 03:37:47 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.35 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -111,7 +111,7 @@ check_ungrouped_columns_walker(Node *node, elog(ERROR, "cache lookup of attribute %d in relation %u failed", var->varattno, rte->relid); elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function", - rte->ref->relname, attname); + rte->eref->relname, attname); } /* Otherwise, recurse. */ return expression_tree_walker(node, check_ungrouped_columns_walker, diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 68da571f922..53d9b25f11b 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.55 2000/02/19 23:45:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.56 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -478,7 +478,7 @@ parseFromClause(ParseState *pstate, List *frmList) { Assert(IsA(j->larg, RangeVar)); l_rte = transformTableEntry(pstate, (RangeVar *) j->larg); - l_name = expandTable(pstate, l_rte->ref->relname, TRUE); + l_name = expandTable(pstate, l_rte->eref->relname, TRUE); } if (IsA(j->rarg, JoinExpr)) @@ -490,7 +490,7 @@ parseFromClause(ParseState *pstate, List *frmList) { Assert(IsA(j->rarg, RangeVar)); r_rte = transformTableEntry(pstate, (RangeVar *) j->rarg); - r_name = expandTable(pstate, r_rte->ref->relname, TRUE); + r_name = expandTable(pstate, r_rte->eref->relname, TRUE); } /* Natural join does not explicitly specify columns; must generate columns to join. diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 210a8f946e3..ce06da2669e 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.34 2000/03/11 23:19:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.35 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -319,6 +319,7 @@ TypeCategory(Oid inType) case (DATEOID): case (TIMEOID): + case (TIMETZOID): case (ABSTIMEOID): case (TIMESTAMPOID): result = DATETIME_TYPE; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index e1e86199722..e2e297cb6b6 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.72 2000/03/07 23:30:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.73 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -574,15 +574,7 @@ transformIdent(ParseState *pstate, Ident *ident, int precedence) if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL) { /* Convert it to a fully qualified Attr, and transform that */ -#ifndef DISABLE_JOIN_SYNTAX - Attr *att = makeAttr(rte->ref->relname, ident->name); -#else - Attr *att = makeNode(Attr); - - att->relname = rte->refname; - att->paramNo = NULL; - att->attrs = lcons(makeString(ident->name), NIL); -#endif + Attr *att = makeAttr(rte->eref->relname, ident->name); att->indirection = ident->indirection; return transformAttr(pstate, att, precedence); } diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 90c65a3830e..eb4884accbb 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.73 2000/03/11 23:17:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.74 2000/03/14 23:06:32 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -325,7 +325,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, * now allow column aliases. * - thomas 2000-02-07 */ - if (rte->ref->attrs != NULL) + if (rte->eref->attrs != NULL) { List *c; /* start counting attributes/columns from one. @@ -333,7 +333,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, * - thomas 2000-01-27 */ int i = 1; - foreach (c, rte->ref->attrs) + foreach (c, rte->eref->attrs) { char *colname = strVal(lfirst(c)); /* found a match? */ @@ -550,7 +550,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, relname = rte->relname; - vnum = refnameRangeTablePosn(pstate, rte->ref->relname, NULL); + vnum = refnameRangeTablePosn(pstate, rte->eref->relname, NULL); /* * for func(relname), the param to the function is the tuple diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 265642faaf3..4a943af6739 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.36 2000/03/09 05:00:24 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.37 2000/03/14 23:06:33 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -68,8 +68,12 @@ static char *attnum_type[SPECIALS] = { /* refnameRangeTableEntries() * Given refname, return a list of range table entries * This is possible with JOIN syntax, where tables in a join - * acquire the same reference name + * acquire the same reference name. * - thomas 2000-01-20 + * But at the moment we aren't carrying along a full list of + * table/column aliases, so we don't have the full mechanism + * to support outer joins in place yet. + * - thomas 2000-03-04 */ List * refnameRangeTableEntries(ParseState *pstate, char *refname); @@ -86,7 +90,7 @@ refnameRangeTableEntries(ParseState *pstate, char *refname) { RangeTblEntry *rte = lfirst(temp); - if (strcmp(rte->ref->relname, refname) == 0) + if (strcmp(rte->eref->relname, refname) == 0) rteList = lappend(rteList, rte); } /* only allow correlated columns in WHERE clause */ @@ -110,11 +114,7 @@ refnameRangeTableEntry(ParseState *pstate, char *refname) { RangeTblEntry *rte = lfirst(temp); -#ifndef DISABLE_JOIN_SYNTAX - if (strcmp(rte->ref->relname, refname) == 0) -#else - if (!strcmp(rte->refname, refname)) -#endif + if (strcmp(rte->eref->relname, refname) == 0) return rte; } /* only allow correlated columns in WHERE clause */ @@ -143,11 +143,7 @@ refnameRangeTablePosn(ParseState *pstate, char *refname, int *sublevels_up) { RangeTblEntry *rte = lfirst(temp); -#ifndef DISABLE_JOIN_SYNTAX - if (strcmp(rte->ref->relname, refname) == 0) -#else - if (!strcmp(rte->refname, refname)) -#endif + if (strcmp(rte->eref->relname, refname) == 0) return index; index++; } @@ -191,7 +187,7 @@ colnameRangeTableEntry(ParseState *pstate, char *colname) if (!rte->inFromCl && rte != pstate->p_target_rangetblentry) continue; - if (rte->ref->attrs != NULL) + if (rte->eref->attrs != NULL) { List *c; foreach (c, rte->ref->attrs) @@ -253,6 +249,7 @@ addRangeTableEntry(ParseState *pstate, { Relation rel; RangeTblEntry *rte; + Attr *eref; int maxattrs; int sublevels_up; int varattno; @@ -286,19 +283,22 @@ addRangeTableEntry(ParseState *pstate, rel = heap_openr(relname, AccessShareLock); rte->relid = RelationGetRelid(rel); maxattrs = RelationGetNumberOfAttributes(rel); - if (maxattrs < length(ref->attrs)) + + eref = copyObject(ref); + if (maxattrs < length(eref->attrs)) elog(ERROR, "Table '%s' has %d columns available but %d columns specified", - relname, maxattrs, length(ref->attrs)); + relname, maxattrs, length(eref->attrs)); /* fill in any unspecified alias columns */ - for (varattno = length(ref->attrs); varattno < maxattrs; varattno++) + for (varattno = length(eref->attrs); varattno < maxattrs; varattno++) { char *attrname; attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname)); - ref->attrs = lappend(ref->attrs, makeString(attrname)); + eref->attrs = lappend(eref->attrs, makeString(attrname)); } heap_close(rel, AccessShareLock); + rte->eref = eref; /* * Flags: @@ -337,10 +337,9 @@ expandTable(ParseState *pstate, char *refname, bool getaliases) rte = refnameRangeTableEntry(pstate, refname); - if (getaliases && (rte != NULL) && (rte->ref != NULL) - && (length(rte->ref->attrs) > 0)) + if (getaliases && (rte != NULL)) { - return rte->ref; + return rte->eref; } if (rte != NULL) @@ -415,8 +414,8 @@ expandAll(ParseState *pstate, char *relname, Attr *ref, int *this_resno) attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname)); /* varattno is zero-based, so check that length() is always greater */ - if (length(rte->ref->attrs) > varattno) - label = pstrdup(strVal(nth(varattno, rte->ref->attrs))); + if (length(rte->eref->attrs) > varattno) + label = pstrdup(strVal(nth(varattno, rte->eref->attrs))); else label = attrname; varnode = make_var(pstate, rte->relid, relname, attrname); diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index e815efc9639..65a5b33d58c 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.56 2000/03/09 05:00:24 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.57 2000/03/14 23:06:33 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -430,7 +430,7 @@ ExpandAllTables(ParseState *pstate) continue; target = nconc(target, - expandAll(pstate, rte->ref->relname, rte->ref, + expandAll(pstate, rte->eref->relname, rte->eref, &pstate->p_last_resno)); } return target; diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 7102f64a44f..378289373b8 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.42 2000/02/16 18:17:02 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.43 2000/03/14 23:06:35 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -198,7 +198,7 @@ date_timestamp(DateADT dateVal) double fsec = 0; char *tzn; - result = palloc(sizeof(Timestamp)); + result = palloc(sizeof(*result)); if (date2tm(dateVal, &tz, tm, &fsec, &tzn) != 0) elog(ERROR, "Unable to convert date to timestamp"); @@ -392,10 +392,10 @@ time_in(char *str) elog(ERROR, "Bad (null) time external representation"); if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0)) + || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0)) elog(ERROR, "Bad time external representation '%s'", str); - time = palloc(sizeof(TimeADT)); + time = palloc(sizeof(*time)); *time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); @@ -422,7 +422,7 @@ time_out(TimeADT *time) fsec = 0; - EncodeTimeOnly(tm, fsec, DateStyle, buf); + EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf); result = palloc(strlen(buf) + 1); @@ -456,8 +456,8 @@ time_lt(TimeADT *time1, TimeADT *time2) if (!PointerIsValid(time1) || !PointerIsValid(time2)) return FALSE; - return *time1 < *time2; -} /* time_eq() */ + return (*time1 < *time2); +} /* time_lt() */ bool time_le(TimeADT *time1, TimeADT *time2) @@ -465,8 +465,8 @@ time_le(TimeADT *time1, TimeADT *time2) if (!PointerIsValid(time1) || !PointerIsValid(time2)) return FALSE; - return *time1 <= *time2; -} /* time_eq() */ + return (*time1 <= *time2); +} /* time_le() */ bool time_gt(TimeADT *time1, TimeADT *time2) @@ -474,8 +474,8 @@ time_gt(TimeADT *time1, TimeADT *time2) if (!PointerIsValid(time1) || !PointerIsValid(time2)) return FALSE; - return *time1 > *time2; -} /* time_eq() */ + return (*time1 > *time2); +} /* time_gt() */ bool time_ge(TimeADT *time1, TimeADT *time2) @@ -483,8 +483,8 @@ time_ge(TimeADT *time1, TimeADT *time2) if (!PointerIsValid(time1) || !PointerIsValid(time2)) return FALSE; - return *time1 >= *time2; -} /* time_eq() */ + return (*time1 >= *time2); +} /* time_ge() */ int time_cmp(TimeADT *time1, TimeADT *time2) @@ -492,6 +492,43 @@ time_cmp(TimeADT *time1, TimeADT *time2) return (*time1 < *time2) ? -1 : (((*time1 > *time2) ? 1 : 0)); } /* time_cmp() */ +TimeADT * +time_larger(TimeADT *time1, TimeADT *time2) +{ + return time_gt(time1, time2)? time1: time2; +} /* time_larger() */ + +TimeADT * +time_smaller(TimeADT *time1, TimeADT *time2) +{ + return time_lt(time1, time2)? time1: time2; +} /* time_smaller() */ + +/* overlaps_time() + * Implements the SQL92 OVERLAPS operator. + * Algorithm from Date and Darwen, 1997 + */ +bool +overlaps_time(TimeADT *ts1, TimeADT *te1, TimeADT *ts2, TimeADT *te2) +{ + /* Make sure we have ordered pairs... */ + if (time_gt(ts1, te1)) + { + TimeADT *tt = ts1; + ts1 = te1; + te1 = tt; + } + if (time_gt(ts2, te2)) + { + TimeADT *tt = ts2; + ts2 = te2; + te2 = tt; + } + + return ((time_gt(ts1, ts2) && (time_lt(ts1, te2) || time_lt(te1, te2))) + || (time_gt(ts2, ts1) && (time_lt(ts2, te1) || time_lt(te2, te1))) + || time_eq(ts1, ts2)); +} /* timestamp_time() * Convert timestamp to time data type. @@ -515,12 +552,10 @@ timestamp_time(Timestamp *timestamp) if (TIMESTAMP_IS_EPOCH(*timestamp)) { timestamp2tm(SetTimestamp(*timestamp), NULL, tm, &fsec, NULL); - } else if (TIMESTAMP_IS_CURRENT(*timestamp)) { timestamp2tm(SetTimestamp(*timestamp), &tz, tm, &fsec, &tzn); - } else { @@ -528,7 +563,7 @@ timestamp_time(Timestamp *timestamp) elog(ERROR, "Unable to convert timestamp to date"); } - result = palloc(sizeof(TimeADT)); + result = palloc(sizeof(*result)); *result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); @@ -546,7 +581,7 @@ datetime_timestamp(DateADT date, TimeADT *time) if (!PointerIsValid(time)) { - result = palloc(sizeof(Timestamp)); + result = palloc(sizeof(*result)); TIMESTAMP_INVALID(*result); } else @@ -557,3 +592,270 @@ datetime_timestamp(DateADT date, TimeADT *time) return result; } /* datetime_timestamp() */ + + +/* time_interval() + * Convert time to interval data type. + */ +Interval * +time_interval(TimeADT *time) +{ + Interval *result; + + if (!PointerIsValid(time)) + return NULL; + + result = palloc(sizeof(*result)); + result->time = *time; + result->month = 0; + + return result; +} /* time_interval() */ + + +/***************************************************************************** + * Time With Time Zone ADT + *****************************************************************************/ + + +TimeTzADT * +timetz_in(char *str) +{ + TimeTzADT *time; + + double fsec; + struct tm tt, + *tm = &tt; + int tz; + + int nf; + char lowstr[MAXDATELEN + 1]; + char *field[MAXDATEFIELDS]; + int dtype; + int ftype[MAXDATEFIELDS]; + + if (!PointerIsValid(str)) + elog(ERROR, "Bad (null) time external representation"); + + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) + elog(ERROR, "Bad time external representation '%s'", str); + + time = palloc(sizeof(*time)); + + time->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); + time->zone = tz; + + return time; +} /* timetz_in() */ + + +char * +timetz_out(TimeTzADT *time) +{ + char *result; + struct tm tt, + *tm = &tt; + + double fsec; + int tz; + char buf[MAXDATELEN + 1]; + + if (!PointerIsValid(time)) + return NULL; + + tm->tm_hour = (time->time / (60 * 60)); + tm->tm_min = (((int) (time->time / 60)) % 60); + tm->tm_sec = (((int) time->time) % 60); + + fsec = 0; + tz = time->zone; + + EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf); + + result = palloc(strlen(buf) + 1); + + strcpy(result, buf); + + return result; +} /* timetz_out() */ + + +bool +timetz_eq(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) == (time2->time + time2->zone)); +} /* timetz_eq() */ + +bool +timetz_ne(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) != (time2->time + time2->zone)); +} /* timetz_ne() */ + +bool +timetz_lt(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) < (time2->time + time2->zone)); +} /* timetz_lt() */ + +bool +timetz_le(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) <= (time2->time + time2->zone)); +} /* timetz_le() */ + +bool +timetz_gt(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) > (time2->time + time2->zone)); +} /* timetz_gt() */ + +bool +timetz_ge(TimeTzADT *time1, TimeTzADT *time2) +{ + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return FALSE; + + return ((time1->time + time1->zone) >= (time2->time + time2->zone)); +} /* timetz_ge() */ + +int +timetz_cmp(TimeTzADT *time1, TimeTzADT *time2) +{ + return (timetz_lt(time1, time2) ? -1 : (timetz_gt(time1, time2)? 1: 0)); +} /* timetz_cmp() */ + +TimeTzADT * +timetz_larger(TimeTzADT *time1, TimeTzADT *time2) +{ + return timetz_gt(time1, time2)? time1: time2; +} /* timetz_larger() */ + +TimeTzADT * +timetz_smaller(TimeTzADT *time1, TimeTzADT *time2) +{ + return timetz_lt(time1, time2)? time1: time2; +} /* timetz_smaller() */ + +/* overlaps_timetz() + * Implements the SQL92 OVERLAPS operator. + * Algorithm from Date and Darwen, 1997 + */ +bool +overlaps_timetz(TimeTzADT *ts1, TimeTzADT *te1, TimeTzADT *ts2, TimeTzADT *te2) +{ + /* Make sure we have ordered pairs... */ + if (timetz_gt(ts1, te1)) + { + TimeTzADT *tt = ts1; + ts1 = te1; + te1 = tt; + } + if (timetz_gt(ts2, te2)) + { + TimeTzADT *tt = ts2; + ts2 = te2; + te2 = tt; + } + + return ((timetz_gt(ts1, ts2) && (timetz_lt(ts1, te2) || timetz_lt(te1, te2))) + || (timetz_gt(ts2, ts1) && (timetz_lt(ts2, te1) || timetz_lt(te2, te1))) + || timetz_eq(ts1, ts2)); +} /* overlaps_timetz() */ + +/* timestamp_timetz() + * Convert timestamp to timetz data type. + */ +TimeTzADT * +timestamp_timetz(Timestamp *timestamp) +{ + TimeTzADT *result; + struct tm tt, + *tm = &tt; + int tz; + double fsec; + char *tzn; + + if (!PointerIsValid(timestamp)) + elog(ERROR, "Unable to convert null timestamp to date"); + + if (TIMESTAMP_NOT_FINITE(*timestamp)) + elog(ERROR, "Unable to convert timestamp to date"); + + if (TIMESTAMP_IS_EPOCH(*timestamp)) + { + timestamp2tm(SetTimestamp(*timestamp), NULL, tm, &fsec, NULL); + tz = 0; + } + else if (TIMESTAMP_IS_CURRENT(*timestamp)) + { + timestamp2tm(SetTimestamp(*timestamp), &tz, tm, &fsec, &tzn); + } + else + { + if (timestamp2tm(*timestamp, &tz, tm, &fsec, &tzn) != 0) + elog(ERROR, "Unable to convert timestamp to date"); + } + + result = palloc(sizeof(*result)); + + result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); + result->zone = tz; + + return result; +} /* timestamp_timetz() */ + + +/* datetimetz_timestamp() + * Convert date and timetz to timestamp data type. + * Timestamp is stored in GMT, so add the time zone + * stored with the timetz to the result. + * - thomas 2000-03-10 + */ +Timestamp * +datetimetz_timestamp(DateADT date, TimeTzADT *time) +{ + Timestamp *result; + struct tm tt, + *tm = &tt; + int tz; + double fsec = 0; + char *tzn; + + result = palloc(sizeof(*result)); + + if (!PointerIsValid(date) || !PointerIsValid(time)) + { + TIMESTAMP_INVALID(*result); + } + else + { + if (date2tm(date, &tz, tm, &fsec, &tzn) != 0) + elog(ERROR, "Unable to convert date to timestamp"); + + if (tm2timestamp(tm, fsec, &time->zone, result) != 0) + elog(ERROR, "Timestamp out of range"); + + *result += time->time; + } + + return result; +} /* datetimetz_timestamp() */ + + diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 1418a0c34c2..3c88ac3a3d1 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.42 2000/02/16 18:17:02 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.43 2000/03/14 23:06:36 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -618,8 +618,7 @@ DecodeDateTime(char **field, int *ftype, int nf, tm->tm_min = 0; tm->tm_sec = 0; *fsec = 0; - tm->tm_isdst = -1; /* don't know daylight savings time status - * apriori */ + tm->tm_isdst = -1; /* don't know daylight savings time status apriori */ if (tzp != NULL) *tzp = 0; @@ -897,8 +896,7 @@ DecodeDateTime(char **field, int *ftype, int nf, tm->tm_mon += 1; #if defined(HAVE_TM_ZONE) - *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is - * Sun/DEC-ism */ + *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ #elif defined(HAVE_INT_TIMEZONE) #ifdef __CYGWIN__ *tzp = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); @@ -927,9 +925,18 @@ DecodeDateTime(char **field, int *ftype, int nf, /* DecodeTimeOnly() * Interpret parsed string as time fields only. + * Note that support for time zone is here for + * SQL92 TIME WITH TIME ZONE, but it reveals + * bogosity with SQL92 date/time standards, since + * we must infer a time zone from current time. + * XXX Later, we should probably support + * SET TIME ZONE <integer> + * which of course is a screwed up convention. + * - thomas 2000-03-10 */ int -DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, double *fsec) +DecodeTimeOnly(char **field, int *ftype, int nf, + int *dtype, struct tm * tm, double *fsec, int *tzp) { int fmask, tmask, @@ -944,9 +951,10 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; - tm->tm_isdst = -1; /* don't know daylight savings time status - * apriori */ *fsec = 0; + tm->tm_isdst = -1; /* don't know daylight savings time status apriori */ + if (tzp != NULL) + *tzp = 0; fmask = DTK_DATE_M; @@ -959,6 +967,14 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou return -1; break; + case DTK_TZ: + if (tzp == NULL) + return -1; + if (DecodeTimezone(field[i], tzp) != 0) + return -1; + tmask = DTK_M(TZ); + break; + case DTK_NUMBER: flen = strlen(field[i]); @@ -1035,6 +1051,45 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou if ((fmask & DTK_TIME_M) != DTK_TIME_M) return -1; + /* timezone not specified? then find local timezone if possible */ + if ((tzp != NULL) && (!(fmask & DTK_M(TZ)))) + { + struct tm tt, *tmp = &tt; + + /* + * daylight savings time modifier but no standard timezone? + * then error + */ + if (fmask & DTK_M(DTZMOD)) + return -1; + + GetCurrentTime(tmp); + tmp->tm_hour = tm->tm_hour; + tmp->tm_min = tm->tm_min; + tmp->tm_sec = tm->tm_sec; + +#ifdef USE_POSIX_TIME + tmp->tm_isdst = -1; + mktime(tmp); + tm->tm_isdst = tmp->tm_isdst; + +#if defined(HAVE_TM_ZONE) + *tzp = -(tmp->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ +#elif defined(HAVE_INT_TIMEZONE) +#ifdef __CYGWIN__ + *tzp = ((tmp->tm_isdst > 0) ? (_timezone - 3600) : _timezone); +#else + *tzp = ((tmp->tm_isdst > 0) ? (timezone - 3600) : timezone); +#endif +#else +#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined +#endif + +#else /* !USE_POSIX_TIME */ + *tzp = CTimeZone; +#endif + } + return 0; } /* DecodeTimeOnly() */ @@ -1830,7 +1885,7 @@ EncodeDateOnly(struct tm * tm, int style, char *str) * Encode time fields only. */ int -EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str) +EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str) { double sec; @@ -1842,6 +1897,15 @@ EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str) sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min); sprintf((str + 6), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec); + if (tzp != NULL) + { + int hour, min; + + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); + } + return TRUE; } /* EncodeTimeOnly() */ diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 0a0df27b808..6af9cd906d3 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.53 2000/01/26 05:57:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.54 2000/03/14 23:06:36 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -1236,6 +1236,31 @@ dlog1(float64 arg1) return result; } +/* + * dlog10 - returns a pointer to the base 10 logarithm of arg1 + */ +float64 +dlog10(float64 arg1) +{ + float64 result; + double tmp; + + if (!PointerIsValid(arg1)) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + if (tmp == 0.0) + elog(ERROR, "can't take log of zero"); + if (tmp < 0) + elog(ERROR, "can't take log of a negative number"); + *result = (float64data) log10(tmp); + + CheckFloat8Val(*result); + return result; +} /* dlog10() */ + /* * ==================== diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 7b56fba275b..9561f9e875d 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.48 2000/01/26 05:57:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.49 2000/03/14 23:06:36 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -3510,29 +3510,6 @@ path_div_pt(PATH *path, Point *point) } /* path_div_pt() */ -bool -path_contain_pt(PATH *path, Point *p) -{ - if (!PointerIsValid(path) || !PointerIsValid(p)) - return FALSE; - - return (on_ppath(p, path)); -} /* path_contain_pt() */ - -/* pt_contained_path - * Point in or on path? This is the same as on_ppath. - * - thomas 1998-10-29 - */ -bool -pt_contained_path(Point *p, PATH *path) -{ - if (!PointerIsValid(p) || !PointerIsValid(path)) - return FALSE; - - return path_contain_pt(path, p); -} /* pt_contained_path() */ - - Point * path_center(PATH *path) { diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 244bf3aaa4b..7eb7783274c 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.34 2000/03/07 23:58:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.35 2000/03/14 23:06:36 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -659,8 +659,8 @@ int42mod(int32 arg1, int32 arg2) return arg1 % arg2; } -/* - * int[24]fac - returns arg1! +/* int[24]fac() + * Factorial */ int32 int4fac(int32 arg1) @@ -678,7 +678,7 @@ int4fac(int32 arg1) int32 int2fac(int16 arg1) { - int16 result; + int32 result; if (arg1 < 1) result = 0; @@ -688,6 +688,21 @@ int2fac(int16 arg1) return result; } +/* int[24]abs() + * Absolute value + */ +int32 +int4abs(int32 arg1) +{ + return ((arg1 < 0)? -arg1: arg1); +} + +int16 +int2abs(int16 arg1) +{ + return ((arg1 < 0)? -arg1: arg1); +} + int16 int2larger(int16 arg1, int16 arg2) { diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 7c00686b194..27b0f42c97f 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -359,6 +359,63 @@ int8div(int64 *val1, int64 *val2) return result; } /* int8div() */ +/* int8abs() + * Absolute value + */ +int64 * +int8abs(int64 *arg1) +{ + int64 *result; + + if (!PointerIsValid(arg1)) + return NULL; + + result = palloc(sizeof(*result)); + + *result = ((*arg1 < 0)? -*arg1: *arg1); + + return result; +} + +/* int8mod() + * Modulo operation. + */ +int64 * +int8mod(int64 *val1, int64 *val2) +{ + int64 *result; + + /* use the divide operation to check params and allocate storage */ + result = int8div(val1, val2); + *result *= *val2; + *result = *val1 - *result; + + return result; +} /* int8mod() */ + +/* int8fac() + * Factorial + */ +int64 * +int8fac(int64 *arg1) +{ + int64 *result; + int64 i; + + if (!PointerIsValid(arg1)) + return NULL; + + result = palloc(sizeof(*result)); + + if (*arg1 < 1) + *result = 0; + else + for (i = *arg1, *result = 1; i > 0; --i) + *result *= i; + + return result; +} + int64 * int8larger(int64 *val1, int64 *val2) { @@ -634,4 +691,4 @@ int8_text(int64 *val) memmove(VARDATA(result), s, len); return result; -} /* int8out() */ +} /* int8_text() */ diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 50be811b22c..b18cbf4a208 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1,24 +1,14 @@ /* * Edmund Mergl <E.Mergl@bawue.de> * - * $Id: oracle_compat.c,v 1.20 1999/07/15 15:20:19 momjian Exp $ + * $Id: oracle_compat.c,v 1.21 2000/03/14 23:06:37 thomas Exp $ * */ #include <ctype.h> #include "postgres.h" - -text *lower(text *string); -text *upper(text *string); -text *initcap(text *string); -text *lpad(text *string1, int4 len, text *string2); -text *rpad(text *string1, int4 len, text *string2); -text *btrim(text *string, text *set); -text *ltrim(text *string, text *set); -text *rtrim(text *string, text *set); -text *substr(text *string, int4 m, int4 n); -text *translate(text *string, char from, char to); +#include "utils/builtins.h" /******************************************************************** @@ -506,42 +496,68 @@ substr(text *string, int4 m, int4 n) * * Syntax: * - * text *translate(text *string, char from, char to) + * text *translate(text *string, text *from, text *to) * * Purpose: * * Returns string after replacing all occurences of from with * the corresponding character in to. TRANSLATE will not remove * characters. + * Modified to work with strings rather than single character + * for the substitution arguments. + * Modifications from Edwin Ramirez <ramirez@doc.mssm.edu>. * ********************************************************************/ text * -translate(text *string, char from, char to) +translate(text *string, text *from, text *to) { - text *ret; - char *ptr, - *ptr_ret; - int m; + text *ret; + char *ptr_ret, *from_ptr, *to_ptr; + char *source, *target, *temp, rep; + int m, fromlen, tolen, retlen, i; if ((string == (text *) NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) return string; - ret = (text *) palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); - - ptr = VARDATA(string); - ptr_ret = VARDATA(ret); + target = (char *) palloc(VARSIZE(string) - VARHDRSZ); + source = VARDATA(string); + temp = target; + fromlen = VARSIZE(from) - VARHDRSZ; + from_ptr = VARDATA(from); + tolen = VARSIZE(to) - VARHDRSZ; + to_ptr = VARDATA(to); + retlen = 0; while (m--) { - *ptr_ret++ = *ptr == from ? to : *ptr; - ptr++; + rep = *source; + for(i=0;i<fromlen;i++) { + if(from_ptr[i] == *source) { + if(i < tolen) { + rep = to_ptr[i]; + } else { + rep = 0; + } + break; + } + } + if(rep != 0) { + *target++ = rep; + retlen++; + } + source++; } + ret = (text *) palloc(retlen + VARHDRSZ); + VARSIZE(ret) = retlen + VARHDRSZ; + ptr_ret = VARDATA(ret); + for(i=0;i<retlen;i++) { + *ptr_ret++ = temp[i]; + } + pfree(target); return ret; } - /* EOF */ diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index bdeaf440829..59ec46a85aa 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * out of its tuple * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.44 2000/02/26 21:13:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.45 2000/03/14 23:06:37 thomas Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -923,6 +923,8 @@ get_select_query_def(Query *query, deparse_context *context) continue; rte = (RangeTblEntry *) lfirst(l); + if (rte->ref == NULL) + continue; if (!strcmp(rte->ref->relname, "*NEW*")) continue; if (!strcmp(rte->ref->relname, "*CURRENT*")) @@ -982,9 +984,10 @@ get_select_query_def(Query *query, deparse_context *context) { rte = (RangeTblEntry *) lfirst(l); + if (rte->ref == NULL) + continue; if (!strcmp(rte->ref->relname, "*NEW*")) continue; - if (!strcmp(rte->ref->relname, "*CURRENT*")) continue; @@ -1008,7 +1011,9 @@ get_select_query_def(Query *query, deparse_context *context) * Since we don't really support SQL joins yet, dropping * the list of column aliases doesn't hurt anything... */ - if (strcmp(rte->relname, rte->ref->relname) != 0) + if ((rte->ref != NULL) + && ((strcmp(rte->relname, rte->ref->relname) != 0) + || (rte->ref->attrs != NIL))) { appendStringInfo(buf, " %s", quote_identifier(rte->ref->relname)); @@ -1104,6 +1109,8 @@ get_insert_query_def(Query *query, deparse_context *context) continue; rte = (RangeTblEntry *) lfirst(l); + if (rte->ref == NULL) + continue; if (!strcmp(rte->ref->relname, "*NEW*")) continue; if (!strcmp(rte->ref->relname, "*CURRENT*")) @@ -1274,7 +1281,10 @@ get_rule_expr(Node *node, deparse_context *context) if (context->varprefix) { - if (!strcmp(rte->ref->relname, "*NEW*")) + if (rte->ref == NULL) + appendStringInfo(buf, "%s.", + quote_identifier(rte->relname)); + else if (!strcmp(rte->ref->relname, "*NEW*")) appendStringInfo(buf, "new."); else if (!strcmp(rte->ref->relname, "*CURRENT*")) appendStringInfo(buf, "old."); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 77202c8308e..4086a803dd7 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.22 2000/02/16 17:24:48 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.23 2000/03/14 23:06:37 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -952,6 +952,32 @@ interval_cmp(Interval *interval1, Interval *interval2) return (span1 < span2) ? -1 : (span1 > span2) ? 1 : 0; } /* interval_cmp() */ +/* overlaps_timestamp() + * Implements the SQL92 OVERLAPS operator. + * Algorithm from Date and Darwen, 1997 + */ +bool +overlaps_timestamp(Timestamp *ts1, Timestamp *te1, Timestamp *ts2, Timestamp *te2) +{ + /* Make sure we have ordered pairs... */ + if (timestamp_gt(ts1, te1)) + { + Timestamp *tt = ts1; + ts1 = te1; + te1 = tt; + } + if (timestamp_gt(ts2, te2)) + { + Timestamp *tt = ts2; + ts2 = te2; + te2 = tt; + } + + return ((timestamp_gt(ts1, ts2) && (timestamp_lt(ts1, te2) || timestamp_lt(te1, te2))) + || (timestamp_gt(ts2, ts1) && (timestamp_lt(ts2, te1) || timestamp_lt(te2, te1))) + || timestamp_eq(ts1, ts2)); +} /* overlaps_timestamp() */ + /*---------------------------------------------------------- * "Arithmetic" operators on date/times. |