aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorThomas G. Lockhart <lockhart@fourpalms.org>2000-12-03 14:51:12 +0000
committerThomas G. Lockhart <lockhart@fourpalms.org>2000-12-03 14:51:12 +0000
commit6969b8fa1194dafdc24e38fccf4acbb32419967e (patch)
treea69a2f308d09d30ffa3b12b9e84c2ea4ef71c0c9 /src/backend
parent1131261270e74dd8a7cf7a3e99c1f3c71175ebe9 (diff)
downloadpostgresql-6969b8fa1194dafdc24e38fccf4acbb32419967e.tar.gz
postgresql-6969b8fa1194dafdc24e38fccf4acbb32419967e.zip
Repair usage of the OVERLAPS operator.
Allow some operator-like tokens to be used as function names. Flesh out support for time, timetz, and interval operators and interactions. Regression tests pass, but non-reference-platform horology test results will need to be updated.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/parser/gram.y96
-rw-r--r--src/backend/utils/adt/date.c114
2 files changed, 177 insertions, 33 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b910f80fe4a..5344a40cb29 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.210 2000/11/24 20:16:39 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.211 2000/12/03 14:50:54 thomas Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -198,8 +198,9 @@ static void doNegateFloat(Value *v);
%type <jtype> join_type
%type <list> extract_list, position_list
-%type <list> substr_list, substr_from, substr_for, trim_list
+%type <list> substr_list, trim_list
%type <list> opt_interval
+%type <node> substr_from, substr_for
%type <boolean> opt_inh_star, opt_binary, opt_using, opt_instead, opt_only
opt_with_copy, index_opt_unique, opt_verbose, opt_analyze
@@ -330,7 +331,7 @@ static void doNegateFloat(Value *v);
* when some sort of pg_privileges relation is introduced.
* - Todd A. Brandys 1998-01-01?
*/
-%token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE, ANALYSE,
+%token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYSE, ANALYZE,
BACKWARD, BEFORE, BINARY, BIT,
CACHE, CHECKPOINT, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
DATABASE, DELIMITERS, DO,
@@ -4873,7 +4874,8 @@ c_expr: attr
| SUBSTRING '(' substr_list ')'
{
/* substring(A from B for C) is converted to
- * substring(A, B, C) */
+ * substring(A, B, C) - thomas 2000-11-28
+ */
FuncCall *n = makeNode(FuncCall);
n->funcname = "substring";
n->args = $3;
@@ -4881,9 +4883,11 @@ c_expr: attr
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
- /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
| TRIM '(' BOTH trim_list ')'
{
+ /* various trim expressions are defined in SQL92
+ * - thomas 1997-07-19
+ */
FuncCall *n = makeNode(FuncCall);
n->funcname = "btrim";
n->args = $4;
@@ -4994,29 +4998,49 @@ position_list: b_expr IN b_expr
{ $$ = NIL; }
;
-substr_list: expr_list substr_from substr_for
+/* SUBSTRING() arguments
+ * SQL9x defines a specific syntax for arguments to SUBSTRING():
+ * o substring(text from int for int)
+ * o substring(text from int) get entire string from starting point "int"
+ * o substring(text for int) get first "int" characters of string
+ * We also want to implement generic substring functions which accept
+ * the usual generic list of arguments. So we will accept both styles
+ * here, and convert the SQL9x style to the generic list for further
+ * processing. - thomas 2000-11-28
+ */
+substr_list: a_expr substr_from substr_for
{
- $$ = nconc(nconc($1,$2),$3);
+ $$ = makeList3($1, $2, $3);
}
- | /*EMPTY*/
- { $$ = NIL; }
- ;
-
-substr_from: FROM expr_list
- { $$ = $2; }
- | /*EMPTY*/
+ | a_expr substr_for substr_from
+ {
+ $$ = makeList3($1, $3, $2);
+ }
+ | a_expr substr_from
+ {
+ $$ = makeList2($1, $2);
+ }
+ | a_expr substr_for
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Integer;
n->val.val.ival = 1;
- $$ = makeList1((Node *)n);
+ $$ = makeList3($1, (Node *)n, $2);
+ }
+ | expr_list
+ {
+ $$ = $1;
}
+ | /*EMPTY*/
+ { $$ = NIL; }
;
-substr_for: FOR expr_list
+substr_from: FROM a_expr
+ { $$ = $2; }
+ ;
+
+substr_for: FOR a_expr
{ $$ = $2; }
- | /*EMPTY*/
- { $$ = NIL; }
;
trim_list: a_expr FROM expr_list
@@ -5241,6 +5265,7 @@ relation_name: SpecialRuleRelation
}
;
+name: ColId { $$ = $1; };
database_name: ColId { $$ = $1; };
access_method: ColId { $$ = $1; };
attr_name: ColId { $$ = $1; };
@@ -5250,9 +5275,27 @@ index_name: ColId { $$ = $1; };
/* Functions
* Include date/time keywords as SQL92 extension.
* Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
+ * Any tokens which show up as operators will screw up the parsing if
+ * allowed as identifiers, but are acceptable as ColLabels:
+ * BETWEEN, IN, IS, ISNULL, NOTNULL, OVERLAPS
+ * Thanks to Tom Lane for pointing this out. - thomas 2000-03-29
+ * We need OVERLAPS allowed as a function name to enable the implementation
+ * of argument type variations on the underlying implementation. These
+ * variations are done as SQL-language entries in the pg_proc catalog.
+ * Do not include SUBSTRING here since it has explicit productions
+ * in a_expr to support the goofy SQL9x argument syntax.
+ * - thomas 2000-11-28
*/
-name: ColId { $$ = $1; };
-func_name: ColId { $$ = xlateSqlFunc($1); };
+func_name: ColId { $$ = xlateSqlFunc($1); }
+ | BETWEEN { $$ = xlateSqlFunc("between"); }
+ | ILIKE { $$ = xlateSqlFunc("ilike"); }
+ | IN { $$ = xlateSqlFunc("in"); }
+ | IS { $$ = xlateSqlFunc("is"); }
+ | ISNULL { $$ = xlateSqlFunc("isnull"); }
+ | LIKE { $$ = xlateSqlFunc("like"); }
+ | NOTNULL { $$ = xlateSqlFunc("notnull"); }
+ | OVERLAPS { $$ = xlateSqlFunc("overlaps"); }
+ ;
file_name: Sconst { $$ = $1; };
@@ -5358,14 +5401,6 @@ UserId: ColId { $$ = $1; };
* some of these keywords will have to be removed from this
* list due to shift/reduce conflicts in yacc. If so, move
* down to the ColLabel entity. - thomas 1997-11-06
- * Any tokens which show up as operators will screw up the parsing if
- * allowed as identifiers, but are acceptable as ColLabels:
- * BETWEEN, IN, IS, ISNULL, NOTNULL, OVERLAPS
- * Thanks to Tom Lane for pointing this out. - thomas 2000-03-29
- * Allow LIKE and ILIKE as TokenId (and ColId) to make sure that they
- * are allowed in the func_name production. Otherwise, we can't define
- * more like() and ilike() functions for new data types.
- * - thomas 2000-08-07
*/
ColId: generic { $$ = $1; }
| datetime { $$ = $1; }
@@ -5428,7 +5463,6 @@ TokenId: ABSOLUTE { $$ = "absolute"; }
| FUNCTION { $$ = "function"; }
| GRANT { $$ = "grant"; }
| HANDLER { $$ = "handler"; }
- | ILIKE { $$ = "ilike"; }
| IMMEDIATE { $$ = "immediate"; }
| INCREMENT { $$ = "increment"; }
| INDEX { $$ = "index"; }
@@ -5441,7 +5475,6 @@ TokenId: ABSOLUTE { $$ = "absolute"; }
| LANGUAGE { $$ = "language"; }
| LANCOMPILER { $$ = "lancompiler"; }
| LEVEL { $$ = "level"; }
- | LIKE { $$ = "like"; }
| LOCATION { $$ = "location"; }
| MATCH { $$ = "match"; }
| MAXVALUE { $$ = "maxvalue"; }
@@ -5571,6 +5604,7 @@ ColLabel: ColId { $$ = $1; }
| GLOBAL { $$ = "global"; }
| GROUP { $$ = "group"; }
| HAVING { $$ = "having"; }
+ | ILIKE { $$ = "ilike"; }
| INITIALLY { $$ = "initially"; }
| IN { $$ = "in"; }
| INNER_P { $$ = "inner"; }
@@ -5582,6 +5616,8 @@ ColLabel: ColId { $$ = $1; }
| JOIN { $$ = "join"; }
| LEADING { $$ = "leading"; }
| LEFT { $$ = "left"; }
+ | LIKE { $$ = "like"; }
+ | LIMIT { $$ = "limit"; }
| LISTEN { $$ = "listen"; }
| LOAD { $$ = "load"; }
| LOCAL { $$ = "local"; }
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index d7f4da718bf..9ccbaa1f488 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.52 2000/11/11 19:55:19 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.53 2000/12/03 14:51:01 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -594,7 +594,6 @@ timestamp_time(PG_FUNCTION_ARGS)
PG_RETURN_TIMEADT(result);
}
-
/* datetime_timestamp()
* Convert date and time to timestamp data type.
*/
@@ -612,7 +611,6 @@ datetime_timestamp(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMP(result);
}
-
/* time_interval()
* Convert time to interval data type.
*/
@@ -630,6 +628,72 @@ time_interval(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result);
}
+/* interval_time()
+ * Convert interval to time data type.
+ */
+Datum
+interval_time(PG_FUNCTION_ARGS)
+{
+ Interval *span = PG_GETARG_INTERVAL_P(0);
+ TimeADT result;
+ Interval span1;
+
+ result = span->time;
+ TMODULO(result, span1.time, 86400e0);
+
+ PG_RETURN_TIMEADT(result);
+}
+
+/* time_pl_interval()
+ * Add interval to time.
+ */
+Datum
+time_pl_interval(PG_FUNCTION_ARGS)
+{
+ TimeADT time = PG_GETARG_TIMEADT(0);
+ Interval *span = PG_GETARG_INTERVAL_P(1);
+ TimeADT result;
+ TimeADT time1;
+
+ result = (time + span->time);
+ TMODULO(result, time1, 86400e0);
+ if (result < 0)
+ result += 86400;
+
+ PG_RETURN_TIMEADT(result);
+}
+
+/* time_mi_interval()
+ * Subtract interval from time.
+ */
+Datum
+time_mi_interval(PG_FUNCTION_ARGS)
+{
+ TimeADT time = PG_GETARG_TIMEADT(0);
+ Interval *span = PG_GETARG_INTERVAL_P(1);
+ TimeADT result;
+ TimeADT time1;
+
+ result = (time - span->time);
+ TMODULO(result, time1, 86400e0);
+ if (result < 0)
+ result += 86400;
+
+ PG_RETURN_TIMEADT(result);
+}
+
+/* interval_pl_time()
+ * Add time to interval.
+ */
+Datum
+interval_pl_time(PG_FUNCTION_ARGS)
+{
+ Datum span = PG_GETARG_DATUM(0);
+ Datum time = PG_GETARG_DATUM(1);
+
+ return DirectFunctionCall2(time_pl_interval, time, span);
+}
+
/* time_text()
* Convert time to text data type.
@@ -856,6 +920,50 @@ timetz_smaller(PG_FUNCTION_ARGS)
PG_RETURN_TIMETZADT_P(time2);
}
+/* timetz_pl_interval()
+ * Add interval to timetz.
+ */
+Datum
+timetz_pl_interval(PG_FUNCTION_ARGS)
+{
+ TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
+ Interval *span = PG_GETARG_INTERVAL_P(1);
+ TimeTzADT *result;
+ TimeTzADT time1;
+
+ result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+
+ result->time = (time->time + span->time);
+ TMODULO(result->time, time1.time, 86400e0);
+ if (result->time < 0)
+ result->time += 86400;
+ result->zone = time->zone;
+
+ PG_RETURN_TIMETZADT_P(result);
+}
+
+/* timetz_mi_interval()
+ * Subtract interval from timetz.
+ */
+Datum
+timetz_mi_interval(PG_FUNCTION_ARGS)
+{
+ TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
+ Interval *span = PG_GETARG_INTERVAL_P(1);
+ TimeTzADT *result;
+ TimeTzADT time1;
+
+ result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+
+ result->time = (time->time - span->time);
+ TMODULO(result->time, time1.time, 86400e0);
+ if (result->time < 0)
+ result->time += 86400;
+ result->zone = time->zone;
+
+ PG_RETURN_TIMETZADT_P(result);
+}
+
/* overlaps_timetz()
* Implements the SQL92 OVERLAPS operator.
* Algorithm from Date and Darwen, 1997