*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.111 2001/09/29 04:02:21 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.112 2001/10/18 17:30:03 thomas Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
{
TransactionState s = CurrentTransactionState;
- *msec = s->startTimeMsec;
+ *msec = s->startTimeUsec;
return s->startTime;
}
#if NOT_USED
s->startTime = GetCurrentAbsoluteTime();
#endif
- s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeMsec));
+ s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
/*
* initialize the various transaction subsystems
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.53 2001/09/19 15:19:12 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.54 2001/10/18 17:30:14 thomas Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/paths.h"
#include "parser/parse_expr.h"
#include "utils/builtins.h"
+#include "utils/date.h"
#include "utils/guc.h"
#include "utils/tqual.h"
static bool show_datestyle(void);
static bool reset_datestyle(void);
-static bool parse_datestyle(char *);
+static bool parse_datestyle(List *);
static bool show_timezone(void);
static bool reset_timezone(void);
-static bool parse_timezone(char *);
+static bool parse_timezone(List *);
static bool show_XactIsoLevel(void);
static bool reset_XactIsoLevel(void);
-static bool parse_XactIsoLevel(char *);
-static bool parse_random_seed(char *);
+static bool parse_XactIsoLevel(List *);
static bool show_random_seed(void);
static bool reset_random_seed(void);
+static bool parse_random_seed(List *);
static bool show_client_encoding(void);
static bool reset_client_encoding(void);
-static bool parse_client_encoding(char *);
+static bool parse_client_encoding(List *);
static bool show_server_encoding(void);
static bool reset_server_encoding(void);
-static bool parse_server_encoding(char *);
+static bool parse_server_encoding(List *);
/*
/*
- * DATE_STYLE
+ * DATESTYLE
*
* NOTE: set_default_datestyle() is called during backend startup to check
* if the PGDATESTYLE environment variable is set. We want the env var
static bool DefaultEuroDates;
static bool
-parse_datestyle(char *value)
+parse_datestyle_internal(char *value)
{
char *tok;
int dcnt = 0,
ecnt = 0;
if (value == NULL)
- {
- reset_datestyle();
- return TRUE;
- }
+ return reset_datestyle();
while ((value = get_token(&tok, NULL, value)) != 0)
{
return TRUE;
}
+static bool
+parse_datestyle(List *args)
+{
+ char *value;
+
+ if (args == NULL)
+ return reset_datestyle();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+ return parse_datestyle_internal(value);
+}
+
static bool
show_datestyle(void)
{
*/
DBDate = strdup(DBDate);
- /* Parse desired setting into DateStyle/EuroDates */
- parse_datestyle(DBDate);
+ /* Parse desired setting into DateStyle/EuroDates
+ * Use parse_datestyle_internal() to avoid any palloc() issues per above
+ * - thomas 2001-10-15
+ */
+ parse_datestyle_internal(DBDate);
free(DBDate);
/* parse_timezone()
* Handle SET TIME ZONE...
* Try to save existing TZ environment variable for later use in RESET TIME ZONE.
- * - thomas 1997-11-10
+ * Accept an explicit interval per SQL9x, though this is less useful than a full time zone.
+ * - thomas 2001-10-11
*/
static bool
-parse_timezone(char *value)
+parse_timezone(List *args)
{
- char *tok;
+ List *arg;
+ TypeName *type;
- if (value == NULL)
- {
- reset_timezone();
- return TRUE;
- }
+ if (args == NULL)
+ return reset_timezone();
- while ((value = get_token(&tok, NULL, value)) != 0)
+ Assert(IsA(args, List));
+
+ foreach(arg, args)
{
- /* Not yet tried to save original value from environment? */
- if (defaultTZ == NULL)
- {
- /* found something? then save it for later */
- if ((defaultTZ = getenv("TZ")) != NULL)
- strcpy(TZvalue, defaultTZ);
+ A_Const *p;
- /* found nothing so mark with an invalid pointer */
- else
- defaultTZ = (char *) -1;
- }
+ Assert(IsA(arg, List));
+ p = lfirst(arg);
+ Assert(IsA(p, A_Const));
- strcpy(tzbuf, "TZ=");
- strcat(tzbuf, tok);
- if (putenv(tzbuf) != 0)
- elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+ type = p->typename;
+ if (type != NULL)
+ {
+ if (strcmp(type->name, "interval") == 0)
+ {
+ Interval *interval;
+
+ interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
+ CStringGetDatum(p->val.val.str),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ if (interval->month != 0)
+ elog(ERROR, "SET TIME ZONE illegal INTERVAL; month not allowed");
+ CTimeZone = interval->time;
+ }
+ else if (strcmp(type->name, "float8") == 0)
+ {
+ float8 time;
+
+ time = DatumGetFloat8(DirectFunctionCall1(float8in, CStringGetDatum(p->val.val.str)));
+ CTimeZone = time * 3600;
+ }
+ /* We do not actually generate an integer constant in gram.y so this is not used... */
+ else if (strcmp(type->name, "int4") == 0)
+ {
+ int32 time;
+
+ time = p->val.val.ival;
+ CTimeZone = time * 3600;
+ }
+ else
+ {
+ elog(ERROR, "Unable to process SET TIME ZONE command; internal coding error");
+ }
- tzset();
+ HasCTZSet = true;
+ }
+ else
+ {
+ char *tok;
+ char *value;
+
+ value = p->val.val.str;
+
+ while ((value = get_token(&tok, NULL, value)) != 0)
+ {
+ /* Not yet tried to save original value from environment? */
+ if (defaultTZ == NULL)
+ {
+ /* found something? then save it for later */
+ if ((defaultTZ = getenv("TZ")) != NULL)
+ strcpy(TZvalue, defaultTZ);
+
+ /* found nothing so mark with an invalid pointer */
+ else
+ defaultTZ = (char *) -1;
+ }
+
+ strcpy(tzbuf, "TZ=");
+ strcat(tzbuf, tok);
+ if (putenv(tzbuf) != 0)
+ elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+
+ tzset();
+ }
+
+ HasCTZSet = false;
+ }
}
return TRUE;
static bool
show_timezone(void)
{
- char *tz;
+ char *tzn;
+
+ if (HasCTZSet)
+ {
+ Interval interval;
- tz = getenv("TZ");
+ interval.month = 0;
+ interval.time = CTimeZone;
+
+ tzn = DatumGetCString(DirectFunctionCall1(interval_out, IntervalPGetDatum(&interval)));
+ }
+ else
+ {
+ tzn = getenv("TZ");
+ }
- elog(NOTICE, "Time zone is %s", ((tz != NULL) ? tz : "unset"));
+ if (tzn != NULL)
+ elog(NOTICE, "Time zone is '%s'", tzn);
+ else
+ elog(NOTICE, "Time zone is unset");
return TRUE;
} /* show_timezone() */
static bool
reset_timezone(void)
{
+ if (HasCTZSet)
+ {
+ HasCTZSet = false;
+ }
+
/* no time zone has been set in this session? */
- if (defaultTZ == NULL)
+ else if (defaultTZ == NULL)
{
}
-/* SET TRANSACTION */
+/*
+ *
+ * SET TRANSACTION
+ *
+ */
static bool
-parse_XactIsoLevel(char *value)
+parse_XactIsoLevel(List *args)
{
+ char *value;
- if (value == NULL)
- {
- reset_XactIsoLevel();
- return TRUE;
- }
+ if (args == NULL)
+ return reset_XactIsoLevel();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
if (SerializableSnapshot != NULL)
{
return TRUE;
}
-
if (strcmp(value, "serializable") == 0)
XactIsoLevel = XACT_SERIALIZABLE;
else if (strcmp(value, "read committed") == 0)
* Random number seed
*/
static bool
-parse_random_seed(char *value)
+parse_random_seed(List *args)
{
- double seed = 0;
+ char *value;
+ double seed = 0;
+
+ if (args == NULL)
+ return reset_random_seed();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+ sscanf(value, "%lf", &seed);
+ DirectFunctionCall1(setseed, Float8GetDatum(seed));
- if (value == NULL)
- reset_random_seed();
- else
- {
- sscanf(value, "%lf", &seed);
- DirectFunctionCall1(setseed, Float8GetDatum(seed));
- }
return (TRUE);
}
*/
static bool
-parse_client_encoding(char *value)
+parse_client_encoding(List *args)
{
+ char *value;
#ifdef MULTIBYTE
- int encoding;
+ int encoding;
+#endif
+ if (args == NULL)
+ return reset_client_encoding();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+#ifdef MULTIBYTE
encoding = pg_valid_client_encoding(value);
if (encoding < 0)
{
if (value)
- elog(ERROR, "Client encoding %s is not supported", value);
+ elog(ERROR, "Client encoding '%s' is not supported", value);
else
elog(ERROR, "No client encoding is specified");
}
static bool
show_client_encoding(void)
{
- elog(NOTICE, "Current client encoding is %s",
- pg_get_client_encoding_name());
+ elog(NOTICE, "Current client encoding is '%s'",
+ pg_get_client_encoding_name());
return TRUE;
}
}
else
encoding = GetDatabaseEncoding();
+
pg_set_client_encoding(encoding);
#endif
return TRUE;
static bool
-parse_server_encoding(char *value)
+parse_server_encoding(List *args)
{
elog(NOTICE, "SET SERVER_ENCODING is not supported");
return TRUE;
static bool
show_server_encoding(void)
{
- elog(NOTICE, "Current server encoding is %s", GetDatabaseEncodingName());
+ elog(NOTICE, "Current server encoding is '%s'", GetDatabaseEncodingName());
return TRUE;
}
+/* SetPGVariable()
+ * Dispatcher for handling SET commands.
+ * Special cases ought to be removed and handled separately by TCOP
+ */
void
-SetPGVariable(const char *name, const char *value)
+SetPGVariable(const char *name, List *args)
{
- char *mvalue = value ? pstrdup(value) : ((char *) NULL);
-
- /*
- * Special cases ought to be removed and handled separately by TCOP
- */
if (strcasecmp(name, "datestyle") == 0)
- parse_datestyle(mvalue);
+ parse_datestyle(args);
else if (strcasecmp(name, "timezone") == 0)
- parse_timezone(mvalue);
+ parse_timezone(args);
else if (strcasecmp(name, "XactIsoLevel") == 0)
- parse_XactIsoLevel(mvalue);
+ parse_XactIsoLevel(args);
else if (strcasecmp(name, "client_encoding") == 0)
- parse_client_encoding(mvalue);
+ parse_client_encoding(args);
else if (strcasecmp(name, "server_encoding") == 0)
- parse_server_encoding(mvalue);
+ parse_server_encoding(args);
else if (strcasecmp(name, "seed") == 0)
- parse_random_seed(mvalue);
- else if (strcasecmp(name, "session_authorization") == 0)
- SetSessionAuthorization(value);
+ parse_random_seed(args);
else
- SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+ {
+ /* For routines defined somewhere else,
+ * go ahead and extract the string argument
+ * to match the original interface definition.
+ * Later, we can change this code too...
+ */
+ char *value;
- if (mvalue)
- pfree(mvalue);
+ value = ((args != NULL)? ((A_Const *) lfirst(args))->val.val.str: NULL);
+
+ if (strcasecmp(name, "session_authorization") == 0)
+ SetSessionAuthorization(value);
+ else
+ SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+ }
+ return;
}
void
show_client_encoding();
show_server_encoding();
show_random_seed();
- } else
+ }
+ else
{
const char *val = GetConfigOption(name);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.157 2001/10/02 21:39:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.158 2001/10/18 17:30:14 thomas Exp $
*
*-------------------------------------------------------------------------
*/
if (from->name)
newnode->name = pstrdup(from->name);
- if (from->value)
- newnode->value = pstrdup(from->value);
+ Node_Copy(from, newnode, args);
return newnode;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.105 2001/10/02 21:39:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.106 2001/10/18 17:30:14 thomas Exp $
*
*-------------------------------------------------------------------------
*/
{
if (!equalstr(a->name, b->name))
return false;
- if (!equalstr(a->value, b->value))
+ if (!equal(a->args, b->args))
return false;
return true;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.262 2001/10/10 00:02:42 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.263 2001/10/18 17:30:14 thomas Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/numeric.h"
+#include "utils/datetime.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
static Node *makeTypeCast(Node *arg, TypeName *typename);
+static Node *makeStringConst(char *str, TypeName *typename);
+static Node *makeFloatConst(char *str);
static Node *makeRowExpr(char *opr, List *largs, List *rargs);
static void mapTargetColumns(List *source, List *target);
static SelectStmt *findLeftmostSelect(SelectStmt *node);
static Node *doNegate(Node *n);
static void doNegateFloat(Value *v);
+#define MASK(b) (1 << (b))
+
%}
%type <list> extract_list, position_list
%type <list> substr_list, trim_list
-%type <list> opt_interval
+%type <ival> opt_interval
%type <node> substr_from, substr_for
%type <boolean> opt_binary, opt_using, opt_instead, opt_cursor
%type <ival> Iconst
%type <str> Sconst, comment_text
-%type <str> UserId, opt_boolean, var_value, zone_value, ColId_or_Sconst
+%type <str> UserId, opt_boolean, var_value, ColId_or_Sconst
%type <str> ColId, ColLabel, TokenId
+%type <node> zone_value
%type <node> TableConstraint
%type <list> ColQualList
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2;
- n->value = $4;
+ n->args = makeList1(makeStringConst($4, NULL));
$$ = (Node *) n;
}
| SET ColId '=' var_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2;
- n->value = $4;
+ n->args = makeList1(makeStringConst($4, NULL));
$$ = (Node *) n;
}
| SET TIME ZONE zone_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "timezone";
- n->value = $4;
+ if ($4 != NULL)
+ n->args = makeList1($4);
$$ = (Node *) n;
}
| SET TRANSACTION ISOLATION LEVEL opt_level
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "XactIsoLevel";
- n->value = $5;
+ n->args = makeList1(makeStringConst($5, NULL));
$$ = (Node *) n;
}
| SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL opt_level
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "default_transaction_isolation";
- n->value = $8;
+ n->args = makeList1(makeStringConst($8, NULL));
$$ = (Node *) n;
}
| SET NAMES opt_encoding
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "client_encoding";
- n->value = $3;
+ n->args = makeList1(makeStringConst($3, NULL));
$$ = (Node *) n;
}
| SET SESSION AUTHORIZATION ColId_or_Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "session_authorization";
- n->value = $4;
+ n->args = makeList1(makeStringConst($4, NULL));
$$ = (Node *) n;
}
;
| OFF { $$ = "off"; }
;
-zone_value: Sconst { $$ = $1; }
+/* Timezone values can be:
+ * - a string such as 'pst8pdt'
+ * - an integer or floating point number
+ * - a time interval per SQL99
+ */
+zone_value: Sconst
+ {
+ $$ = makeStringConst($1, NULL);
+ }
+ | ConstInterval Sconst opt_interval
+ {
+ A_Const *n = (A_Const *) makeStringConst($2, $1);
+ n->typename->typmod = (($3 << 16) | 0xFFFF);
+ $$ = (Node *)n;
+ }
+ | ConstInterval '(' Iconst ')' Sconst opt_interval
+ {
+ A_Const *n = (A_Const *) makeStringConst($5, $1);
+ n->typename->typmod = (($3 << 16) | $6);
+ $$ = (Node *)n;
+ }
+ | FCONST
+ {
+ $$ = makeFloatConst($1);
+ }
+ | '-' FCONST
+ {
+ $$ = doNegate(makeFloatConst($2));
+ }
+ | ICONST
+ {
+ char buf[64];
+ sprintf(buf, "%d", $1);
+ $$ = makeFloatConst(pstrdup(buf));
+ }
+ | '-' ICONST
+ {
+ char buf[64];
+ sprintf(buf, "%d", $2);
+ $$ = doNegate(makeFloatConst(pstrdup(buf)));
+ }
| DEFAULT { $$ = NULL; }
| LOCAL { $$ = NULL; }
;
;
SimpleTypename: ConstTypename
- | ConstInterval
+ | ConstInterval opt_interval
+ {
+ $$ = $1;
+ $$->typmod = (($2 << 16) | 0xFFFF);
+ }
+ | ConstInterval '(' Iconst ')' opt_interval
+ {
+ $$ = $1;
+ $$->typmod = (($5 << 16) | $3);
+ }
;
ConstTypename: GenericType
* - thomas 2001-09-06
*/
$$->timezone = $2;
- $$->typmod = 0;
+ /* SQL99 specified a default precision of six.
+ * - thomas 2001-09-30
+ */
+ $$->typmod = 6;
}
| TIME '(' Iconst ')' opt_timezone
{
}
;
-ConstInterval: INTERVAL opt_interval
+ConstInterval: INTERVAL
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("interval");
| /*EMPTY*/ { $$ = FALSE; }
;
-opt_interval: datetime { $$ = makeList1($1); }
- | YEAR_P TO MONTH_P { $$ = NIL; }
- | DAY_P TO HOUR_P { $$ = NIL; }
- | DAY_P TO MINUTE_P { $$ = NIL; }
- | DAY_P TO SECOND_P { $$ = NIL; }
- | HOUR_P TO MINUTE_P { $$ = NIL; }
- | HOUR_P TO SECOND_P { $$ = NIL; }
- | MINUTE_P TO SECOND_P { $$ = NIL; }
- | /*EMPTY*/ { $$ = NIL; }
+opt_interval: YEAR_P { $$ = MASK(YEAR); }
+ | MONTH_P { $$ = MASK(MONTH); }
+ | DAY_P { $$ = MASK(DAY); }
+ | HOUR_P { $$ = MASK(HOUR); }
+ | MINUTE_P { $$ = MASK(MINUTE); }
+ | SECOND_P { $$ = MASK(SECOND); }
+ | YEAR_P TO MONTH_P { $$ = MASK(YEAR) | MASK(MONTH); }
+ | DAY_P TO HOUR_P { $$ = MASK(DAY) | MASK(HOUR); }
+ | DAY_P TO MINUTE_P { $$ = MASK(DAY) | MASK(HOUR) | MASK(MINUTE); }
+ | DAY_P TO SECOND_P { $$ = MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND); }
+ | HOUR_P TO MINUTE_P { $$ = MASK(HOUR) | MASK(MINUTE); }
+ | HOUR_P TO SECOND_P { $$ = MASK(HOUR) | MASK(MINUTE) | MASK(SECOND); }
+ | MINUTE_P TO SECOND_P { $$ = MASK(MINUTE) | MASK(SECOND); }
+ | /*EMPTY*/ { $$ = -1; }
;
n->typename = $1;
n->val.type = T_String;
n->val.val.str = $2;
+ n->typename->typmod = (($3 << 16) | 0xFFFF);
+ $$ = (Node *)n;
+ }
+ | ConstInterval '(' Iconst ')' Sconst opt_interval
+ {
+ A_Const *n = makeNode(A_Const);
+ n->typename = $1;
+ n->val.type = T_String;
+ n->val.val.str = $5;
+ n->typename->typmod = (($6 << 16) | $3);
$$ = (Node *)n;
}
| ParamNo
ColId: IDENT { $$ = $1; }
| datetime { $$ = $1; }
| TokenId { $$ = $1; }
- | INTERVAL { $$ = "interval"; }
| NATIONAL { $$ = "national"; }
| NONE { $$ = "none"; }
| PATH_P { $$ = "path"; }
| GROUP { $$ = "group"; }
| HAVING { $$ = "having"; }
| ILIKE { $$ = "ilike"; }
- | INITIALLY { $$ = "initially"; }
| IN { $$ = "in"; }
+ | INITIALLY { $$ = "initially"; }
| INNER_P { $$ = "inner"; }
+ | INOUT { $$ = "inout"; }
| INTERSECT { $$ = "intersect"; }
+ | INTERVAL { $$ = "interval"; }
| INTO { $$ = "into"; }
- | INOUT { $$ = "inout"; }
| IS { $$ = "is"; }
| ISNULL { $$ = "isnull"; }
| JOIN { $$ = "join"; }
}
}
+static Node *
+makeStringConst(char *str, TypeName *typename)
+{
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = str;
+ n->typename = typename;
+
+ return (Node *)n;
+}
+
+static Node *
+makeFloatConst(char *str)
+{
+ A_Const *n = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+ n->val.type = T_Float;
+ n->val.val.str = str;
+ t->name = xlateSqlType("float");
+ t->typmod = -1;
+ n->typename = t;
+
+ return (Node *)n;
+}
+
/* makeRowExpr()
* Generate separate operator nodes for a single row descriptor expression.
* Perhaps this should go deeper in the parser someday...
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.120 2001/10/12 00:07:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.121 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
{
VariableSetStmt *n = (VariableSetStmt *) parsetree;
- SetPGVariable(n->name, n->value);
+ SetPGVariable(n->name, n->args);
set_ps_display(commandTag = "SET VARIABLE");
}
break;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.61 2001/10/04 15:14:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.62 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
Int32GetDatum(-1));
}
+/* timetz_part()
+ * Extract specified field from time type.
+ */
+Datum
+timetz_part(PG_FUNCTION_ARGS)
+{
+ text *units = PG_GETARG_TEXT_P(0);
+ TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
+ float8 result;
+ int type,
+ val;
+ int i;
+ char *up,
+ *lp,
+ lowunits[MAXDATELEN + 1];
+
+ if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
+ elog(ERROR, "TIMETZ units '%s' not recognized",
+ DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(units))));
+ up = VARDATA(units);
+ lp = lowunits;
+ for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+ *lp++ = tolower((unsigned char) *up++);
+ *lp = '\0';
+
+ type = DecodeUnits(0, lowunits, &val);
+ if (type == UNKNOWN_FIELD)
+ type = DecodeSpecial(0, lowunits, &val);
+
+ if (type == UNITS)
+ {
+ double trem;
+ double dummy;
+ int tz;
+ double fsec;
+ struct tm tt,
+ *tm = &tt;
+
+ trem = time->time;
+ TMODULO(trem, tm->tm_hour, 3600e0);
+ TMODULO(trem, tm->tm_min, 60e0);
+ TMODULO(trem, tm->tm_sec, 1e0);
+ fsec = trem;
+ tz = time->zone;
+
+ switch (val)
+ {
+ case DTK_TZ:
+ result = tz;
+ break;
+
+ case DTK_TZ_MINUTE:
+ result = tz / 60;
+ TMODULO(result, dummy, 60e0);
+ break;
+
+ case DTK_TZ_HOUR:
+ dummy = tz;
+ TMODULO(dummy, result, 3600e0);
+ break;
+
+ case DTK_MICROSEC:
+ result = ((tm->tm_sec + fsec) * 1000000);
+ break;
+
+ case DTK_MILLISEC:
+ result = ((tm->tm_sec + fsec) * 1000);
+ break;
+
+ case DTK_SECOND:
+ result = (tm->tm_sec + fsec);
+ break;
+
+ case DTK_MINUTE:
+ result = tm->tm_min;
+ break;
+
+ case DTK_HOUR:
+ result = tm->tm_hour;
+ break;
+
+ case DTK_DAY:
+ case DTK_MONTH:
+ case DTK_QUARTER:
+ case DTK_YEAR:
+ case DTK_DECADE:
+ case DTK_CENTURY:
+ case DTK_MILLENNIUM:
+ default:
+ elog(ERROR, "TIMETZ units '%s' not supported",
+ DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(units))));
+ result = 0;
+ }
+ }
+ else if ((type == RESERV) && (val == DTK_EPOCH))
+ {
+ result = time->time - time->zone;
+ }
+ else
+ {
+ elog(ERROR, "TIMETZ units '%s' not recognized",
+ DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(units))));
+ result = 0;
+ }
+
+ PG_RETURN_FLOAT8(result);
+}
+
/* timetz_zone()
* Encode time with time zone type with specified time zone.
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.72 2001/10/11 18:06:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.73 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
static int DecodePosixTimezone(char *str, int *val);
+void TrimTrailingZeros(char *str);
int day_tab[2][13] = {
sizeof australian_datetktbl[0];
static datetkn deltatktbl[] = {
-/* text, token, lexval */
- {"@", IGNORE, 0}, /* postgres relative time prefix */
+ /* text, token, lexval */
+ {"@", IGNORE, 0}, /* postgres relative prefix */
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
- {"c", UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"cent", UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative time units */
- {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"d", UNITS, DTK_DAY}, /* "day" relative time units */
- {DDAY, UNITS, DTK_DAY}, /* "day" relative time units */
- {"days", UNITS, DTK_DAY}, /* "days" relative time units */
- {"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */
- {"decs", UNITS, DTK_DECADE},/* "decades" relative time units */
- {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative time units */
- {"decades", UNITS, DTK_DECADE}, /* "decades" relative time units */
- {"h", UNITS, DTK_HOUR}, /* "hour" relative time units */
- {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative time units */
- {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */
- {"hr", UNITS, DTK_HOUR}, /* "hour" relative time units */
- {"hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */
+ {"c", UNITS, DTK_CENTURY}, /* "century" relative */
+ {"cent", UNITS, DTK_CENTURY}, /* "century" relative */
+ {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative */
+ {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
+ {"d", UNITS, DTK_DAY}, /* "day" relative */
+ {DDAY, UNITS, DTK_DAY}, /* "day" relative */
+ {"days", UNITS, DTK_DAY}, /* "days" relative */
+ {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
+ {"decs", UNITS, DTK_DECADE}, /* "decades" relative */
+ {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative */
+ {"decades", UNITS, DTK_DECADE}, /* "decades" relative */
+ {"h", UNITS, DTK_HOUR}, /* "hour" relative */
+ {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative */
+ {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
+ {"hr", UNITS, DTK_HOUR}, /* "hour" relative */
+ {"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
{INVALID, RESERV, DTK_INVALID}, /* reserved for invalid time */
- {"m", UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative
- * time units */
- {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative time
- * units */
- {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative time units */
- {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative
- * time units */
- {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative
- * time units */
- {"millisecon", UNITS, DTK_MILLISEC}, /* relative time units */
- {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
- {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
- {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative time units */
- {"mon", UNITS, DTK_MONTH}, /* "months" relative time units */
- {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
- {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
+ {"m", UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
+ {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
+ {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
+ {"millisecon", UNITS, DTK_MILLISEC}, /* relative */
+ {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
+ {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {"mon", UNITS, DTK_MONTH}, /* "months" relative */
+ {"mons", UNITS, DTK_MONTH}, /* "months" relative */
+ {DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
{"months", UNITS, DTK_MONTH},
{"ms", UNITS, DTK_MILLISEC},
{"msec", UNITS, DTK_MILLISEC},
{DMILLISEC, UNITS, DTK_MILLISEC},
{"mseconds", UNITS, DTK_MILLISEC},
{"msecs", UNITS, DTK_MILLISEC},
- {"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time */
- {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time */
- {"reltime", IGNORE, 0}, /* for pre-v6.1 "Undefined Reltime" */
+ {"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative */
+ {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
+ {"reltime", IGNORE, 0}, /* pre-v6.1 "Undefined Reltime" */
{"s", UNITS, DTK_SECOND},
{"sec", UNITS, DTK_SECOND},
{DSECOND, UNITS, DTK_SECOND},
{"seconds", UNITS, DTK_SECOND},
{"secs", UNITS, DTK_SECOND},
- {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
+ {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
{"timezone", UNITS, DTK_TZ}, /* "timezone" time offset */
{"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
{"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
- {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
- {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time
- * units */
- {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative time
- * units */
- {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
- * units */
- {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
- * units */
- {"w", UNITS, DTK_WEEK}, /* "week" relative time units */
- {DWEEK, UNITS, DTK_WEEK}, /* "week" relative time units */
- {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */
- {"y", UNITS, DTK_YEAR}, /* "year" relative time units */
- {DYEAR, UNITS, DTK_YEAR}, /* "year" relative time units */
- {"years", UNITS, DTK_YEAR}, /* "years" relative time units */
- {"yr", UNITS, DTK_YEAR}, /* "year" relative time units */
- {"yrs", UNITS, DTK_YEAR}, /* "years" relative time units */
+ {"us", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
+ {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
+ {"w", UNITS, DTK_WEEK}, /* "week" relative */
+ {DWEEK, UNITS, DTK_WEEK}, /* "week" relative */
+ {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
+ {"y", UNITS, DTK_YEAR}, /* "year" relative */
+ {DYEAR, UNITS, DTK_YEAR}, /* "year" relative */
+ {"years", UNITS, DTK_YEAR}, /* "years" relative */
+ {"yr", UNITS, DTK_YEAR}, /* "year" relative */
+ {"yrs", UNITS, DTK_YEAR}, /* "years" relative */
};
static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
{
int m12 = (m - 14) / 12;
- return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12
- - (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075);
+ return ((1461 * (y + 4800 + m12)) / 4
+ + (367 * (m - 2 - 12 * (m12))) / 12
+ - (3 * ((y + 4900 + m12) / 100)) / 4
+ + d - 32075);
} /* date2j() */
void
} /* j2day() */
-/*
- * parse and convert date in timestr (the normal interface)
- *
- * Returns the number of seconds since epoch (J2000)
- */
+void
+TrimTrailingZeros(char *str)
+{
+ int len = strlen(str);
+
+ /* chop off trailing one to cope with interval rounding */
+ if (strcmp((str + len - 4), "0001") == 0)
+ {
+ len -= 4;
+ *(str + len) = '\0';
+ }
+
+ /* chop off trailing zeros... */
+ while ((*(str + len - 1) == '0')
+ && (*(str + len - 3) != '.'))
+ {
+ len--;
+ *(str + len) = '\0';
+ }
+ return;
+}
+
/* ParseDateTime()
* Break string into tokens based on a date/time context.
{
int tz;
- if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+ if (HasCTZSet)
+ {
+ tz = CTimeZone;
+ }
+ else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
/*
* 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
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
sprintf((str + strlen(str)), ":%02.0f", sec);
}
- if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+ /* tzp == NULL indicates that we don't want *any* time zone info in the output string.
+ * *tzn != NULL indicates that we *have* time zone info available.
+ * tm_isdst != -1 indicates that we have a valid time zone translation.
+ */
+ if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
{
- if (tzp != NULL)
- {
- hour = -(*tzp / 3600);
- min = ((abs(*tzp) / 60) % 60);
- }
- else
- {
- hour = 0;
- min = 0;
- }
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
}
-
}
else
{
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (tzp != NULL)
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
sprintf((str + 5), "/%04d %02d:%02d %s",
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (tzp != NULL)
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
sprintf((str + 5), ".%04d %02d:%02d %s",
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
}
sprintf((str + strlen(str)), " %04d", tm->tm_year);
- if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+
+ if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (HasCTZSet && (tzp != NULL))
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
{
if (fsec != 0)
{
fsec += tm->tm_sec;
- sprintf(cp, ":%05.2f", fabs(fsec));
+ sprintf(cp, ":%013.10f", fabs(fsec));
+ TrimTrailingZeros(cp);
cp += strlen(cp);
is_nonzero = TRUE;
-
- /* otherwise, integer seconds only? */
}
+ /* otherwise, integer seconds only? */
else if (tm->tm_sec != 0)
{
sprintf(cp, ":%02d", abs(tm->tm_sec));
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.87 2001/10/01 02:31:33 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.88 2001/10/18 17:30:15 thomas Exp $
*
* NOTES
*
/* GetCurrentAbsoluteTime()
* Get the current system time. Set timezone parameters if not specified elsewhere.
- * Define HasTZSet to allow clients to specify the default timezone.
+ * Define HasCTZSet to allow clients to specify the default timezone.
*
* Returns the number of seconds since epoch (January 1 1970 GMT)
*/
*/
strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
#endif
- };
+ }
return (AbsoluteTime) now;
} /* GetCurrentAbsoluteTime() */
/* GetCurrentAbsoluteTime()
* Get the current system time. Set timezone parameters if not specified elsewhere.
- * Define HasTZSet to allow clients to specify the default timezone.
+ * Define HasCTZSet to allow clients to specify the default timezone.
*
* Returns the number of seconds since epoch (January 1 1970 GMT)
*/
void
-abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char *tzn)
+abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
{
time_t time = (time_t) _time;
ftime(&tb);
#endif
+ /* If HasCTZSet is true then we have a brute force time zone specified.
+ * Go ahead and rotate to the local time zone since we will later bypass
+ * any calls which adjust the tm fields.
+ */
+ if (HasCTZSet && (tzp != NULL))
+ time -= CTimeZone;
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
- if (tzp != NULL)
+ if ((! HasCTZSet) && (tzp != NULL))
{
tx = localtime((time_t *) &time);
#ifdef NO_MKTIME_BEFORE_1970
tm->tm_zone = tx->tm_zone;
if (tzp != NULL)
- *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
- /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
- if (tzn != NULL)
{
-
- /*
- * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
- * contains an error message, which doesn't fit in the buffer
+ /* We have a brute force time zone per SQL99?
+ * Then use it without change
+ * since we have already rotated to the time zone.
*/
- StrNCpy(tzn, tm->tm_zone, MAXTZLEN + 1);
- if (strlen(tm->tm_zone) > MAXTZLEN)
- elog(NOTICE, "Invalid timezone \'%s\'", tm->tm_zone);
+ if (HasCTZSet)
+ {
+ *tzp = CTimeZone;
+ tm->tm_gmtoff = CTimeZone;
+ tm->tm_isdst = -1;
+ tm->tm_zone = NULL;
+ if (tzn != NULL)
+ *tzn = NULL;
+ }
+ else
+ {
+ *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
+
+ /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
+ if (tzn != NULL)
+ {
+ /*
+ * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
+ * contains an error message, which doesn't fit in the buffer
+ */
+ StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);
+ if (strlen(tm->tm_zone) > MAXTZLEN)
+ elog(NOTICE, "Invalid timezone \'%s\'", tm->tm_zone);
+ }
+ }
}
#elif defined(HAVE_INT_TIMEZONE)
if (tzp != NULL)
- *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
-
- if (tzn != NULL)
- {
-
- /*
- * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
- * contains an error message, which doesn't fit in the buffer
+ /* We have a brute force time zone per SQL99?
+ * Then use it without change
+ * since we have already rotated to the time zone.
*/
- StrNCpy(tzn, tzname[tm->tm_isdst], MAXTZLEN + 1);
- if (strlen(tzname[tm->tm_isdst]) > MAXTZLEN)
- elog(NOTICE, "Invalid timezone \'%s\'", tzname[tm->tm_isdst]);
+ if (HasCTZSet)
+ {
+ *tzp = CTimeZone;
+ tm->tm_isdst = -1;
+ if (tzn != NULL)
+ *tzn = NULL;
+ }
+ else
+ {
+ *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
+
+ if (tzn != NULL)
+ {
+
+ /*
+ * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
+ * contains an error message, which doesn't fit in the buffer
+ */
+ StrNCpy(*tzn, tzname[tm->tm_isdst], MAXTZLEN + 1);
+ if (strlen(tzname[tm->tm_isdst]) > MAXTZLEN)
+ elog(NOTICE, "Invalid timezone \'%s\'", tzname[tm->tm_isdst]);
+ }
+ }
}
#endif
#else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
if (tzp != NULL)
- *tzp = tb.timezone * 60;
-
- /*
- * XXX does this work to get the local timezone string in V7? - tgl
- * 97/03/18
- */
- if (tzn != NULL)
{
- strftime(tzn, MAXTZLEN, "%Z", localtime(&now));
- tzn[MAXTZLEN] = '\0'; /* let's just be sure it's null-terminated */
+ /* We have a brute force time zone per SQL99?
+ * Then use it without change
+ * since we have already rotated to the time zone.
+ */
+ if (HasCTZSet)
+ {
+ *tzp = CTimeZone;
+ if (tzn != NULL)
+ *tzn = NULL;
+ }
+ else
+ {
+ *tzp = tb.timezone * 60;
+
+ /*
+ * XXX does this work to get the local timezone string in V7? - tgl
+ * 97/03/18
+ */
+ if (tzn != NULL)
+ {
+ strftime(*tzn, MAXTZLEN, "%Z", localtime(&now));
+ tzn[MAXTZLEN] = '\0'; /* let's just be sure it's null-terminated */
+ }
+ }
}
#endif
strcpy(buf, EARLY);
break;
default:
- abstime2tm(time, &tz, tm, tzn);
+ abstime2tm(time, &tz, tm, &tzn);
EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
break;
}
struct tm tt,
*tm = &tt;
int tz;
- char tzn[MAXTZLEN];
+ char zone[MAXDATELEN + 1],
+ *tzn = zone;
switch (abstime)
{
break;
default:
- abstime2tm(abstime, &tz, tm, tzn);
+ abstime2tm(abstime, &tz, tm, &tzn);
result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400) + tz;
break;
};
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.55 2001/10/05 06:38:59 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.56 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
static int EncodeSpecialTimestamp(Timestamp dt, char *str);
static Timestamp dt2local(Timestamp dt, int timezone);
static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
+static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);
/*****************************************************************************
{
case DTK_DATE:
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
- elog(ERROR, "Timestamp out of range '%s'", str);
+ elog(ERROR, "TIMESTAMP out of range '%s'", str);
break;
case DTK_EPOCH:
break;
case DTK_INVALID:
- elog(ERROR, "Timestamp '%s' no longer supported", str);
+ elog(ERROR, "TIMESTAMP '%s' no longer supported", str);
TIMESTAMP_NOEND(result);
break;
default:
- elog(ERROR, "Timestamp '%s' not parsed; internal coding error", str);
+ elog(ERROR, "TIMESTAMP '%s' not parsed; internal coding error", str);
TIMESTAMP_NOEND(result);
}
TimestampTypmod = typmod;
}
- *time = (rint(((double) *time)*TimestampScale)/TimestampScale);
+ *time = (rint(((double) *time) * TimestampScale)/TimestampScale);
}
}
{
case DTK_DATE:
if (tm2timestamp(tm, fsec, &tz, &result) != 0)
- elog(ERROR, "Timestamp out of range '%s'", str);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE out of range '%s'", str);
break;
case DTK_EPOCH:
break;
case DTK_INVALID:
- elog(ERROR, "Timestamp with time zone '%s' no longer supported", str);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE '%s' no longer supported", str);
TIMESTAMP_NOEND(result);
break;
default:
- elog(ERROR, "Timestamp with time zone '%s' not parsed; internal coding error", str);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE '%s' not parsed; internal coding error", str);
TIMESTAMP_NOEND(result);
}
interval_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+ Oid typelem = PG_GETARG_OID(1);
+#endif
+ int32 typmod = PG_GETARG_INT32(2);
Interval *result;
double fsec;
struct tm tt,
case DTK_DELTA:
if (tm2interval(tm, fsec, result) != 0)
elog(ERROR, "Bad interval external representation '%s'", str);
+ AdjustIntervalForTypmod(result, typmod);
break;
case DTK_INVALID:
PG_RETURN_CSTRING(result);
}
+/* interval_scale()
+ * Adjust interval type for specified fields.
+ * Used by PostgreSQL type system to stuff columns.
+ */
+Datum
+interval_scale(PG_FUNCTION_ARGS)
+{
+ Interval *interval = PG_GETARG_INTERVAL_P(0);
+ int32 typmod = PG_GETARG_INT32(1);
+ Interval *result;
+
+ result = palloc(sizeof(Interval));
+ *result = *interval;
+
+ AdjustIntervalForTypmod(result, typmod);
+
+ PG_RETURN_INTERVAL_P(result);
+}
+
+#define MASK(b) (1 << (b))
+
+static void
+AdjustIntervalForTypmod(Interval *interval, int32 typmod)
+{
+ if (typmod != -1)
+ {
+ int range = ((typmod >> 16) & 0xFFFF);
+ int precision = (typmod & 0xFFFF);
+
+ if (range == 0xFFFF)
+ {
+ /* Do nothing... */
+ }
+ if (range == MASK(YEAR))
+ {
+ interval->month = ((interval->month / 12) * 12);
+ interval->time = 0;
+ }
+ else if (range == MASK(MONTH))
+ {
+ interval->month %= 12;
+ interval->time = 0;
+ }
+ /* YEAR TO MONTH */
+ else if (range == (MASK(YEAR) | MASK(MONTH)))
+ {
+ interval->time = 0;
+ }
+ else if (range == MASK(DAY))
+ {
+ interval->month = 0;
+ interval->time = (((int)(interval->time / 86400)) * 86400);
+ }
+ else if (range == MASK(HOUR))
+ {
+ double day;
+
+ interval->month = 0;
+ TMODULO(interval->time, day, 86400.0);
+ interval->time = (((int)(interval->time / 3600)) * 3600.0);
+ }
+ else if (range == MASK(MINUTE))
+ {
+ double hour;
+
+ interval->month = 0;
+ TMODULO(interval->time, hour, 3600.0);
+ interval->time = (((int)(interval->time / 60)) * 60);
+ }
+ else if (range == MASK(SECOND))
+ {
+ double hour;
+
+ interval->month = 0;
+ TMODULO(interval->time, hour, 60.0);
+// interval->time = (int)(interval->time);
+ }
+ /* DAY TO HOUR */
+ else if (range == (MASK(DAY) | MASK(HOUR)))
+ {
+ interval->month = 0;
+ interval->time = (((int)(interval->time / 3600)) * 3600);
+ }
+ /* DAY TO MINUTE */
+ else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE)))
+ {
+ interval->month = 0;
+ interval->time = (((int)(interval->time / 60)) * 60);
+ }
+ /* DAY TO SECOND */
+ else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
+ {
+ interval->month = 0;
+ }
+ /* HOUR TO MINUTE */
+ else if (range == (MASK(HOUR) | MASK(MINUTE)))
+ {
+ double day;
+
+ interval->month = 0;
+ TMODULO(interval->time, day, 86400.0);
+ interval->time = (((int)(interval->time / 60)) * 60);
+ }
+ /* HOUR TO SECOND */
+ else if (range == (MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
+ {
+ double day;
+
+ interval->month = 0;
+ TMODULO(interval->time, day, 86400.0);
+ }
+ /* MINUTE TO SECOND */
+ else if (range == (MASK(MINUTE) | MASK(SECOND)))
+ {
+ double hour;
+
+ interval->month = 0;
+ TMODULO(interval->time, hour, 3600.0);
+ }
+ else
+ {
+ elog(ERROR, "AdjustIntervalForTypmod(): internal coding error");
+ }
+
+ if (precision != 0xFFFF)
+ {
+ static double IntervalScale = 1;
+ static int IntervalTypmod = 0;
+
+ if (precision != IntervalTypmod)
+ {
+ IntervalTypmod = precision;
+ IntervalScale = pow(10.0, IntervalTypmod);
+ }
+
+ interval->time = (rint(interval->time * IntervalScale) / IntervalScale);
+ }
+ }
+
+ return;
+}
+
/* EncodeSpecialTimestamp()
* Convert reserved timestamp data type to string.
date0 = date2j(2000, 1, 1);
+ /* If HasCTZSet is true then we have a brute force time zone specified.
+ * Go ahead and rotate to the local time zone since we will later bypass
+ * any calls which adjust the tm fields.
+ */
+ if (HasCTZSet && (tzp != NULL))
+ dt -= CTimeZone;
+
time = dt;
TMODULO(time, date, 86400e0);
if (tzp != NULL)
{
- if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+ /* We have a brute force time zone per SQL99?
+ * Then use it without change
+ * since we have already rotated to the time zone.
+ */
+ if (HasCTZSet)
+ {
+ *tzp = CTimeZone;
+ tm->tm_gmtoff = CTimeZone;
+ tm->tm_isdst = 0;
+ tm->tm_zone = NULL;
+ if (tzn != NULL)
+ *tzn = NULL;
+ }
+
+ /* Does this fall within the capabilities of the localtime() interface?
+ * Then use this to rotate to the local time zone.
+ */
+ else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{
utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
*tzn = CTZName;
#endif
+ dt = dt2local(dt, *tzp);
}
else
{
if (tzn != NULL)
*tzn = NULL;
}
-
- dt = dt2local(dt, *tzp);
-
}
else
{
if (tm2timestamp(tm, fsec, NULL, ×tamp) != 0)
{
- elog(ERROR, "Unable to add timestamp and interval"
+ elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
"\n\ttimestamp_pl_span() internal error encoding timestamp");
PG_RETURN_NULL();
}
}
else
{
- elog(ERROR, "Unable to add timestamp and interval"
+ elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
"\n\ttimestamp_pl_span() internal error decoding timestamp");
PG_RETURN_NULL();
}
tz = DetermineLocalTimeZone(tm);
if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0)
- elog(ERROR, "Unable to add timestamp and interval"
+ elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
"\n\ttimestamptz_pl_span() internal error encoding timestamp");
}
else
{
- elog(ERROR, "Unable to add timestamp and interval"
+ elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
"\n\ttimestamptz_pl_span() internal error decoding timestamp");
}
}
}
if (tm2interval(tm, fsec, result) != 0)
- elog(ERROR, "Unable to encode interval"
+ elog(ERROR, "Unable to encode INTERVAL"
"\n\ttimestamp_age() internal coding error");
}
else
- elog(ERROR, "Unable to decode timestamp"
+ elog(ERROR, "Unable to decode TIMESTAMP"
"\n\ttimestamp_age() internal coding error");
PG_RETURN_INTERVAL_P(result);
}
if (tm2interval(tm, fsec, result) != 0)
- elog(ERROR, "Unable to decode timestamp");
+ elog(ERROR, "Unable to decode TIMESTAMP");
}
else
- elog(ERROR, "Unable to decode timestamp");
+ elog(ERROR, "Unable to decode TIMESTAMP");
PG_RETURN_INTERVAL_P(result);
}
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Bad timestamp external representation (too long)");
+ elog(ERROR, "TIMESTAMP bad external representation (too long)");
sp = VARDATA(str);
dp = dstr;
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Bad timestamp with time zone external representation (too long)");
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE bad external representation (too long)");
sp = VARDATA(str);
dp = dstr;
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Bad interval external representation (too long)");
+ elog(ERROR, "INTERVAL bad external representation (too long)");
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
- return DirectFunctionCall1(interval_in, CStringGetDatum(dstr));
+ return DirectFunctionCall3(interval_in,
+ CStringGetDatum(dstr),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1));
}
/* timestamp_trunc()
*tm = &tt;
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "TIMESTAMP units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
break;
default:
- elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
result = 0;
}
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
- elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits);
+ elog(ERROR, "Unable to truncate TIMESTAMP to '%s'", lowunits);
}
else
{
- elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+ elog(ERROR, "TIMESTAMP units '%s' not recognized", lowunits);
result = 0;
}
*tm = &tt;
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
case DTK_MILLISEC:
fsec = rint(fsec * 1000) / 1000;
break;
-
case DTK_MICROSEC:
fsec = rint(fsec * 1000000) / 1000000;
break;
default:
- elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
result = 0;
}
tz = DetermineLocalTimeZone(tm);
if (tm2timestamp(tm, fsec, &tz, &result) != 0)
- elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits);
+ elog(ERROR, "Unable to truncate TIMESTAMP WITH TIME ZONE to '%s'", lowunits);
}
else
{
- elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized", lowunits);
PG_RETURN_NULL();
}
result = (Interval *) palloc(sizeof(Interval));
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "INTERVAL units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
break;
default:
- elog(ERROR, "Interval units '%s' not supported", lowunits);
+ elog(ERROR, "INTERVAL units '%s' not supported", lowunits);
}
if (tm2interval(tm, fsec, result) != 0)
- elog(ERROR, "Unable to truncate interval to '%s'", lowunits);
+ elog(ERROR, "Unable to truncate INTERVAL to '%s'", lowunits);
}
else
{
- elog(NOTICE, "Unable to decode interval; internal coding error");
+ elog(NOTICE, "Unable to decode INTERVAL; internal coding error");
*result = *interval;
}
}
else
{
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "INTERVAL units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
*result = *interval;
*tm = &tt;
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "TIMESTAMP units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
*lp = '\0';
type = DecodeUnits(0, lowunits, &val);
- if (type == IGNORE)
+ if (type == UNKNOWN_FIELD)
type = DecodeSpecial(0, lowunits, &val);
if (TIMESTAMP_NOT_FINITE(timestamp))
PG_RETURN_FLOAT8(result);
}
- if ((type == UNITS) && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0))
+ if ((type == UNITS)
+ && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0))
{
switch (val)
{
case DTK_TZ_MINUTE:
case DTK_TZ_HOUR:
default:
- elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
result = 0;
}
}
case DTK_DOW:
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
- elog(ERROR, "Unable to encode timestamp");
+ elog(ERROR, "Unable to encode TIMESTAMP");
result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
break;
case DTK_DOY:
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
- elog(ERROR, "Unable to encode timestamp");
+ elog(ERROR, "Unable to encode TIMESTAMP");
result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
- date2j(tm->tm_year, 1, 1) + 1);
break;
default:
- elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
result = 0;
}
}
else
{
- elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+ elog(ERROR, "TIMESTAMP units '%s' not recognized", lowunits);
result = 0;
}
*tm = &tt;
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
*lp = '\0';
type = DecodeUnits(0, lowunits, &val);
- if (type == IGNORE)
+ if (type == UNKNOWN_FIELD)
type = DecodeSpecial(0, lowunits, &val);
if (TIMESTAMP_NOT_FINITE(timestamp))
break;
default:
- elog(ERROR, "Timestamp with time zone units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
result = 0;
}
case DTK_DOW:
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to encode timestamp with time zone");
+ elog(ERROR, "Unable to encode TIMESTAMP WITH TIME ZONE");
result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
break;
case DTK_DOY:
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to encode timestamp with time zone");
+ elog(ERROR, "Unable to encode TIMESTAMP WITH TIME ZONE");
result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
- date2j(tm->tm_year, 1, 1) + 1);
break;
default:
- elog(ERROR, "Timestamp with time zone units '%s' not supported", lowunits);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
result = 0;
}
}
else
{
- elog(ERROR, "Timestamp with time zone units '%s' not recognized", lowunits);
+ elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized", lowunits);
result = 0;
}
*tm = &tt;
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "INTERVAL units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
up = VARDATA(units);
*lp = '\0';
type = DecodeUnits(0, lowunits, &val);
- if (type == IGNORE)
+ if (type == UNKNOWN_FIELD)
type = DecodeSpecial(0, lowunits, &val);
if (type == UNITS)
break;
default:
- elog(ERROR, "Interval units '%s' not supported",
+ elog(ERROR, "INTERVAL units '%s' not supported",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
result = 0;
}
else
{
- elog(NOTICE, "Unable to decode interval"
+ elog(NOTICE, "Unable to decode INTERVAL"
"\n\tinterval_part() internal coding error");
result = 0;
}
}
else
{
- elog(ERROR, "Interval units '%s' not recognized",
+ elog(ERROR, "INTERVAL units '%s' not recognized",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(units))));
result = 0;
else
{
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
- elog(ERROR, "Unable to convert timestamp to timestamp with time zone (tm)");
+ elog(ERROR, "Unable to convert TIMESTAMP to TIMESTAMP WITH TIME ZONE (tm)");
tz = DetermineLocalTimeZone(tm);
if (tm2timestamp(tm, fsec, &tz, &result) != 0)
- elog(ERROR, "Unable to convert timestamp to timestamp with time zone");
+ elog(ERROR, "Unable to convert TIMESTAMP to TIMESTAMP WITH TIME ZONE");
}
PG_RETURN_TIMESTAMPTZ(result);
else
{
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to convert timestamp with time zone to timestamp (tm)");
+ elog(ERROR, "Unable to convert TIMESTAMP WITH TIME ZONE to TIMESTAMP (tm)");
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
- elog(ERROR, "Unable to convert timestamp with time zone to timestamp");
+ elog(ERROR, "Unable to convert TIMESTAMP WITH TIME ZONE to TIMESTAMP");
}
PG_RETURN_TIMESTAMP(result);
dt = dt2local(timestamp, tz);
if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
- elog(ERROR, "Unable to decode timestamp"
- "\n\ttimestamp_zone() internal coding error");
+ elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
+ "\n\ttimestamptz_zone() internal coding error");
up = upzone;
lp = lowzone;
dt = dt2local(timestamp, tz);
if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
- elog(ERROR, "Unable to decode timestamp"
- "\n\ttimestamp_izone() internal coding error");
+ elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
+ "\n\ttimestamptz_izone() internal coding error");
EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
len = (strlen(buf) + VARHDRSZ);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: xact.h,v 1.37 2001/09/28 08:09:12 thomas Exp $
+ * $Id: xact.h,v 1.38 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
CommandId commandId;
CommandId scanCommandId;
AbsoluteTime startTime;
- int startTimeMsec;
+ int startTimeUsec;
int state;
int blockState;
} TransactionStateData;
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.98 2001/10/03 17:22:05 tgl Exp $
+ * $Id: catversion.h,v 1.99 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200110031
+#define CATALOG_VERSION_NO 200110181
#endif
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_proc.h,v 1.216 2001/10/12 02:08:34 ishii Exp $
+ * $Id: pg_proc.h,v 1.217 2001/10/18 17:30:15 thomas Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
DESCR("extract field from timestamp with time zone");
DATA(insert OID = 1172 ( date_part PGUID 12 f t t t 2 f 701 "25 1186" 100 0 0 100 interval_part - ));
DESCR("extract field from interval");
-
DATA(insert OID = 1173 ( timestamptz PGUID 12 f t f t 1 f 1184 "702" 100 0 0 100 abstime_timestamptz - ));
DESCR("convert abstime to timestamp with time zone");
DATA(insert OID = 1174 ( timestamptz PGUID 12 f t f t 1 f 1184 "1082" 100 0 0 100 date_timestamptz - ));
DESCR("SQL92 interval comparison");
DATA(insert OID = 1272 ( datetime_pl PGUID 12 f t t t 2 f 1114 "1082 1083" 100 0 0 100 datetime_timestamp - ));
DESCR("convert date and time to timestamp");
-
+DATA(insert OID = 1273 ( date_part PGUID 12 f t t t 2 f 701 "25 1266" 100 0 0 100 timetz_part - ));
+DESCR("extract field from time with time zone");
DATA(insert OID = 1274 ( int84pl PGUID 12 f t t t 2 f 20 "20 23" 100 0 0 100 int84pl - ));
DESCR("add");
DATA(insert OID = 1275 ( int84mi PGUID 12 f t t t 2 f 20 "20 23" 100 0 0 100 int84mi - ));
DATA(insert OID = 1382 ( date_part PGUID 14 f t f t 2 f 701 "25 702" 100 0 0 100 "select date_part($1, timestamptz($2))" - ));
DESCR("extract field from abstime");
-DATA(insert OID = 1383 ( date_part PGUID 14 f t f t 2 f 701 "25 703" 100 0 0 100 "select date_part($1, interval($2))" - ));
+DATA(insert OID = 1383 ( date_part PGUID 14 f t f t 2 f 701 "25 703" 100 0 0 100 "select date_part($1, cast($2 as interval))" - ));
DESCR("extract field from reltime");
DATA(insert OID = 1384 ( date_part PGUID 14 f t t t 2 f 701 "25 1082" 100 0 0 100 "select date_part($1, cast($2 as timestamp without time zone))" - ));
DESCR("extract field from date");
-DATA(insert OID = 1385 ( date_part PGUID 14 f t t t 2 f 701 "25 1083" 100 0 0 100 "select date_part($1, interval($2))" - ));
+DATA(insert OID = 1385 ( date_part PGUID 14 f t t t 2 f 701 "25 1083" 100 0 0 100 "select date_part($1, cast($2 as time with time zone))" - ));
DESCR("extract field from time");
DATA(insert OID = 1386 ( age PGUID 14 f t f t 1 f 1186 "1184" 100 0 0 100 "select age(cast(current_date as timestamp with time zone), $1)" - ));
DESCR("date difference from today preserving months and years");
* Headers for handling of 'SET var TO', 'SHOW var' and 'RESET var'
* statements
*
- * $Id: variable.h,v 1.13 2000/10/26 17:31:33 tgl Exp $
+ * $Id: variable.h,v 1.14 2001/10/18 17:30:16 thomas Exp $
*
*/
#ifndef VARIABLE_H
#define VARIABLE_H
-extern void SetPGVariable(const char *name, const char *value);
+extern void SetPGVariable(const char *name, List *args);
extern void GetPGVariable(const char *name);
extern void ResetPGVariable(const char *name);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.146 2001/10/12 00:07:15 tgl Exp $
+ * $Id: parsenodes.h,v 1.147 2001/10/18 17:30:16 thomas Exp $
*
*-------------------------------------------------------------------------
*/
{
NodeTag type;
char *name;
- char *value;
+ List *args;
} VariableSetStmt;
/* ----------------------
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: date.h,v 1.13 2001/10/03 05:29:25 thomas Exp $
+ * $Id: date.h,v 1.14 2001/10/18 17:30:16 thomas Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum datetimetz_timestamptz(PG_FUNCTION_ARGS);
extern Datum text_timetz(PG_FUNCTION_ARGS);
extern Datum timetz_text(PG_FUNCTION_ARGS);
+extern Datum timetz_part(PG_FUNCTION_ARGS);
extern Datum timetz_zone(PG_FUNCTION_ARGS);
extern Datum timetz_izone(PG_FUNCTION_ARGS);
extern Datum timetz_pl_interval(PG_FUNCTION_ARGS);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nabstime.h,v 1.31 2001/09/28 08:09:14 thomas Exp $
+ * $Id: nabstime.h,v 1.32 2001/10/18 17:30:16 thomas Exp $
*
*-------------------------------------------------------------------------
*/
/* non-fmgr-callable support routines */
extern AbsoluteTime GetCurrentAbsoluteTime(void);
extern AbsoluteTime GetCurrentAbsoluteTimeUsec(int *usec);
-extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn);
+extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char **tzn);
#endif /* NABSTIME_H */
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: timestamp.h,v 1.20 2001/10/03 15:42:12 tgl Exp $
+ * $Id: timestamp.h,v 1.21 2001/10/18 17:30:16 thomas Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum interval_in(PG_FUNCTION_ARGS);
extern Datum interval_out(PG_FUNCTION_ARGS);
+extern Datum interval_scale(PG_FUNCTION_ARGS);
extern Datum interval_eq(PG_FUNCTION_ARGS);
extern Datum interval_ne(PG_FUNCTION_ARGS);
extern Datum interval_lt(PG_FUNCTION_ARGS);
mapFunc = mapFunction(key);
/*
- * We could have mapFunction() return key if not in table... -
- * thomas 2000-04-03
+ * We could have mapFunction() return key if not in table...
+ * - thomas 2000-04-03
*/
if (mapFunc == NULL)
{
| Sat Sep 22 18:19:20 2001 PDT
(16 rows)
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 + t.f1 AS plus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
- ORDER BY plus, "timestamp", interval;
+ ORDER BY plus, "timestamp", "interval";
160 | timestamp | interval | plus
-----+------------------------------+-------------------------------+------------------------------
| Thu Jan 01 00:00:00 1970 PST | @ 14 secs ago | Wed Dec 31 23:59:46 1969 PST
| Sat Sep 22 18:19:20 2001 PDT | @ 34 years | Sat Sep 22 18:19:20 2035 PDT
(160 rows)
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 - t.f1 AS minus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
WHERE isfinite(d.f1)
- ORDER BY minus, "timestamp", interval;
+ ORDER BY minus, "timestamp", "interval";
160 | timestamp | interval | minus
-----+------------------------------+-------------------------------+------------------------------
| Thu Jan 01 00:00:00 1970 PST | @ 34 years | Wed Jan 01 00:00:00 1936 PST
| @ 5 mons 12 hours | @ 5 mons 12 hours
(10 rows)
-SELECT '' AS six, f1 as reltime, interval(f1) AS interval
+SELECT '' AS six, f1 as reltime, CAST(f1 AS interval) AS interval
FROM RELTIME_TBL;
six | reltime | interval
-----+---------------+---------------
INSERT INTO TIMESTAMP_TBL VALUES ('epoch');
-- Obsolete special values
INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
-ERROR: Timestamp 'invalid' no longer supported
+ERROR: TIMESTAMP 'invalid' no longer supported
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: Bad timestamp external representation 'Feb 16 17:32:01 -0097'
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
-ERROR: Timestamp out of range 'Feb 16 17:32:01 5097 BC'
+ERROR: TIMESTAMP out of range 'Feb 16 17:32:01 5097 BC'
SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
64 | d1
----+-----------------------------
INSERT INTO TIMESTAMPTZ_TBL VALUES ('epoch');
-- Obsolete special values
INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
-ERROR: Timestamp with time zone 'invalid' no longer supported
+ERROR: TIMESTAMP WITH TIME ZONE 'invalid' no longer supported
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: Bad timestamp external representation 'Feb 16 17:32:01 -0097'
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC');
-ERROR: Timestamp out of range 'Feb 16 17:32:01 5097 BC'
+ERROR: TIMESTAMP WITH TIME ZONE out of range 'Feb 16 17:32:01 5097 BC'
SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL;
64 | d1
----+---------------------------------
FROM TEMP_TIMESTAMP
ORDER BY "timestamp";
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 + t.f1 AS plus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
- ORDER BY plus, "timestamp", interval;
+ ORDER BY plus, "timestamp", "interval";
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 - t.f1 AS minus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
WHERE isfinite(d.f1)
- ORDER BY minus, "timestamp", interval;
+ ORDER BY minus, "timestamp", "interval";
SELECT '' AS "16", d.f1 AS "timestamp", timestamp '1980-01-06 00:00 GMT' AS gpstime_zero,
d.f1 - timestamp '1980-01-06 00:00 GMT' AS difference
SELECT '' AS ten, f1 AS interval, reltime(f1) AS reltime
FROM INTERVAL_TBL;
-SELECT '' AS six, f1 as reltime, interval(f1) AS interval
+SELECT '' AS six, f1 as reltime, CAST(f1 AS interval) AS interval
FROM RELTIME_TBL;
DROP TABLE TEMP_TIMESTAMP;