Datum tstz_dist(PG_FUNCTION_ARGS) { TimestampTz a = PG_GETARG_TIMESTAMPTZ(0); TimestampTz b = PG_GETARG_TIMESTAMPTZ(1); Interval *r; if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b)) { Interval *p = palloc(sizeof(Interval)); p->day = INT_MAX; p->month = INT_MAX; #ifdef HAVE_INT64_TIMESTAMP p->time = INT64CONST(0x7FFFFFFFFFFFFFFF); #else p->time = DBL_MAX; #endif PG_RETURN_INTERVAL_P(p); } r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1))); PG_RETURN_INTERVAL_P(abs_interval(r)); }
Datum ora_timestamptz_round(PG_FUNCTION_ARGS) { TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0); TimestampTz result; text *fmt = PG_GETARG_TEXT_PP(1); int tz; fsec_t fsec; struct pg_tm tt, *tm = &tt; const char *tzn; bool redotz = false; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_TIMESTAMPTZ(timestamp); if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); tm_round(tm, fmt, &redotz); if (redotz) tz = DetermineTimeZoneOffset(tm, get_session_timezone(fcinfo)); if (tm2timestamp(tm, fsec, &tz, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); PG_RETURN_TIMESTAMPTZ(result); }
Datum HASHAPI_Hash_1_timestamptz(PG_FUNCTION_ARGS) { int32 num_segs; /* number of segments */ TimestampTz val1; /* varchar value */ unsigned int targetbucket; /* 0-based */ int16 algorithm; /* hashing algorithm */ Datum d1; Oid oid; /* Get number of segments */ num_segs = PG_GETARG_INT32(0); /* Get hashing algoriithm */ algorithm = PG_GETARG_INT16(1); /* Get the value to hash */ val1 = PG_GETARG_TIMESTAMPTZ(2); d1 = TimestampTzGetDatum(val1); /* create a CdbHash for this hash test. */ h = makeCdbHash(num_segs, algorithm); /* init cdb hash */ cdbhashinit(h); oid = TIMESTAMPTZOID; cdbhash(h, d1, oid); /* reduce the result hash value */ targetbucket = cdbhashreduce(h); PG_RETURN_INT32(targetbucket); /* return target bucket (segID) */ }
Datum dbms_pipe_pack_message_timestamp(PG_FUNCTION_ARGS) { TimestampTz dt = PG_GETARG_TIMESTAMPTZ(0); output_buffer = check_buffer(output_buffer, LOCALMSGSZ); pack_field(output_buffer, IT_TIMESTAMPTZ, sizeof(dt), &dt, InvalidOid); PG_RETURN_VOID(); }
Datum gbt_tstz_distance(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); TimestampTz query = PG_GETARG_TIMESTAMPTZ(1); /* Oid subtype = PG_GETARG_OID(3); */ char *kkk = (char *) DatumGetPointer(entry->key); GBT_NUMKEY_R key; Timestamp qqq; key.lower = (GBT_NUMKEY *) &kkk[0]; key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)]; qqq = tstz_to_ts_gmt(query); PG_RETURN_FLOAT8( gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo) ); }
/* * assign_distributed_transaction_id updates the shared memory allocated for this backend * and sets initiatorNodeIdentifier, transactionNumber, timestamp fields with the given * inputs. Also, the function sets the database id and process id via the information that * Postgres provides. * * This function is only intended for internal use for managing distributed transactions. * Users should not use this function for any purpose. */ Datum assign_distributed_transaction_id(PG_FUNCTION_ARGS) { CheckCitusVersion(ERROR); /* MyBackendData should always be avaliable, just out of paranoia */ if (!MyBackendData) { ereport(ERROR, (errmsg("backend is not ready for distributed transactions"))); } /* * Note that we don't need to lock shared memory (i.e., LockBackendSharedMemory()) here * since this function is executed after AssignDistributedTransactionId() issued on the * initiator node, which already takes the required lock to enforce the consistency. */ SpinLockAcquire(&MyBackendData->mutex); /* if an id is already assigned, release the lock and error */ if (MyBackendData->transactionId.transactionNumber != 0) { SpinLockRelease(&MyBackendData->mutex); ereport(ERROR, (errmsg("the backend has already been assigned a " "transaction id"))); } MyBackendData->databaseId = MyDatabaseId; MyBackendData->transactionId.initiatorNodeIdentifier = PG_GETARG_INT32(0); MyBackendData->transactionId.transactionNumber = PG_GETARG_INT64(1); MyBackendData->transactionId.timestamp = PG_GETARG_TIMESTAMPTZ(2); MyBackendData->transactionId.transactionOriginator = false; SpinLockRelease(&MyBackendData->mutex); PG_RETURN_VOID(); }
Datum gbt_tstz_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); TimestampTz query = PG_GETARG_TIMESTAMPTZ(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); char *kkk = (char *) DatumGetPointer(entry->key); GBT_NUMKEY_R key; Timestamp qqq; /* All cases served by this function are exact */ *recheck = false; key.lower = (GBT_NUMKEY *) &kkk[0]; key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)]; qqq = tstz_to_ts_gmt(query); PG_RETURN_BOOL( gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo) ); }
/* * linterp_abscissa * * Common code that checks arguments. The result is a floating point value * representing what fraction of the distance x lies along the interval from * x0 to x1. It can be negative or greater than one (extrapolation) though * this isn't the intended use. If x0 == x1, then the fraction is not * determined and the function returns 0 and sets *notnull false. In all * other cases (except error exits) *notnull is set to true. An additional * flag indicates whether the abscissa value is equal to the lower boundary * value. */ static float8 linterp_abscissa(PG_FUNCTION_ARGS, bool *p_eq_bounds, bool *p_eq_abscissas) { Oid x_type; Oid x0_type; Oid x1_type; Oid y0_type; Oid y1_type; float8 p = 0; bool eq_bounds = false; bool eq_abscissas = false; /* The abscissa (x) arguments are nominally declared anyelement. * All the type checking is up to us. We insist that the types * are exactly alike. Explicit casts may be needed. */ x_type = get_fn_expr_argtype(fcinfo->flinfo, 0); x0_type = get_fn_expr_argtype(fcinfo->flinfo, 1); x1_type = get_fn_expr_argtype(fcinfo->flinfo, 3); if (!OidIsValid(x_type)||!OidIsValid(x0_type)||!OidIsValid(x1_type)) { elog(ERROR, "could not determine argument data types"); } if ( x_type!=x0_type || x_type!=x1_type ) { elog(ERROR, "abscissa types unequal"); } /* The ordinate (y) arguments are specifically declared in the SQL * function declaration. Here we just check and insist they are * identical. */ y0_type = get_fn_expr_argtype(fcinfo->flinfo, 2); y1_type = get_fn_expr_argtype(fcinfo->flinfo, 4); if ( y0_type != y1_type ) { elog(ERROR, "mismatched ordinate types"); } switch (x_type) { case INT8OID: { float8 x = (float8)PG_GETARG_INT64(0); float8 x0 = (float8)PG_GETARG_INT64(1); float8 x1 = (float8)PG_GETARG_INT64(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case INT4OID: { float8 x = (float8)PG_GETARG_INT32(0); float8 x0 = (float8)PG_GETARG_INT32(1); float8 x1 = (float8)PG_GETARG_INT32(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case INT2OID: { float8 x = (float8)PG_GETARG_INT16(0); float8 x0 = (float8)PG_GETARG_INT16(1); float8 x1 = (float8)PG_GETARG_INT16(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case FLOAT4OID: { float8 x = (float8)PG_GETARG_FLOAT4(0); float8 x0 = (float8)PG_GETARG_FLOAT4(1); float8 x1 = (float8)PG_GETARG_FLOAT4(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case FLOAT8OID: { float8 x = PG_GETARG_FLOAT8(0); float8 x0 = PG_GETARG_FLOAT8(1); float8 x1 = PG_GETARG_FLOAT8(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case DATEOID: { DateADT x = PG_GETARG_DATEADT(0); DateADT x0 = PG_GETARG_DATEADT(1); DateADT x1 = PG_GETARG_DATEADT(3); int32 x_x0 = date_diff(x, x0); int32 x1_x0 = date_diff(x1, x0); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x_x0 == 0 ); } else p = ((float8)x_x0)/((float8)x1_x0); } break; case TIMEOID: { TimeADT x = PG_GETARG_TIMEADT(0); TimeADT x0 = PG_GETARG_TIMEADT(1); TimeADT x1 = PG_GETARG_TIMEADT(3); p = time_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case TIMESTAMPOID: { Timestamp x = PG_GETARG_TIMESTAMP(0); Timestamp x0 = PG_GETARG_TIMESTAMP(1); Timestamp x1 = PG_GETARG_TIMESTAMP(3); p = timestamp_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case TIMESTAMPTZOID: { TimestampTz x = PG_GETARG_TIMESTAMPTZ(0); TimestampTz x0 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz x1 = PG_GETARG_TIMESTAMPTZ(3); p = timestamptz_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case INTERVALOID: { Interval * x = PG_GETARG_INTERVAL_P(0); Interval * x0 = PG_GETARG_INTERVAL_P(1); Interval * x1 = PG_GETARG_INTERVAL_P(3); p = interval_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case NUMERICOID: { Numeric x = PG_GETARG_NUMERIC(0); Numeric x0 = PG_GETARG_NUMERIC(1); Numeric x1 = PG_GETARG_NUMERIC(3); p = numeric_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; default: elog(ERROR, "abscissa type not supported"); } if ( p_eq_bounds ) *p_eq_bounds = eq_bounds; if ( p_eq_abscissas ) *p_eq_abscissas = eq_abscissas; return p; }