00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include <ctype.h>
00019 #include <limits.h>
00020 #include <float.h>
00021 #include <time.h>
00022
00023 #include "access/hash.h"
00024 #include "libpq/pqformat.h"
00025 #include "miscadmin.h"
00026 #include "parser/scansup.h"
00027 #include "utils/array.h"
00028 #include "utils/builtins.h"
00029 #include "utils/date.h"
00030 #include "utils/datetime.h"
00031 #include "utils/nabstime.h"
00032 #include "utils/sortsupport.h"
00033
00034
00035
00036
00037
00038 #ifdef __FAST_MATH__
00039 #error -ffast-math is known to break this code
00040 #endif
00041
00042
00043 static void EncodeSpecialDate(DateADT dt, char *str);
00044 static int time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec);
00045 static int timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp);
00046 static int tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result);
00047 static int tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
00048 static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
00049
00050
00051
00052 static int32
00053 anytime_typmodin(bool istz, ArrayType *ta)
00054 {
00055 int32 typmod;
00056 int32 *tl;
00057 int n;
00058
00059 tl = ArrayGetIntegerTypmods(ta, &n);
00060
00061
00062
00063
00064
00065 if (n != 1)
00066 ereport(ERROR,
00067 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00068 errmsg("invalid type modifier")));
00069
00070 if (*tl < 0)
00071 ereport(ERROR,
00072 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00073 errmsg("TIME(%d)%s precision must not be negative",
00074 *tl, (istz ? " WITH TIME ZONE" : ""))));
00075 if (*tl > MAX_TIME_PRECISION)
00076 {
00077 ereport(WARNING,
00078 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00079 errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
00080 *tl, (istz ? " WITH TIME ZONE" : ""),
00081 MAX_TIME_PRECISION)));
00082 typmod = MAX_TIME_PRECISION;
00083 }
00084 else
00085 typmod = *tl;
00086
00087 return typmod;
00088 }
00089
00090
00091 static char *
00092 anytime_typmodout(bool istz, int32 typmod)
00093 {
00094 char *res = (char *) palloc(64);
00095 const char *tz = istz ? " with time zone" : " without time zone";
00096
00097 if (typmod >= 0)
00098 snprintf(res, 64, "(%d)%s", (int) typmod, tz);
00099 else
00100 snprintf(res, 64, "%s", tz);
00101 return res;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 Datum
00114 date_in(PG_FUNCTION_ARGS)
00115 {
00116 char *str = PG_GETARG_CSTRING(0);
00117 DateADT date;
00118 fsec_t fsec;
00119 struct pg_tm tt,
00120 *tm = &tt;
00121 int tzp;
00122 int dtype;
00123 int nf;
00124 int dterr;
00125 char *field[MAXDATEFIELDS];
00126 int ftype[MAXDATEFIELDS];
00127 char workbuf[MAXDATELEN + 1];
00128
00129 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
00130 field, ftype, MAXDATEFIELDS, &nf);
00131 if (dterr == 0)
00132 dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp);
00133 if (dterr != 0)
00134 DateTimeParseError(dterr, str, "date");
00135
00136 switch (dtype)
00137 {
00138 case DTK_DATE:
00139 break;
00140
00141 case DTK_CURRENT:
00142 ereport(ERROR,
00143 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00144 errmsg("date/time value \"current\" is no longer supported")));
00145
00146 GetCurrentDateTime(tm);
00147 break;
00148
00149 case DTK_EPOCH:
00150 GetEpochTime(tm);
00151 break;
00152
00153 case DTK_LATE:
00154 DATE_NOEND(date);
00155 PG_RETURN_DATEADT(date);
00156
00157 case DTK_EARLY:
00158 DATE_NOBEGIN(date);
00159 PG_RETURN_DATEADT(date);
00160
00161 default:
00162 DateTimeParseError(DTERR_BAD_FORMAT, str, "date");
00163 break;
00164 }
00165
00166 if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
00167 ereport(ERROR,
00168 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00169 errmsg("date out of range: \"%s\"", str)));
00170
00171 date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
00172
00173 PG_RETURN_DATEADT(date);
00174 }
00175
00176
00177
00178
00179 Datum
00180 date_out(PG_FUNCTION_ARGS)
00181 {
00182 DateADT date = PG_GETARG_DATEADT(0);
00183 char *result;
00184 struct pg_tm tt,
00185 *tm = &tt;
00186 char buf[MAXDATELEN + 1];
00187
00188 if (DATE_NOT_FINITE(date))
00189 EncodeSpecialDate(date, buf);
00190 else
00191 {
00192 j2date(date + POSTGRES_EPOCH_JDATE,
00193 &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
00194 EncodeDateOnly(tm, DateStyle, buf);
00195 }
00196
00197 result = pstrdup(buf);
00198 PG_RETURN_CSTRING(result);
00199 }
00200
00201
00202
00203
00204 Datum
00205 date_recv(PG_FUNCTION_ARGS)
00206 {
00207 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00208 DateADT result;
00209
00210 result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
00211
00212
00213 if (DATE_NOT_FINITE(result))
00214 ;
00215 else if (result < -POSTGRES_EPOCH_JDATE ||
00216 result >= JULIAN_MAX - POSTGRES_EPOCH_JDATE)
00217 ereport(ERROR,
00218 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00219 errmsg("date out of range")));
00220
00221 PG_RETURN_DATEADT(result);
00222 }
00223
00224
00225
00226
00227 Datum
00228 date_send(PG_FUNCTION_ARGS)
00229 {
00230 DateADT date = PG_GETARG_DATEADT(0);
00231 StringInfoData buf;
00232
00233 pq_begintypsend(&buf);
00234 pq_sendint(&buf, date, sizeof(date));
00235 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00236 }
00237
00238
00239
00240
00241 static void
00242 EncodeSpecialDate(DateADT dt, char *str)
00243 {
00244 if (DATE_IS_NOBEGIN(dt))
00245 strcpy(str, EARLY);
00246 else if (DATE_IS_NOEND(dt))
00247 strcpy(str, LATE);
00248 else
00249 elog(ERROR, "invalid argument for EncodeSpecialDate");
00250 }
00251
00252
00253
00254
00255
00256
00257 Datum
00258 date_eq(PG_FUNCTION_ARGS)
00259 {
00260 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00261 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00262
00263 PG_RETURN_BOOL(dateVal1 == dateVal2);
00264 }
00265
00266 Datum
00267 date_ne(PG_FUNCTION_ARGS)
00268 {
00269 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00270 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00271
00272 PG_RETURN_BOOL(dateVal1 != dateVal2);
00273 }
00274
00275 Datum
00276 date_lt(PG_FUNCTION_ARGS)
00277 {
00278 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00279 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00280
00281 PG_RETURN_BOOL(dateVal1 < dateVal2);
00282 }
00283
00284 Datum
00285 date_le(PG_FUNCTION_ARGS)
00286 {
00287 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00288 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00289
00290 PG_RETURN_BOOL(dateVal1 <= dateVal2);
00291 }
00292
00293 Datum
00294 date_gt(PG_FUNCTION_ARGS)
00295 {
00296 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00297 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00298
00299 PG_RETURN_BOOL(dateVal1 > dateVal2);
00300 }
00301
00302 Datum
00303 date_ge(PG_FUNCTION_ARGS)
00304 {
00305 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00306 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00307
00308 PG_RETURN_BOOL(dateVal1 >= dateVal2);
00309 }
00310
00311 Datum
00312 date_cmp(PG_FUNCTION_ARGS)
00313 {
00314 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00315 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00316
00317 if (dateVal1 < dateVal2)
00318 PG_RETURN_INT32(-1);
00319 else if (dateVal1 > dateVal2)
00320 PG_RETURN_INT32(1);
00321 PG_RETURN_INT32(0);
00322 }
00323
00324 static int
00325 date_fastcmp(Datum x, Datum y, SortSupport ssup)
00326 {
00327 DateADT a = DatumGetDateADT(x);
00328 DateADT b = DatumGetDateADT(y);
00329
00330 if (a < b)
00331 return -1;
00332 else if (a > b)
00333 return 1;
00334 return 0;
00335 }
00336
00337 Datum
00338 date_sortsupport(PG_FUNCTION_ARGS)
00339 {
00340 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00341
00342 ssup->comparator = date_fastcmp;
00343 PG_RETURN_VOID();
00344 }
00345
00346 Datum
00347 date_finite(PG_FUNCTION_ARGS)
00348 {
00349 DateADT date = PG_GETARG_DATEADT(0);
00350
00351 PG_RETURN_BOOL(!DATE_NOT_FINITE(date));
00352 }
00353
00354 Datum
00355 date_larger(PG_FUNCTION_ARGS)
00356 {
00357 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00358 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00359
00360 PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);
00361 }
00362
00363 Datum
00364 date_smaller(PG_FUNCTION_ARGS)
00365 {
00366 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00367 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00368
00369 PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);
00370 }
00371
00372
00373
00374 Datum
00375 date_mi(PG_FUNCTION_ARGS)
00376 {
00377 DateADT dateVal1 = PG_GETARG_DATEADT(0);
00378 DateADT dateVal2 = PG_GETARG_DATEADT(1);
00379
00380 if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
00381 ereport(ERROR,
00382 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00383 errmsg("cannot subtract infinite dates")));
00384
00385 PG_RETURN_INT32((int32) (dateVal1 - dateVal2));
00386 }
00387
00388
00389
00390
00391 Datum
00392 date_pli(PG_FUNCTION_ARGS)
00393 {
00394 DateADT dateVal = PG_GETARG_DATEADT(0);
00395 int32 days = PG_GETARG_INT32(1);
00396
00397 if (DATE_NOT_FINITE(dateVal))
00398 days = 0;
00399
00400 PG_RETURN_DATEADT(dateVal + days);
00401 }
00402
00403
00404
00405 Datum
00406 date_mii(PG_FUNCTION_ARGS)
00407 {
00408 DateADT dateVal = PG_GETARG_DATEADT(0);
00409 int32 days = PG_GETARG_INT32(1);
00410
00411 if (DATE_NOT_FINITE(dateVal))
00412 days = 0;
00413
00414 PG_RETURN_DATEADT(dateVal - days);
00415 }
00416
00417
00418
00419
00420
00421
00422 static Timestamp
00423 date2timestamp(DateADT dateVal)
00424 {
00425 Timestamp result;
00426
00427 if (DATE_IS_NOBEGIN(dateVal))
00428 TIMESTAMP_NOBEGIN(result);
00429 else if (DATE_IS_NOEND(dateVal))
00430 TIMESTAMP_NOEND(result);
00431 else
00432 {
00433 #ifdef HAVE_INT64_TIMESTAMP
00434
00435 result = dateVal * USECS_PER_DAY;
00436
00437 if (result / USECS_PER_DAY != dateVal)
00438 ereport(ERROR,
00439 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00440 errmsg("date out of range for timestamp")));
00441 #else
00442
00443 result = dateVal * (double) SECS_PER_DAY;
00444 #endif
00445 }
00446
00447 return result;
00448 }
00449
00450 static TimestampTz
00451 date2timestamptz(DateADT dateVal)
00452 {
00453 TimestampTz result;
00454 struct pg_tm tt,
00455 *tm = &tt;
00456 int tz;
00457
00458 if (DATE_IS_NOBEGIN(dateVal))
00459 TIMESTAMP_NOBEGIN(result);
00460 else if (DATE_IS_NOEND(dateVal))
00461 TIMESTAMP_NOEND(result);
00462 else
00463 {
00464 j2date(dateVal + POSTGRES_EPOCH_JDATE,
00465 &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
00466 tm->tm_hour = 0;
00467 tm->tm_min = 0;
00468 tm->tm_sec = 0;
00469 tz = DetermineTimeZoneOffset(tm, session_timezone);
00470
00471 #ifdef HAVE_INT64_TIMESTAMP
00472 result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
00473
00474 if ((result - tz * USECS_PER_SEC) / USECS_PER_DAY != dateVal)
00475 ereport(ERROR,
00476 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00477 errmsg("date out of range for timestamp")));
00478 #else
00479 result = dateVal * (double) SECS_PER_DAY + tz;
00480 #endif
00481 }
00482
00483 return result;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 double
00497 date2timestamp_no_overflow(DateADT dateVal)
00498 {
00499 double result;
00500
00501 if (DATE_IS_NOBEGIN(dateVal))
00502 result = -DBL_MAX;
00503 else if (DATE_IS_NOEND(dateVal))
00504 result = DBL_MAX;
00505 else
00506 {
00507 #ifdef HAVE_INT64_TIMESTAMP
00508
00509 result = dateVal * (double) USECS_PER_DAY;
00510 #else
00511
00512 result = dateVal * (double) SECS_PER_DAY;
00513 #endif
00514 }
00515
00516 return result;
00517 }
00518
00519
00520
00521
00522
00523
00524 Datum
00525 date_eq_timestamp(PG_FUNCTION_ARGS)
00526 {
00527 DateADT dateVal = PG_GETARG_DATEADT(0);
00528 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00529 Timestamp dt1;
00530
00531 dt1 = date2timestamp(dateVal);
00532
00533 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
00534 }
00535
00536 Datum
00537 date_ne_timestamp(PG_FUNCTION_ARGS)
00538 {
00539 DateADT dateVal = PG_GETARG_DATEADT(0);
00540 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00541 Timestamp dt1;
00542
00543 dt1 = date2timestamp(dateVal);
00544
00545 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
00546 }
00547
00548 Datum
00549 date_lt_timestamp(PG_FUNCTION_ARGS)
00550 {
00551 DateADT dateVal = PG_GETARG_DATEADT(0);
00552 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00553 Timestamp dt1;
00554
00555 dt1 = date2timestamp(dateVal);
00556
00557 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
00558 }
00559
00560 Datum
00561 date_gt_timestamp(PG_FUNCTION_ARGS)
00562 {
00563 DateADT dateVal = PG_GETARG_DATEADT(0);
00564 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00565 Timestamp dt1;
00566
00567 dt1 = date2timestamp(dateVal);
00568
00569 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
00570 }
00571
00572 Datum
00573 date_le_timestamp(PG_FUNCTION_ARGS)
00574 {
00575 DateADT dateVal = PG_GETARG_DATEADT(0);
00576 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00577 Timestamp dt1;
00578
00579 dt1 = date2timestamp(dateVal);
00580
00581 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
00582 }
00583
00584 Datum
00585 date_ge_timestamp(PG_FUNCTION_ARGS)
00586 {
00587 DateADT dateVal = PG_GETARG_DATEADT(0);
00588 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00589 Timestamp dt1;
00590
00591 dt1 = date2timestamp(dateVal);
00592
00593 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
00594 }
00595
00596 Datum
00597 date_cmp_timestamp(PG_FUNCTION_ARGS)
00598 {
00599 DateADT dateVal = PG_GETARG_DATEADT(0);
00600 Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
00601 Timestamp dt1;
00602
00603 dt1 = date2timestamp(dateVal);
00604
00605 PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
00606 }
00607
00608 Datum
00609 date_eq_timestamptz(PG_FUNCTION_ARGS)
00610 {
00611 DateADT dateVal = PG_GETARG_DATEADT(0);
00612 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00613 TimestampTz dt1;
00614
00615 dt1 = date2timestamptz(dateVal);
00616
00617 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);
00618 }
00619
00620 Datum
00621 date_ne_timestamptz(PG_FUNCTION_ARGS)
00622 {
00623 DateADT dateVal = PG_GETARG_DATEADT(0);
00624 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00625 TimestampTz dt1;
00626
00627 dt1 = date2timestamptz(dateVal);
00628
00629 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);
00630 }
00631
00632 Datum
00633 date_lt_timestamptz(PG_FUNCTION_ARGS)
00634 {
00635 DateADT dateVal = PG_GETARG_DATEADT(0);
00636 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00637 TimestampTz dt1;
00638
00639 dt1 = date2timestamptz(dateVal);
00640
00641 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);
00642 }
00643
00644 Datum
00645 date_gt_timestamptz(PG_FUNCTION_ARGS)
00646 {
00647 DateADT dateVal = PG_GETARG_DATEADT(0);
00648 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00649 TimestampTz dt1;
00650
00651 dt1 = date2timestamptz(dateVal);
00652
00653 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);
00654 }
00655
00656 Datum
00657 date_le_timestamptz(PG_FUNCTION_ARGS)
00658 {
00659 DateADT dateVal = PG_GETARG_DATEADT(0);
00660 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00661 TimestampTz dt1;
00662
00663 dt1 = date2timestamptz(dateVal);
00664
00665 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);
00666 }
00667
00668 Datum
00669 date_ge_timestamptz(PG_FUNCTION_ARGS)
00670 {
00671 DateADT dateVal = PG_GETARG_DATEADT(0);
00672 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00673 TimestampTz dt1;
00674
00675 dt1 = date2timestamptz(dateVal);
00676
00677 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);
00678 }
00679
00680 Datum
00681 date_cmp_timestamptz(PG_FUNCTION_ARGS)
00682 {
00683 DateADT dateVal = PG_GETARG_DATEADT(0);
00684 TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
00685 TimestampTz dt1;
00686
00687 dt1 = date2timestamptz(dateVal);
00688
00689 PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));
00690 }
00691
00692 Datum
00693 timestamp_eq_date(PG_FUNCTION_ARGS)
00694 {
00695 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00696 DateADT dateVal = PG_GETARG_DATEADT(1);
00697 Timestamp dt2;
00698
00699 dt2 = date2timestamp(dateVal);
00700
00701 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
00702 }
00703
00704 Datum
00705 timestamp_ne_date(PG_FUNCTION_ARGS)
00706 {
00707 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00708 DateADT dateVal = PG_GETARG_DATEADT(1);
00709 Timestamp dt2;
00710
00711 dt2 = date2timestamp(dateVal);
00712
00713 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
00714 }
00715
00716 Datum
00717 timestamp_lt_date(PG_FUNCTION_ARGS)
00718 {
00719 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00720 DateADT dateVal = PG_GETARG_DATEADT(1);
00721 Timestamp dt2;
00722
00723 dt2 = date2timestamp(dateVal);
00724
00725 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
00726 }
00727
00728 Datum
00729 timestamp_gt_date(PG_FUNCTION_ARGS)
00730 {
00731 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00732 DateADT dateVal = PG_GETARG_DATEADT(1);
00733 Timestamp dt2;
00734
00735 dt2 = date2timestamp(dateVal);
00736
00737 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
00738 }
00739
00740 Datum
00741 timestamp_le_date(PG_FUNCTION_ARGS)
00742 {
00743 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00744 DateADT dateVal = PG_GETARG_DATEADT(1);
00745 Timestamp dt2;
00746
00747 dt2 = date2timestamp(dateVal);
00748
00749 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
00750 }
00751
00752 Datum
00753 timestamp_ge_date(PG_FUNCTION_ARGS)
00754 {
00755 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00756 DateADT dateVal = PG_GETARG_DATEADT(1);
00757 Timestamp dt2;
00758
00759 dt2 = date2timestamp(dateVal);
00760
00761 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
00762 }
00763
00764 Datum
00765 timestamp_cmp_date(PG_FUNCTION_ARGS)
00766 {
00767 Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
00768 DateADT dateVal = PG_GETARG_DATEADT(1);
00769 Timestamp dt2;
00770
00771 dt2 = date2timestamp(dateVal);
00772
00773 PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
00774 }
00775
00776 Datum
00777 timestamptz_eq_date(PG_FUNCTION_ARGS)
00778 {
00779 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00780 DateADT dateVal = PG_GETARG_DATEADT(1);
00781 TimestampTz dt2;
00782
00783 dt2 = date2timestamptz(dateVal);
00784
00785 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);
00786 }
00787
00788 Datum
00789 timestamptz_ne_date(PG_FUNCTION_ARGS)
00790 {
00791 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00792 DateADT dateVal = PG_GETARG_DATEADT(1);
00793 TimestampTz dt2;
00794
00795 dt2 = date2timestamptz(dateVal);
00796
00797 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);
00798 }
00799
00800 Datum
00801 timestamptz_lt_date(PG_FUNCTION_ARGS)
00802 {
00803 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00804 DateADT dateVal = PG_GETARG_DATEADT(1);
00805 TimestampTz dt2;
00806
00807 dt2 = date2timestamptz(dateVal);
00808
00809 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);
00810 }
00811
00812 Datum
00813 timestamptz_gt_date(PG_FUNCTION_ARGS)
00814 {
00815 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00816 DateADT dateVal = PG_GETARG_DATEADT(1);
00817 TimestampTz dt2;
00818
00819 dt2 = date2timestamptz(dateVal);
00820
00821 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);
00822 }
00823
00824 Datum
00825 timestamptz_le_date(PG_FUNCTION_ARGS)
00826 {
00827 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00828 DateADT dateVal = PG_GETARG_DATEADT(1);
00829 TimestampTz dt2;
00830
00831 dt2 = date2timestamptz(dateVal);
00832
00833 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);
00834 }
00835
00836 Datum
00837 timestamptz_ge_date(PG_FUNCTION_ARGS)
00838 {
00839 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00840 DateADT dateVal = PG_GETARG_DATEADT(1);
00841 TimestampTz dt2;
00842
00843 dt2 = date2timestamptz(dateVal);
00844
00845 PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);
00846 }
00847
00848 Datum
00849 timestamptz_cmp_date(PG_FUNCTION_ARGS)
00850 {
00851 TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
00852 DateADT dateVal = PG_GETARG_DATEADT(1);
00853 TimestampTz dt2;
00854
00855 dt2 = date2timestamptz(dateVal);
00856
00857 PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867 Datum
00868 date_pl_interval(PG_FUNCTION_ARGS)
00869 {
00870 DateADT dateVal = PG_GETARG_DATEADT(0);
00871 Interval *span = PG_GETARG_INTERVAL_P(1);
00872 Timestamp dateStamp;
00873
00874 dateStamp = date2timestamp(dateVal);
00875
00876 return DirectFunctionCall2(timestamp_pl_interval,
00877 TimestampGetDatum(dateStamp),
00878 PointerGetDatum(span));
00879 }
00880
00881
00882
00883
00884
00885
00886
00887 Datum
00888 date_mi_interval(PG_FUNCTION_ARGS)
00889 {
00890 DateADT dateVal = PG_GETARG_DATEADT(0);
00891 Interval *span = PG_GETARG_INTERVAL_P(1);
00892 Timestamp dateStamp;
00893
00894 dateStamp = date2timestamp(dateVal);
00895
00896 return DirectFunctionCall2(timestamp_mi_interval,
00897 TimestampGetDatum(dateStamp),
00898 PointerGetDatum(span));
00899 }
00900
00901
00902
00903
00904 Datum
00905 date_timestamp(PG_FUNCTION_ARGS)
00906 {
00907 DateADT dateVal = PG_GETARG_DATEADT(0);
00908 Timestamp result;
00909
00910 result = date2timestamp(dateVal);
00911
00912 PG_RETURN_TIMESTAMP(result);
00913 }
00914
00915
00916
00917
00918 Datum
00919 timestamp_date(PG_FUNCTION_ARGS)
00920 {
00921 Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
00922 DateADT result;
00923 struct pg_tm tt,
00924 *tm = &tt;
00925 fsec_t fsec;
00926
00927 if (TIMESTAMP_IS_NOBEGIN(timestamp))
00928 DATE_NOBEGIN(result);
00929 else if (TIMESTAMP_IS_NOEND(timestamp))
00930 DATE_NOEND(result);
00931 else
00932 {
00933 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
00934 ereport(ERROR,
00935 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00936 errmsg("timestamp out of range")));
00937
00938 result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
00939 }
00940
00941 PG_RETURN_DATEADT(result);
00942 }
00943
00944
00945
00946
00947
00948 Datum
00949 date_timestamptz(PG_FUNCTION_ARGS)
00950 {
00951 DateADT dateVal = PG_GETARG_DATEADT(0);
00952 TimestampTz result;
00953
00954 result = date2timestamptz(dateVal);
00955
00956 PG_RETURN_TIMESTAMP(result);
00957 }
00958
00959
00960
00961
00962
00963 Datum
00964 timestamptz_date(PG_FUNCTION_ARGS)
00965 {
00966 TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
00967 DateADT result;
00968 struct pg_tm tt,
00969 *tm = &tt;
00970 fsec_t fsec;
00971 int tz;
00972
00973 if (TIMESTAMP_IS_NOBEGIN(timestamp))
00974 DATE_NOBEGIN(result);
00975 else if (TIMESTAMP_IS_NOEND(timestamp))
00976 DATE_NOEND(result);
00977 else
00978 {
00979 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
00980 ereport(ERROR,
00981 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
00982 errmsg("timestamp out of range")));
00983
00984 result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
00985 }
00986
00987 PG_RETURN_DATEADT(result);
00988 }
00989
00990
00991
00992
00993
00994 Datum
00995 abstime_date(PG_FUNCTION_ARGS)
00996 {
00997 AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);
00998 DateADT result;
00999 struct pg_tm tt,
01000 *tm = &tt;
01001 int tz;
01002
01003 switch (abstime)
01004 {
01005 case INVALID_ABSTIME:
01006 ereport(ERROR,
01007 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01008 errmsg("cannot convert reserved abstime value to date")));
01009 result = 0;
01010 break;
01011
01012 case NOSTART_ABSTIME:
01013 DATE_NOBEGIN(result);
01014 break;
01015
01016 case NOEND_ABSTIME:
01017 DATE_NOEND(result);
01018 break;
01019
01020 default:
01021 abstime2tm(abstime, &tz, tm, NULL);
01022 result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
01023 break;
01024 }
01025
01026 PG_RETURN_DATEADT(result);
01027 }
01028
01029
01030
01031
01032
01033
01034 Datum
01035 time_in(PG_FUNCTION_ARGS)
01036 {
01037 char *str = PG_GETARG_CSTRING(0);
01038
01039 #ifdef NOT_USED
01040 Oid typelem = PG_GETARG_OID(1);
01041 #endif
01042 int32 typmod = PG_GETARG_INT32(2);
01043 TimeADT result;
01044 fsec_t fsec;
01045 struct pg_tm tt,
01046 *tm = &tt;
01047 int tz;
01048 int nf;
01049 int dterr;
01050 char workbuf[MAXDATELEN + 1];
01051 char *field[MAXDATEFIELDS];
01052 int dtype;
01053 int ftype[MAXDATEFIELDS];
01054
01055 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
01056 field, ftype, MAXDATEFIELDS, &nf);
01057 if (dterr == 0)
01058 dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);
01059 if (dterr != 0)
01060 DateTimeParseError(dterr, str, "time");
01061
01062 tm2time(tm, fsec, &result);
01063 AdjustTimeForTypmod(&result, typmod);
01064
01065 PG_RETURN_TIMEADT(result);
01066 }
01067
01068
01069
01070
01071 static int
01072 tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result)
01073 {
01074 #ifdef HAVE_INT64_TIMESTAMP
01075 *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
01076 * USECS_PER_SEC) + fsec;
01077 #else
01078 *result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
01079 #endif
01080 return 0;
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090 static int
01091 time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec)
01092 {
01093 #ifdef HAVE_INT64_TIMESTAMP
01094 tm->tm_hour = time / USECS_PER_HOUR;
01095 time -= tm->tm_hour * USECS_PER_HOUR;
01096 tm->tm_min = time / USECS_PER_MINUTE;
01097 time -= tm->tm_min * USECS_PER_MINUTE;
01098 tm->tm_sec = time / USECS_PER_SEC;
01099 time -= tm->tm_sec * USECS_PER_SEC;
01100 *fsec = time;
01101 #else
01102 double trem;
01103
01104 recalc:
01105 trem = time;
01106 TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
01107 TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
01108 TMODULO(trem, tm->tm_sec, 1.0);
01109 trem = TIMEROUND(trem);
01110
01111 if (trem >= 1.0)
01112 {
01113 time = ceil(time);
01114 goto recalc;
01115 }
01116 *fsec = trem;
01117 #endif
01118
01119 return 0;
01120 }
01121
01122 Datum
01123 time_out(PG_FUNCTION_ARGS)
01124 {
01125 TimeADT time = PG_GETARG_TIMEADT(0);
01126 char *result;
01127 struct pg_tm tt,
01128 *tm = &tt;
01129 fsec_t fsec;
01130 char buf[MAXDATELEN + 1];
01131
01132 time2tm(time, tm, &fsec);
01133 EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
01134
01135 result = pstrdup(buf);
01136 PG_RETURN_CSTRING(result);
01137 }
01138
01139
01140
01141
01142
01143
01144
01145 Datum
01146 time_recv(PG_FUNCTION_ARGS)
01147 {
01148 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
01149
01150 #ifdef NOT_USED
01151 Oid typelem = PG_GETARG_OID(1);
01152 #endif
01153 int32 typmod = PG_GETARG_INT32(2);
01154 TimeADT result;
01155
01156 #ifdef HAVE_INT64_TIMESTAMP
01157 result = pq_getmsgint64(buf);
01158
01159 if (result < INT64CONST(0) || result > USECS_PER_DAY)
01160 ereport(ERROR,
01161 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01162 errmsg("time out of range")));
01163 #else
01164 result = pq_getmsgfloat8(buf);
01165
01166 if (result < 0 || result > (double) SECS_PER_DAY)
01167 ereport(ERROR,
01168 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01169 errmsg("time out of range")));
01170 #endif
01171
01172 AdjustTimeForTypmod(&result, typmod);
01173
01174 PG_RETURN_TIMEADT(result);
01175 }
01176
01177
01178
01179
01180 Datum
01181 time_send(PG_FUNCTION_ARGS)
01182 {
01183 TimeADT time = PG_GETARG_TIMEADT(0);
01184 StringInfoData buf;
01185
01186 pq_begintypsend(&buf);
01187 #ifdef HAVE_INT64_TIMESTAMP
01188 pq_sendint64(&buf, time);
01189 #else
01190 pq_sendfloat8(&buf, time);
01191 #endif
01192 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
01193 }
01194
01195 Datum
01196 timetypmodin(PG_FUNCTION_ARGS)
01197 {
01198 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
01199
01200 PG_RETURN_INT32(anytime_typmodin(false, ta));
01201 }
01202
01203 Datum
01204 timetypmodout(PG_FUNCTION_ARGS)
01205 {
01206 int32 typmod = PG_GETARG_INT32(0);
01207
01208 PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
01209 }
01210
01211
01212
01213
01214
01215
01216 Datum
01217 time_transform(PG_FUNCTION_ARGS)
01218 {
01219 PG_RETURN_POINTER(TemporalTransform(MAX_TIME_PRECISION,
01220 (Node *) PG_GETARG_POINTER(0)));
01221 }
01222
01223
01224
01225
01226
01227 Datum
01228 time_scale(PG_FUNCTION_ARGS)
01229 {
01230 TimeADT time = PG_GETARG_TIMEADT(0);
01231 int32 typmod = PG_GETARG_INT32(1);
01232 TimeADT result;
01233
01234 result = time;
01235 AdjustTimeForTypmod(&result, typmod);
01236
01237 PG_RETURN_TIMEADT(result);
01238 }
01239
01240
01241
01242
01243
01244
01245
01246
01247 static void
01248 AdjustTimeForTypmod(TimeADT *time, int32 typmod)
01249 {
01250 #ifdef HAVE_INT64_TIMESTAMP
01251 static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
01252 INT64CONST(1000000),
01253 INT64CONST(100000),
01254 INT64CONST(10000),
01255 INT64CONST(1000),
01256 INT64CONST(100),
01257 INT64CONST(10),
01258 INT64CONST(1)
01259 };
01260
01261 static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
01262 INT64CONST(500000),
01263 INT64CONST(50000),
01264 INT64CONST(5000),
01265 INT64CONST(500),
01266 INT64CONST(50),
01267 INT64CONST(5),
01268 INT64CONST(0)
01269 };
01270 #else
01271
01272 static const double TimeScales[MAX_TIME_PRECISION + 1] = {
01273 1.0,
01274 10.0,
01275 100.0,
01276 1000.0,
01277 10000.0,
01278 100000.0,
01279 1000000.0,
01280 10000000.0,
01281 100000000.0,
01282 1000000000.0,
01283 10000000000.0
01284 };
01285 #endif
01286
01287 if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
01288 {
01289
01290
01291
01292
01293
01294
01295
01296 #ifdef HAVE_INT64_TIMESTAMP
01297 if (*time >= INT64CONST(0))
01298 *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
01299 TimeScales[typmod];
01300 else
01301 *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
01302 TimeScales[typmod]);
01303 #else
01304 *time = rint((double) *time * TimeScales[typmod]) / TimeScales[typmod];
01305 #endif
01306 }
01307 }
01308
01309
01310 Datum
01311 time_eq(PG_FUNCTION_ARGS)
01312 {
01313 TimeADT time1 = PG_GETARG_TIMEADT(0);
01314 TimeADT time2 = PG_GETARG_TIMEADT(1);
01315
01316 PG_RETURN_BOOL(time1 == time2);
01317 }
01318
01319 Datum
01320 time_ne(PG_FUNCTION_ARGS)
01321 {
01322 TimeADT time1 = PG_GETARG_TIMEADT(0);
01323 TimeADT time2 = PG_GETARG_TIMEADT(1);
01324
01325 PG_RETURN_BOOL(time1 != time2);
01326 }
01327
01328 Datum
01329 time_lt(PG_FUNCTION_ARGS)
01330 {
01331 TimeADT time1 = PG_GETARG_TIMEADT(0);
01332 TimeADT time2 = PG_GETARG_TIMEADT(1);
01333
01334 PG_RETURN_BOOL(time1 < time2);
01335 }
01336
01337 Datum
01338 time_le(PG_FUNCTION_ARGS)
01339 {
01340 TimeADT time1 = PG_GETARG_TIMEADT(0);
01341 TimeADT time2 = PG_GETARG_TIMEADT(1);
01342
01343 PG_RETURN_BOOL(time1 <= time2);
01344 }
01345
01346 Datum
01347 time_gt(PG_FUNCTION_ARGS)
01348 {
01349 TimeADT time1 = PG_GETARG_TIMEADT(0);
01350 TimeADT time2 = PG_GETARG_TIMEADT(1);
01351
01352 PG_RETURN_BOOL(time1 > time2);
01353 }
01354
01355 Datum
01356 time_ge(PG_FUNCTION_ARGS)
01357 {
01358 TimeADT time1 = PG_GETARG_TIMEADT(0);
01359 TimeADT time2 = PG_GETARG_TIMEADT(1);
01360
01361 PG_RETURN_BOOL(time1 >= time2);
01362 }
01363
01364 Datum
01365 time_cmp(PG_FUNCTION_ARGS)
01366 {
01367 TimeADT time1 = PG_GETARG_TIMEADT(0);
01368 TimeADT time2 = PG_GETARG_TIMEADT(1);
01369
01370 if (time1 < time2)
01371 PG_RETURN_INT32(-1);
01372 if (time1 > time2)
01373 PG_RETURN_INT32(1);
01374 PG_RETURN_INT32(0);
01375 }
01376
01377 Datum
01378 time_hash(PG_FUNCTION_ARGS)
01379 {
01380
01381 #ifdef HAVE_INT64_TIMESTAMP
01382 return hashint8(fcinfo);
01383 #else
01384 return hashfloat8(fcinfo);
01385 #endif
01386 }
01387
01388 Datum
01389 time_larger(PG_FUNCTION_ARGS)
01390 {
01391 TimeADT time1 = PG_GETARG_TIMEADT(0);
01392 TimeADT time2 = PG_GETARG_TIMEADT(1);
01393
01394 PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
01395 }
01396
01397 Datum
01398 time_smaller(PG_FUNCTION_ARGS)
01399 {
01400 TimeADT time1 = PG_GETARG_TIMEADT(0);
01401 TimeADT time2 = PG_GETARG_TIMEADT(1);
01402
01403 PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
01404 }
01405
01406
01407
01408
01409
01410
01411
01412 Datum
01413 overlaps_time(PG_FUNCTION_ARGS)
01414 {
01415
01416
01417
01418
01419 Datum ts1 = PG_GETARG_DATUM(0);
01420 Datum te1 = PG_GETARG_DATUM(1);
01421 Datum ts2 = PG_GETARG_DATUM(2);
01422 Datum te2 = PG_GETARG_DATUM(3);
01423 bool ts1IsNull = PG_ARGISNULL(0);
01424 bool te1IsNull = PG_ARGISNULL(1);
01425 bool ts2IsNull = PG_ARGISNULL(2);
01426 bool te2IsNull = PG_ARGISNULL(3);
01427
01428 #define TIMEADT_GT(t1,t2) \
01429 (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
01430 #define TIMEADT_LT(t1,t2) \
01431 (DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
01432
01433
01434
01435
01436
01437
01438 if (ts1IsNull)
01439 {
01440 if (te1IsNull)
01441 PG_RETURN_NULL();
01442
01443 ts1 = te1;
01444 te1IsNull = true;
01445 }
01446 else if (!te1IsNull)
01447 {
01448 if (TIMEADT_GT(ts1, te1))
01449 {
01450 Datum tt = ts1;
01451
01452 ts1 = te1;
01453 te1 = tt;
01454 }
01455 }
01456
01457
01458 if (ts2IsNull)
01459 {
01460 if (te2IsNull)
01461 PG_RETURN_NULL();
01462
01463 ts2 = te2;
01464 te2IsNull = true;
01465 }
01466 else if (!te2IsNull)
01467 {
01468 if (TIMEADT_GT(ts2, te2))
01469 {
01470 Datum tt = ts2;
01471
01472 ts2 = te2;
01473 te2 = tt;
01474 }
01475 }
01476
01477
01478
01479
01480
01481 if (TIMEADT_GT(ts1, ts2))
01482 {
01483
01484
01485
01486
01487 if (te2IsNull)
01488 PG_RETURN_NULL();
01489 if (TIMEADT_LT(ts1, te2))
01490 PG_RETURN_BOOL(true);
01491 if (te1IsNull)
01492 PG_RETURN_NULL();
01493
01494
01495
01496
01497
01498 PG_RETURN_BOOL(false);
01499 }
01500 else if (TIMEADT_LT(ts1, ts2))
01501 {
01502
01503 if (te1IsNull)
01504 PG_RETURN_NULL();
01505 if (TIMEADT_LT(ts2, te1))
01506 PG_RETURN_BOOL(true);
01507 if (te2IsNull)
01508 PG_RETURN_NULL();
01509
01510
01511
01512
01513
01514 PG_RETURN_BOOL(false);
01515 }
01516 else
01517 {
01518
01519
01520
01521
01522 if (te1IsNull || te2IsNull)
01523 PG_RETURN_NULL();
01524 PG_RETURN_BOOL(true);
01525 }
01526
01527 #undef TIMEADT_GT
01528 #undef TIMEADT_LT
01529 }
01530
01531
01532
01533
01534 Datum
01535 timestamp_time(PG_FUNCTION_ARGS)
01536 {
01537 Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
01538 TimeADT result;
01539 struct pg_tm tt,
01540 *tm = &tt;
01541 fsec_t fsec;
01542
01543 if (TIMESTAMP_NOT_FINITE(timestamp))
01544 PG_RETURN_NULL();
01545
01546 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
01547 ereport(ERROR,
01548 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01549 errmsg("timestamp out of range")));
01550
01551 #ifdef HAVE_INT64_TIMESTAMP
01552
01553
01554
01555
01556
01557 result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
01558 USECS_PER_SEC) + fsec;
01559 #else
01560 result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
01561 #endif
01562
01563 PG_RETURN_TIMEADT(result);
01564 }
01565
01566
01567
01568
01569 Datum
01570 timestamptz_time(PG_FUNCTION_ARGS)
01571 {
01572 TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
01573 TimeADT result;
01574 struct pg_tm tt,
01575 *tm = &tt;
01576 int tz;
01577 fsec_t fsec;
01578
01579 if (TIMESTAMP_NOT_FINITE(timestamp))
01580 PG_RETURN_NULL();
01581
01582 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
01583 ereport(ERROR,
01584 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01585 errmsg("timestamp out of range")));
01586
01587 #ifdef HAVE_INT64_TIMESTAMP
01588
01589
01590
01591
01592
01593 result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
01594 USECS_PER_SEC) + fsec;
01595 #else
01596 result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
01597 #endif
01598
01599 PG_RETURN_TIMEADT(result);
01600 }
01601
01602
01603
01604
01605 Datum
01606 datetime_timestamp(PG_FUNCTION_ARGS)
01607 {
01608 DateADT date = PG_GETARG_DATEADT(0);
01609 TimeADT time = PG_GETARG_TIMEADT(1);
01610 Timestamp result;
01611
01612 result = date2timestamp(date);
01613 if (!TIMESTAMP_NOT_FINITE(result))
01614 result += time;
01615
01616 PG_RETURN_TIMESTAMP(result);
01617 }
01618
01619
01620
01621
01622 Datum
01623 time_interval(PG_FUNCTION_ARGS)
01624 {
01625 TimeADT time = PG_GETARG_TIMEADT(0);
01626 Interval *result;
01627
01628 result = (Interval *) palloc(sizeof(Interval));
01629
01630 result->time = time;
01631 result->day = 0;
01632 result->month = 0;
01633
01634 PG_RETURN_INTERVAL_P(result);
01635 }
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 Datum
01646 interval_time(PG_FUNCTION_ARGS)
01647 {
01648 Interval *span = PG_GETARG_INTERVAL_P(0);
01649 TimeADT result;
01650
01651 #ifdef HAVE_INT64_TIMESTAMP
01652 int64 days;
01653
01654 result = span->time;
01655 if (result >= USECS_PER_DAY)
01656 {
01657 days = result / USECS_PER_DAY;
01658 result -= days * USECS_PER_DAY;
01659 }
01660 else if (result < 0)
01661 {
01662 days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
01663 result += days * USECS_PER_DAY;
01664 }
01665 #else
01666 result = span->time;
01667 if (result >= (double) SECS_PER_DAY || result < 0)
01668 result -= floor(result / (double) SECS_PER_DAY) * (double) SECS_PER_DAY;
01669 #endif
01670
01671 PG_RETURN_TIMEADT(result);
01672 }
01673
01674
01675
01676
01677 Datum
01678 time_mi_time(PG_FUNCTION_ARGS)
01679 {
01680 TimeADT time1 = PG_GETARG_TIMEADT(0);
01681 TimeADT time2 = PG_GETARG_TIMEADT(1);
01682 Interval *result;
01683
01684 result = (Interval *) palloc(sizeof(Interval));
01685
01686 result->month = 0;
01687 result->day = 0;
01688 result->time = time1 - time2;
01689
01690 PG_RETURN_INTERVAL_P(result);
01691 }
01692
01693
01694
01695
01696 Datum
01697 time_pl_interval(PG_FUNCTION_ARGS)
01698 {
01699 TimeADT time = PG_GETARG_TIMEADT(0);
01700 Interval *span = PG_GETARG_INTERVAL_P(1);
01701 TimeADT result;
01702
01703 #ifdef HAVE_INT64_TIMESTAMP
01704 result = time + span->time;
01705 result -= result / USECS_PER_DAY * USECS_PER_DAY;
01706 if (result < INT64CONST(0))
01707 result += USECS_PER_DAY;
01708 #else
01709 TimeADT time1;
01710
01711 result = time + span->time;
01712 TMODULO(result, time1, (double) SECS_PER_DAY);
01713 if (result < 0)
01714 result += SECS_PER_DAY;
01715 #endif
01716
01717 PG_RETURN_TIMEADT(result);
01718 }
01719
01720
01721
01722
01723 Datum
01724 time_mi_interval(PG_FUNCTION_ARGS)
01725 {
01726 TimeADT time = PG_GETARG_TIMEADT(0);
01727 Interval *span = PG_GETARG_INTERVAL_P(1);
01728 TimeADT result;
01729
01730 #ifdef HAVE_INT64_TIMESTAMP
01731 result = time - span->time;
01732 result -= result / USECS_PER_DAY * USECS_PER_DAY;
01733 if (result < INT64CONST(0))
01734 result += USECS_PER_DAY;
01735 #else
01736 TimeADT time1;
01737
01738 result = time - span->time;
01739 TMODULO(result, time1, (double) SECS_PER_DAY);
01740 if (result < 0)
01741 result += SECS_PER_DAY;
01742 #endif
01743
01744 PG_RETURN_TIMEADT(result);
01745 }
01746
01747
01748
01749
01750
01751 Datum
01752 time_part(PG_FUNCTION_ARGS)
01753 {
01754 text *units = PG_GETARG_TEXT_PP(0);
01755 TimeADT time = PG_GETARG_TIMEADT(1);
01756 float8 result;
01757 int type,
01758 val;
01759 char *lowunits;
01760
01761 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
01762 VARSIZE_ANY_EXHDR(units),
01763 false);
01764
01765 type = DecodeUnits(0, lowunits, &val);
01766 if (type == UNKNOWN_FIELD)
01767 type = DecodeSpecial(0, lowunits, &val);
01768
01769 if (type == UNITS)
01770 {
01771 fsec_t fsec;
01772 struct pg_tm tt,
01773 *tm = &tt;
01774
01775 time2tm(time, tm, &fsec);
01776
01777 switch (val)
01778 {
01779 case DTK_MICROSEC:
01780 #ifdef HAVE_INT64_TIMESTAMP
01781 result = tm->tm_sec * 1000000.0 + fsec;
01782 #else
01783 result = (tm->tm_sec + fsec) * 1000000;
01784 #endif
01785 break;
01786
01787 case DTK_MILLISEC:
01788 #ifdef HAVE_INT64_TIMESTAMP
01789 result = tm->tm_sec * 1000.0 + fsec / 1000.0;
01790 #else
01791 result = (tm->tm_sec + fsec) * 1000;
01792 #endif
01793 break;
01794
01795 case DTK_SECOND:
01796 #ifdef HAVE_INT64_TIMESTAMP
01797 result = tm->tm_sec + fsec / 1000000.0;
01798 #else
01799 result = tm->tm_sec + fsec;
01800 #endif
01801 break;
01802
01803 case DTK_MINUTE:
01804 result = tm->tm_min;
01805 break;
01806
01807 case DTK_HOUR:
01808 result = tm->tm_hour;
01809 break;
01810
01811 case DTK_TZ:
01812 case DTK_TZ_MINUTE:
01813 case DTK_TZ_HOUR:
01814 case DTK_DAY:
01815 case DTK_MONTH:
01816 case DTK_QUARTER:
01817 case DTK_YEAR:
01818 case DTK_DECADE:
01819 case DTK_CENTURY:
01820 case DTK_MILLENNIUM:
01821 case DTK_ISOYEAR:
01822 default:
01823 ereport(ERROR,
01824 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01825 errmsg("\"time\" units \"%s\" not recognized",
01826 lowunits)));
01827 result = 0;
01828 }
01829 }
01830 else if (type == RESERV && val == DTK_EPOCH)
01831 {
01832 #ifdef HAVE_INT64_TIMESTAMP
01833 result = time / 1000000.0;
01834 #else
01835 result = time;
01836 #endif
01837 }
01838 else
01839 {
01840 ereport(ERROR,
01841 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01842 errmsg("\"time\" units \"%s\" not recognized",
01843 lowunits)));
01844 result = 0;
01845 }
01846
01847 PG_RETURN_FLOAT8(result);
01848 }
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858 static int
01859 tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
01860 {
01861 #ifdef HAVE_INT64_TIMESTAMP
01862 result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
01863 USECS_PER_SEC) + fsec;
01864 #else
01865 result->time = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
01866 #endif
01867 result->zone = tz;
01868
01869 return 0;
01870 }
01871
01872 Datum
01873 timetz_in(PG_FUNCTION_ARGS)
01874 {
01875 char *str = PG_GETARG_CSTRING(0);
01876
01877 #ifdef NOT_USED
01878 Oid typelem = PG_GETARG_OID(1);
01879 #endif
01880 int32 typmod = PG_GETARG_INT32(2);
01881 TimeTzADT *result;
01882 fsec_t fsec;
01883 struct pg_tm tt,
01884 *tm = &tt;
01885 int tz;
01886 int nf;
01887 int dterr;
01888 char workbuf[MAXDATELEN + 1];
01889 char *field[MAXDATEFIELDS];
01890 int dtype;
01891 int ftype[MAXDATEFIELDS];
01892
01893 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
01894 field, ftype, MAXDATEFIELDS, &nf);
01895 if (dterr == 0)
01896 dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);
01897 if (dterr != 0)
01898 DateTimeParseError(dterr, str, "time with time zone");
01899
01900 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
01901 tm2timetz(tm, fsec, tz, result);
01902 AdjustTimeForTypmod(&(result->time), typmod);
01903
01904 PG_RETURN_TIMETZADT_P(result);
01905 }
01906
01907 Datum
01908 timetz_out(PG_FUNCTION_ARGS)
01909 {
01910 TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
01911 char *result;
01912 struct pg_tm tt,
01913 *tm = &tt;
01914 fsec_t fsec;
01915 int tz;
01916 char buf[MAXDATELEN + 1];
01917
01918 timetz2tm(time, tm, &fsec, &tz);
01919 EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
01920
01921 result = pstrdup(buf);
01922 PG_RETURN_CSTRING(result);
01923 }
01924
01925
01926
01927
01928 Datum
01929 timetz_recv(PG_FUNCTION_ARGS)
01930 {
01931 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
01932
01933 #ifdef NOT_USED
01934 Oid typelem = PG_GETARG_OID(1);
01935 #endif
01936 int32 typmod = PG_GETARG_INT32(2);
01937 TimeTzADT *result;
01938
01939 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
01940
01941 #ifdef HAVE_INT64_TIMESTAMP
01942 result->time = pq_getmsgint64(buf);
01943
01944 if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
01945 ereport(ERROR,
01946 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01947 errmsg("time out of range")));
01948 #else
01949 result->time = pq_getmsgfloat8(buf);
01950
01951 if (result->time < 0 || result->time > (double) SECS_PER_DAY)
01952 ereport(ERROR,
01953 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
01954 errmsg("time out of range")));
01955 #endif
01956
01957 result->zone = pq_getmsgint(buf, sizeof(result->zone));
01958
01959
01960 if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
01961 ereport(ERROR,
01962 (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
01963 errmsg("time zone displacement out of range")));
01964
01965 AdjustTimeForTypmod(&(result->time), typmod);
01966
01967 PG_RETURN_TIMETZADT_P(result);
01968 }
01969
01970
01971
01972
01973 Datum
01974 timetz_send(PG_FUNCTION_ARGS)
01975 {
01976 TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
01977 StringInfoData buf;
01978
01979 pq_begintypsend(&buf);
01980 #ifdef HAVE_INT64_TIMESTAMP
01981 pq_sendint64(&buf, time->time);
01982 #else
01983 pq_sendfloat8(&buf, time->time);
01984 #endif
01985 pq_sendint(&buf, time->zone, sizeof(time->zone));
01986 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
01987 }
01988
01989 Datum
01990 timetztypmodin(PG_FUNCTION_ARGS)
01991 {
01992 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
01993
01994 PG_RETURN_INT32(anytime_typmodin(true, ta));
01995 }
01996
01997 Datum
01998 timetztypmodout(PG_FUNCTION_ARGS)
01999 {
02000 int32 typmod = PG_GETARG_INT32(0);
02001
02002 PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
02003 }
02004
02005
02006
02007
02008
02009 static int
02010 timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp)
02011 {
02012 TimeOffset trem = time->time;
02013
02014 #ifdef HAVE_INT64_TIMESTAMP
02015 tm->tm_hour = trem / USECS_PER_HOUR;
02016 trem -= tm->tm_hour * USECS_PER_HOUR;
02017 tm->tm_min = trem / USECS_PER_MINUTE;
02018 trem -= tm->tm_min * USECS_PER_MINUTE;
02019 tm->tm_sec = trem / USECS_PER_SEC;
02020 *fsec = trem - tm->tm_sec * USECS_PER_SEC;
02021 #else
02022 recalc:
02023 TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
02024 TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
02025 TMODULO(trem, tm->tm_sec, 1.0);
02026 trem = TIMEROUND(trem);
02027
02028 if (trem >= 1.0)
02029 {
02030 trem = ceil(time->time);
02031 goto recalc;
02032 }
02033 *fsec = trem;
02034 #endif
02035
02036 if (tzp != NULL)
02037 *tzp = time->zone;
02038
02039 return 0;
02040 }
02041
02042
02043
02044
02045
02046 Datum
02047 timetz_scale(PG_FUNCTION_ARGS)
02048 {
02049 TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
02050 int32 typmod = PG_GETARG_INT32(1);
02051 TimeTzADT *result;
02052
02053 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02054
02055 result->time = time->time;
02056 result->zone = time->zone;
02057
02058 AdjustTimeForTypmod(&(result->time), typmod);
02059
02060 PG_RETURN_TIMETZADT_P(result);
02061 }
02062
02063
02064 static int
02065 timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
02066 {
02067 TimeOffset t1,
02068 t2;
02069
02070
02071 #ifdef HAVE_INT64_TIMESTAMP
02072 t1 = time1->time + (time1->zone * USECS_PER_SEC);
02073 t2 = time2->time + (time2->zone * USECS_PER_SEC);
02074 #else
02075 t1 = time1->time + time1->zone;
02076 t2 = time2->time + time2->zone;
02077 #endif
02078
02079 if (t1 > t2)
02080 return 1;
02081 if (t1 < t2)
02082 return -1;
02083
02084
02085
02086
02087
02088 if (time1->zone > time2->zone)
02089 return 1;
02090 if (time1->zone < time2->zone)
02091 return -1;
02092
02093 return 0;
02094 }
02095
02096 Datum
02097 timetz_eq(PG_FUNCTION_ARGS)
02098 {
02099 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02100 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02101
02102 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
02103 }
02104
02105 Datum
02106 timetz_ne(PG_FUNCTION_ARGS)
02107 {
02108 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02109 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02110
02111 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
02112 }
02113
02114 Datum
02115 timetz_lt(PG_FUNCTION_ARGS)
02116 {
02117 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02118 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02119
02120 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
02121 }
02122
02123 Datum
02124 timetz_le(PG_FUNCTION_ARGS)
02125 {
02126 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02127 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02128
02129 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
02130 }
02131
02132 Datum
02133 timetz_gt(PG_FUNCTION_ARGS)
02134 {
02135 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02136 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02137
02138 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
02139 }
02140
02141 Datum
02142 timetz_ge(PG_FUNCTION_ARGS)
02143 {
02144 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02145 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02146
02147 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
02148 }
02149
02150 Datum
02151 timetz_cmp(PG_FUNCTION_ARGS)
02152 {
02153 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02154 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02155
02156 PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
02157 }
02158
02159 Datum
02160 timetz_hash(PG_FUNCTION_ARGS)
02161 {
02162 TimeTzADT *key = PG_GETARG_TIMETZADT_P(0);
02163 uint32 thash;
02164
02165
02166
02167
02168
02169
02170
02171 #ifdef HAVE_INT64_TIMESTAMP
02172 thash = DatumGetUInt32(DirectFunctionCall1(hashint8,
02173 Int64GetDatumFast(key->time)));
02174 #else
02175 thash = DatumGetUInt32(DirectFunctionCall1(hashfloat8,
02176 Float8GetDatumFast(key->time)));
02177 #endif
02178 thash ^= DatumGetUInt32(hash_uint32(key->zone));
02179 PG_RETURN_UINT32(thash);
02180 }
02181
02182 Datum
02183 timetz_larger(PG_FUNCTION_ARGS)
02184 {
02185 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02186 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02187 TimeTzADT *result;
02188
02189 if (timetz_cmp_internal(time1, time2) > 0)
02190 result = time1;
02191 else
02192 result = time2;
02193 PG_RETURN_TIMETZADT_P(result);
02194 }
02195
02196 Datum
02197 timetz_smaller(PG_FUNCTION_ARGS)
02198 {
02199 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
02200 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
02201 TimeTzADT *result;
02202
02203 if (timetz_cmp_internal(time1, time2) < 0)
02204 result = time1;
02205 else
02206 result = time2;
02207 PG_RETURN_TIMETZADT_P(result);
02208 }
02209
02210
02211
02212
02213 Datum
02214 timetz_pl_interval(PG_FUNCTION_ARGS)
02215 {
02216 TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
02217 Interval *span = PG_GETARG_INTERVAL_P(1);
02218 TimeTzADT *result;
02219
02220 #ifndef HAVE_INT64_TIMESTAMP
02221 TimeTzADT time1;
02222 #endif
02223
02224 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02225
02226 #ifdef HAVE_INT64_TIMESTAMP
02227 result->time = time->time + span->time;
02228 result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
02229 if (result->time < INT64CONST(0))
02230 result->time += USECS_PER_DAY;
02231 #else
02232 result->time = time->time + span->time;
02233 TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
02234 if (result->time < 0)
02235 result->time += SECS_PER_DAY;
02236 #endif
02237
02238 result->zone = time->zone;
02239
02240 PG_RETURN_TIMETZADT_P(result);
02241 }
02242
02243
02244
02245
02246 Datum
02247 timetz_mi_interval(PG_FUNCTION_ARGS)
02248 {
02249 TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
02250 Interval *span = PG_GETARG_INTERVAL_P(1);
02251 TimeTzADT *result;
02252
02253 #ifndef HAVE_INT64_TIMESTAMP
02254 TimeTzADT time1;
02255 #endif
02256
02257 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02258
02259 #ifdef HAVE_INT64_TIMESTAMP
02260 result->time = time->time - span->time;
02261 result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
02262 if (result->time < INT64CONST(0))
02263 result->time += USECS_PER_DAY;
02264 #else
02265 result->time = time->time - span->time;
02266 TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
02267 if (result->time < 0)
02268 result->time += SECS_PER_DAY;
02269 #endif
02270
02271 result->zone = time->zone;
02272
02273 PG_RETURN_TIMETZADT_P(result);
02274 }
02275
02276
02277
02278
02279
02280
02281
02282 Datum
02283 overlaps_timetz(PG_FUNCTION_ARGS)
02284 {
02285
02286
02287
02288
02289 Datum ts1 = PG_GETARG_DATUM(0);
02290 Datum te1 = PG_GETARG_DATUM(1);
02291 Datum ts2 = PG_GETARG_DATUM(2);
02292 Datum te2 = PG_GETARG_DATUM(3);
02293 bool ts1IsNull = PG_ARGISNULL(0);
02294 bool te1IsNull = PG_ARGISNULL(1);
02295 bool ts2IsNull = PG_ARGISNULL(2);
02296 bool te2IsNull = PG_ARGISNULL(3);
02297
02298 #define TIMETZ_GT(t1,t2) \
02299 DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
02300 #define TIMETZ_LT(t1,t2) \
02301 DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
02302
02303
02304
02305
02306
02307
02308 if (ts1IsNull)
02309 {
02310 if (te1IsNull)
02311 PG_RETURN_NULL();
02312
02313 ts1 = te1;
02314 te1IsNull = true;
02315 }
02316 else if (!te1IsNull)
02317 {
02318 if (TIMETZ_GT(ts1, te1))
02319 {
02320 Datum tt = ts1;
02321
02322 ts1 = te1;
02323 te1 = tt;
02324 }
02325 }
02326
02327
02328 if (ts2IsNull)
02329 {
02330 if (te2IsNull)
02331 PG_RETURN_NULL();
02332
02333 ts2 = te2;
02334 te2IsNull = true;
02335 }
02336 else if (!te2IsNull)
02337 {
02338 if (TIMETZ_GT(ts2, te2))
02339 {
02340 Datum tt = ts2;
02341
02342 ts2 = te2;
02343 te2 = tt;
02344 }
02345 }
02346
02347
02348
02349
02350
02351 if (TIMETZ_GT(ts1, ts2))
02352 {
02353
02354
02355
02356
02357 if (te2IsNull)
02358 PG_RETURN_NULL();
02359 if (TIMETZ_LT(ts1, te2))
02360 PG_RETURN_BOOL(true);
02361 if (te1IsNull)
02362 PG_RETURN_NULL();
02363
02364
02365
02366
02367
02368 PG_RETURN_BOOL(false);
02369 }
02370 else if (TIMETZ_LT(ts1, ts2))
02371 {
02372
02373 if (te1IsNull)
02374 PG_RETURN_NULL();
02375 if (TIMETZ_LT(ts2, te1))
02376 PG_RETURN_BOOL(true);
02377 if (te2IsNull)
02378 PG_RETURN_NULL();
02379
02380
02381
02382
02383
02384 PG_RETURN_BOOL(false);
02385 }
02386 else
02387 {
02388
02389
02390
02391
02392 if (te1IsNull || te2IsNull)
02393 PG_RETURN_NULL();
02394 PG_RETURN_BOOL(true);
02395 }
02396
02397 #undef TIMETZ_GT
02398 #undef TIMETZ_LT
02399 }
02400
02401
02402 Datum
02403 timetz_time(PG_FUNCTION_ARGS)
02404 {
02405 TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
02406 TimeADT result;
02407
02408
02409 result = timetz->time;
02410
02411 PG_RETURN_TIMEADT(result);
02412 }
02413
02414
02415 Datum
02416 time_timetz(PG_FUNCTION_ARGS)
02417 {
02418 TimeADT time = PG_GETARG_TIMEADT(0);
02419 TimeTzADT *result;
02420 struct pg_tm tt,
02421 *tm = &tt;
02422 fsec_t fsec;
02423 int tz;
02424
02425 GetCurrentDateTime(tm);
02426 time2tm(time, tm, &fsec);
02427 tz = DetermineTimeZoneOffset(tm, session_timezone);
02428
02429 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02430
02431 result->time = time;
02432 result->zone = tz;
02433
02434 PG_RETURN_TIMETZADT_P(result);
02435 }
02436
02437
02438
02439
02440
02441 Datum
02442 timestamptz_timetz(PG_FUNCTION_ARGS)
02443 {
02444 TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
02445 TimeTzADT *result;
02446 struct pg_tm tt,
02447 *tm = &tt;
02448 int tz;
02449 fsec_t fsec;
02450
02451 if (TIMESTAMP_NOT_FINITE(timestamp))
02452 PG_RETURN_NULL();
02453
02454 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
02455 ereport(ERROR,
02456 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
02457 errmsg("timestamp out of range")));
02458
02459 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02460
02461 tm2timetz(tm, fsec, tz, result);
02462
02463 PG_RETURN_TIMETZADT_P(result);
02464 }
02465
02466
02467
02468
02469
02470
02471
02472
02473 Datum
02474 datetimetz_timestamptz(PG_FUNCTION_ARGS)
02475 {
02476 DateADT date = PG_GETARG_DATEADT(0);
02477 TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
02478 TimestampTz result;
02479
02480 if (DATE_IS_NOBEGIN(date))
02481 TIMESTAMP_NOBEGIN(result);
02482 else if (DATE_IS_NOEND(date))
02483 TIMESTAMP_NOEND(result);
02484 else
02485 {
02486 #ifdef HAVE_INT64_TIMESTAMP
02487 result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
02488 #else
02489 result = date * (double) SECS_PER_DAY + time->time + time->zone;
02490 #endif
02491 }
02492
02493 PG_RETURN_TIMESTAMP(result);
02494 }
02495
02496
02497
02498
02499
02500 Datum
02501 timetz_part(PG_FUNCTION_ARGS)
02502 {
02503 text *units = PG_GETARG_TEXT_PP(0);
02504 TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
02505 float8 result;
02506 int type,
02507 val;
02508 char *lowunits;
02509
02510 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
02511 VARSIZE_ANY_EXHDR(units),
02512 false);
02513
02514 type = DecodeUnits(0, lowunits, &val);
02515 if (type == UNKNOWN_FIELD)
02516 type = DecodeSpecial(0, lowunits, &val);
02517
02518 if (type == UNITS)
02519 {
02520 double dummy;
02521 int tz;
02522 fsec_t fsec;
02523 struct pg_tm tt,
02524 *tm = &tt;
02525
02526 timetz2tm(time, tm, &fsec, &tz);
02527
02528 switch (val)
02529 {
02530 case DTK_TZ:
02531 result = -tz;
02532 break;
02533
02534 case DTK_TZ_MINUTE:
02535 result = -tz;
02536 result /= SECS_PER_MINUTE;
02537 FMODULO(result, dummy, (double) SECS_PER_MINUTE);
02538 break;
02539
02540 case DTK_TZ_HOUR:
02541 dummy = -tz;
02542 FMODULO(dummy, result, (double) SECS_PER_HOUR);
02543 break;
02544
02545 case DTK_MICROSEC:
02546 #ifdef HAVE_INT64_TIMESTAMP
02547 result = tm->tm_sec * 1000000.0 + fsec;
02548 #else
02549 result = (tm->tm_sec + fsec) * 1000000;
02550 #endif
02551 break;
02552
02553 case DTK_MILLISEC:
02554 #ifdef HAVE_INT64_TIMESTAMP
02555 result = tm->tm_sec * 1000.0 + fsec / 1000.0;
02556 #else
02557 result = (tm->tm_sec + fsec) * 1000;
02558 #endif
02559 break;
02560
02561 case DTK_SECOND:
02562 #ifdef HAVE_INT64_TIMESTAMP
02563 result = tm->tm_sec + fsec / 1000000.0;
02564 #else
02565 result = tm->tm_sec + fsec;
02566 #endif
02567 break;
02568
02569 case DTK_MINUTE:
02570 result = tm->tm_min;
02571 break;
02572
02573 case DTK_HOUR:
02574 result = tm->tm_hour;
02575 break;
02576
02577 case DTK_DAY:
02578 case DTK_MONTH:
02579 case DTK_QUARTER:
02580 case DTK_YEAR:
02581 case DTK_DECADE:
02582 case DTK_CENTURY:
02583 case DTK_MILLENNIUM:
02584 default:
02585 ereport(ERROR,
02586 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
02587 errmsg("\"time with time zone\" units \"%s\" not recognized",
02588 lowunits)));
02589 result = 0;
02590 }
02591 }
02592 else if (type == RESERV && val == DTK_EPOCH)
02593 {
02594 #ifdef HAVE_INT64_TIMESTAMP
02595 result = time->time / 1000000.0 + time->zone;
02596 #else
02597 result = time->time + time->zone;
02598 #endif
02599 }
02600 else
02601 {
02602 ereport(ERROR,
02603 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
02604 errmsg("\"time with time zone\" units \"%s\" not recognized",
02605 lowunits)));
02606 result = 0;
02607 }
02608
02609 PG_RETURN_FLOAT8(result);
02610 }
02611
02612
02613
02614
02615
02616 Datum
02617 timetz_zone(PG_FUNCTION_ARGS)
02618 {
02619 text *zone = PG_GETARG_TEXT_PP(0);
02620 TimeTzADT *t = PG_GETARG_TIMETZADT_P(1);
02621 TimeTzADT *result;
02622 int tz;
02623 char tzname[TZ_STRLEN_MAX + 1];
02624 char *lowzone;
02625 int type,
02626 val;
02627 pg_tz *tzp;
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
02638 lowzone = downcase_truncate_identifier(tzname,
02639 strlen(tzname),
02640 false);
02641
02642 type = DecodeSpecial(0, lowzone, &val);
02643
02644 if (type == TZ || type == DTZ)
02645 tz = val * MINS_PER_HOUR;
02646 else
02647 {
02648 tzp = pg_tzset(tzname);
02649 if (tzp)
02650 {
02651
02652 pg_time_t now = (pg_time_t) time(NULL);
02653 struct pg_tm *tm;
02654
02655 tm = pg_localtime(&now, tzp);
02656 tz = -tm->tm_gmtoff;
02657 }
02658 else
02659 {
02660 ereport(ERROR,
02661 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
02662 errmsg("time zone \"%s\" not recognized", tzname)));
02663 tz = 0;
02664 }
02665 }
02666
02667 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02668
02669 #ifdef HAVE_INT64_TIMESTAMP
02670 result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
02671 while (result->time < INT64CONST(0))
02672 result->time += USECS_PER_DAY;
02673 while (result->time >= USECS_PER_DAY)
02674 result->time -= USECS_PER_DAY;
02675 #else
02676 result->time = t->time + (t->zone - tz);
02677 while (result->time < 0)
02678 result->time += SECS_PER_DAY;
02679 while (result->time >= SECS_PER_DAY)
02680 result->time -= SECS_PER_DAY;
02681 #endif
02682
02683 result->zone = tz;
02684
02685 PG_RETURN_TIMETZADT_P(result);
02686 }
02687
02688
02689
02690
02691 Datum
02692 timetz_izone(PG_FUNCTION_ARGS)
02693 {
02694 Interval *zone = PG_GETARG_INTERVAL_P(0);
02695 TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
02696 TimeTzADT *result;
02697 int tz;
02698
02699 if (zone->month != 0 || zone->day != 0)
02700 ereport(ERROR,
02701 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
02702 errmsg("interval time zone \"%s\" must not include months or days",
02703 DatumGetCString(DirectFunctionCall1(interval_out,
02704 PointerGetDatum(zone))))));
02705
02706 #ifdef HAVE_INT64_TIMESTAMP
02707 tz = -(zone->time / USECS_PER_SEC);
02708 #else
02709 tz = -(zone->time);
02710 #endif
02711
02712 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
02713
02714 #ifdef HAVE_INT64_TIMESTAMP
02715 result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
02716 while (result->time < INT64CONST(0))
02717 result->time += USECS_PER_DAY;
02718 while (result->time >= USECS_PER_DAY)
02719 result->time -= USECS_PER_DAY;
02720 #else
02721 result->time = time->time + (time->zone - tz);
02722 while (result->time < 0)
02723 result->time += SECS_PER_DAY;
02724 while (result->time >= SECS_PER_DAY)
02725 result->time -= SECS_PER_DAY;
02726 #endif
02727
02728 result->zone = tz;
02729
02730 PG_RETURN_TIMETZADT_P(result);
02731 }