Datum ginint4_queryextract(PG_FUNCTION_ARGS) { int32 *nentries = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); Datum *res = NULL; *nentries = 0; if (strategy == BooleanSearchStrategy) { QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0)); ITEM *items = GETQUERY(query); int i; if (query->size == 0) PG_RETURN_POINTER(NULL); if (shorterquery(items, query->size) == 0) elog(ERROR, "Query requires full scan, GIN doesn't support it"); pfree(query); query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0)); items = GETQUERY(query); res = (Datum *) palloc(sizeof(Datum) * query->size); *nentries = 0; for (i = 0; i < query->size; i++) if (items[i].type == VAL) { res[*nentries] = Int32GetDatum(items[i].val); (*nentries)++; } } else { ArrayType *query = PG_GETARG_ARRAYTYPE_P(0); int4 *arr; uint32 i; CHECKARRVALID(query); *nentries = ARRNELEMS(query); if (*nentries > 0) { res = (Datum *) palloc(sizeof(Datum) * (*nentries)); arr = ARRPTR(query); for (i = 0; i < *nentries; i++) res[i] = Int32GetDatum(arr[i]); } } if (*nentries == 0) { switch (strategy) { case BooleanSearchStrategy: case RTOverlapStrategyNumber: *nentries = -1; /* nobody can be found */ break; default: /* require fullscan: GIN can't find void * arrays */ break; } } PG_RETURN_POINTER(res); }
Datum ginint4_consistent(PG_FUNCTION_ARGS) { bool *check = (bool *) PG_GETARG_POINTER(0); StrategyNumber strategy = PG_GETARG_UINT16(1); /* int32 nkeys = PG_GETARG_INT32(3); */ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */ bool *recheck = (bool *) PG_GETARG_POINTER(5); bool res = FALSE; /* * we need not check array carefully, it's done by previous * ginarrayextract call */ switch (strategy) { case RTOverlapStrategyNumber: /* result is not lossy */ *recheck = false; /* at least one element in check[] is true, so result = true */ res = TRUE; break; case RTContainedByStrategyNumber: case RTOldContainedByStrategyNumber: /* we will need recheck */ *recheck = true; /* at least one element in check[] is true, so result = true */ res = TRUE; break; case RTSameStrategyNumber: { ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); int i, nentries = ARRNELEMS(query); /* we will need recheck */ *recheck = true; res = TRUE; for (i = 0; i < nentries; i++) if (!check[i]) { res = FALSE; break; } } break; case RTContainsStrategyNumber: case RTOldContainsStrategyNumber: { ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); int i, nentries = ARRNELEMS(query); /* result is not lossy */ *recheck = false; res = TRUE; for (i = 0; i < nentries; i++) if (!check[i]) { res = FALSE; break; } } break; case BooleanSearchStrategy: { QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2)); /* result is not lossy */ *recheck = false; res = ginconsistent(query, check); } break; default: elog(ERROR, "ginint4_consistent: unknown strategy number: %d", strategy); } PG_RETURN_BOOL(res); }
void rt__int_size(ArrayType *a, float *size) { *size = (float) ARRNELEMS(a); }
datum_t ginint4_queryextract(PG_FUNC_ARGS) { int32 *nentries = (int32 *) ARG_POINTER(1); strat_nr_t strategy = ARG_UINT16(2); int32 *searchMode = (int32 *) ARG_POINTER(6); datum_t *res = NULL; *nentries = 0; if (strategy == BooleanSearchStrategy) { QUERYTYPE *query = ARG_QUERYTYPE_P(0); ITEM *items = GETQUERY(query); int i; /* empty query must fail */ if (query->size <= 0) RET_POINTER(NULL); /* * If the query doesn't have any required primitive values (for * instance, it's something like '! 42'), we have to do a full index * scan. */ if (query_has_required_values(query)) *searchMode = GIN_SEARCH_MODE_DEFAULT; else *searchMode = GIN_SEARCH_MODE_ALL; /* * Extract all the VAL items as things we want GIN to check for. */ res = (datum_t *) palloc(sizeof(datum_t) * query->size); *nentries = 0; for (i = 0; i < query->size; i++) { if (items[i].type == VAL) { res[*nentries] = INT32_TO_D(items[i].val); (*nentries)++; } } } else { array_s *query = ARG_ARRAY_P(0); CHECKARRVALID(query); *nentries = ARRNELEMS(query); if (*nentries > 0) { int4 *arr; int32 i; res = (datum_t *) palloc(sizeof(datum_t) * (*nentries)); arr = ARRPTR(query); for (i = 0; i < *nentries; i++) res[i] = INT32_TO_D(arr[i]); } switch (strategy) { case RTOverlapStrategyNumber: *searchMode = GIN_SEARCH_MODE_DEFAULT; break; case RTContainedByStrategyNumber: case RTOldContainedByStrategyNumber: /* empty set is contained in everything */ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; break; case RTSameStrategyNumber: if (*nentries > 0) *searchMode = GIN_SEARCH_MODE_DEFAULT; else *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; break; case RTContainsStrategyNumber: case RTOldContainsStrategyNumber: if (*nentries > 0) *searchMode = GIN_SEARCH_MODE_DEFAULT; else /* everything contains the empty set */ *searchMode = GIN_SEARCH_MODE_ALL; break; default: elog(ERROR, "ginint4_queryextract: unknown strategy number: %d", strategy); } } RET_POINTER(res); }
/* ** GiST Compress and Decompress methods */ Datum g_int_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int len; int *dr; int i, min, cand; if (entry->leafkey) { r = DatumGetArrayTypePCopy(entry->key); CHECKARRVALID(r); PREPAREARR(r); if (ARRNELEMS(r) >= 2 * MAXNUMRANGE) elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead", 2 * MAXNUMRANGE - 1, ARRNELEMS(r)); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } /* * leaf entries never compress one more time, only when entry->leafkey * ==true, so now we work only with internal keys */ r = DatumGetArrayTypeP(entry->key); CHECKARRVALID(r); if (ARRISEMPTY(r)) { if (r != (ArrayType *) DatumGetPointer(entry->key)) pfree(r); PG_RETURN_POINTER(entry); } if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE) { /* compress */ if (r == (ArrayType *) DatumGetPointer(entry->key)) r = DatumGetArrayTypePCopy(entry->key); r = resize_intArrayType(r, 2 * (len)); dr = ARRPTR(r); for (i = len - 1; i >= 0; i--) dr[2 * i] = dr[2 * i + 1] = dr[i]; len *= 2; cand = 1; while (len > MAXNUMRANGE * 2) { min = 0x7fffffff; for (i = 2; i < len; i += 2) if (min > (dr[i] - dr[i - 1])) { min = (dr[i] - dr[i - 1]); cand = i; } memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32)); len -= 2; } r = resize_intArrayType(r, len); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } else PG_RETURN_POINTER(entry); PG_RETURN_POINTER(entry); }
Datum g_int_decompress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int *dr, lenr; ArrayType *in; int lenin; int *din; int i, j; in = DatumGetArrayTypeP(entry->key); CHECKARRVALID(in); if (ARRISEMPTY(in)) { if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } lenin = ARRNELEMS(in); if (lenin < 2 * MAXNUMRANGE) { /* not compressed value */ if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } din = ARRPTR(in); lenr = internal_size(din, lenin); r = new_intArrayType(lenr); dr = ARRPTR(r); for (i = 0; i < lenin; i += 2) for (j = din[i]; j <= din[i + 1]; j++) if ((!i) || *(dr - 1) != j) *dr++ = j; if (in != (ArrayType *) DatumGetPointer(entry->key)) pfree(in); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); }
Datum g_intbig_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); if (entry->leafkey) { GISTENTRY *retval; ArrayType *in = DatumGetArrayTypeP(entry->key); int32 *ptr; int num; GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0)); CHECKARRVALID(in); if (ARRISEMPTY(in)) { ptr = NULL; num = 0; } else { ptr = ARRPTR(in); num = ARRNELEMS(in); } SET_VARSIZE(res, CALCGTSIZE(0)); while (num--) { HASH(GETSIGN(res), *ptr); ptr++; } retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); if (in != DatumGetArrayTypeP(entry->key)) pfree(in); PG_RETURN_POINTER(retval); } else if (!ISALLTRUE(DatumGetPointer(entry->key))) { GISTENTRY *retval; int i; BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); GISTTYPE *res; LOOPBYTE { if ((sign[i] & 0xff) != 0xff) PG_RETURN_POINTER(entry); } res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE)); SET_VARSIZE(res, CALCGTSIZE(ALLISTRUE)); res->flag = ALLISTRUE; retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); }
/* ** GiST Compress and Decompress methods */ Datum g_int_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int len; int *dr; int i, min, cand; if (entry->leafkey) { r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key); PREPAREARR(r); r->flags |= LEAFKEY; retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE); PG_RETURN_POINTER(retval); } r = (ArrayType *) PG_DETOAST_DATUM(entry->key); if (ISLEAFKEY(r) || ARRISVOID(r)) { if (r != (ArrayType *) DatumGetPointer(entry->key)) pfree(r); PG_RETURN_POINTER(entry); } if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE) { /* compress */ if (r == (ArrayType *) DatumGetPointer(entry->key)) r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key); r = resize_intArrayType(r, 2 * (len)); dr = ARRPTR(r); for (i = len - 1; i >= 0; i--) dr[2 * i] = dr[2 * i + 1] = dr[i]; len *= 2; cand = 1; while (len > MAXNUMRANGE * 2) { min = 0x7fffffff; for (i = 2; i < len; i += 2) if (min > (dr[i] - dr[i - 1])) { min = (dr[i] - dr[i - 1]); cand = i; } memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int)); len -= 2; } r = resize_intArrayType(r, len); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE); PG_RETURN_POINTER(retval); } else PG_RETURN_POINTER(entry); PG_RETURN_POINTER(entry); }
Datum ta_f( PG_FUNCTION_ARGS) { // Declare for TA TA_RetCode retCode; TA_Real *closePrice = NULL; TA_Real *out; TA_Integer outBeg; TA_Integer outNbElement; // Declare for postgres FuncCallContext *funcctx; int call_cntr; int max_calls; Datum *result = NULL; int dim; int z; ArrayType *ur = PG_GETARG_ARRAYTYPE_P(0); if (array_contains_nulls(ur)) { ereport(ERROR, ( errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("cannot work with arrays containing NULLs") )); } dim = ARRNELEMS(ur); closePrice = ARRPTR(ur); if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* One-time setup code appears here: */ retCode = TA_Initialize(); if (retCode != TA_SUCCESS) { ereport(ERROR, ( errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot initialize TA-Lib (%d)!\n", retCode) )); } out = palloc(dim * sizeof(TA_Real)); retCode = TA_MA(0, dim - 1, &closePrice[0], 5, TA_MAType_SMA, &outBeg, &outNbElement, &out[0]); result = palloc(outNbElement * sizeof(Datum)); // Error log for debugging /* ereport(NOTICE, (errmsg("dims %d, outBeg: %d, outNbElement %d\n", dim, outBeg, outNbElement))); */ for (z = 0; z < dim; z++) { // Error log for debugging //ereport(NOTICE, (errmsg("z: %d, out[z]: %5.1f", z, out[z]))); if(z > outBeg-1) { result[z] = Float8GetDatum(out[z-outBeg]); continue; } result[z] = NULL; } TA_Shutdown(); funcctx->max_calls = dim; funcctx->user_fctx = result; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; if (call_cntr < max_calls) { if(((Datum *) funcctx->user_fctx)[call_cntr]) { SRF_RETURN_NEXT(funcctx, ((Datum *) funcctx->user_fctx)[call_cntr]); } SRF_RETURN_NEXT_NULL(funcctx); } SRF_RETURN_DONE(funcctx); }
void init_cfg(Oid id, TSCfgInfo * cfg) { Oid arg[2]; bool isnull; Datum pars[2]; int stat, i, j; text *ptr; text *prsname = NULL; char *nsp = get_namespace(TSNSP_FunctionOid); char buf[1024]; MemoryContext oldcontext; void *plan; arg[0] = OIDOID; arg[1] = OIDOID; pars[0] = ObjectIdGetDatum(id); pars[1] = ObjectIdGetDatum(id); memset(cfg, 0, sizeof(TSCfgInfo)); SPI_connect(); sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp); plan = SPI_prepare(buf, 1, arg); if (!plan) ts_error(ERROR, "SPI_prepare() failed"); stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) { prsname = (text *) DatumGetPointer( SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull) ); oldcontext = MemoryContextSwitchTo(TopMemoryContext); prsname = ptextdup(prsname); MemoryContextSwitchTo(oldcontext); cfg->id = id; } else ts_error(ERROR, "No tsearch cfg with id %d", id); SPI_freeplan(plan); arg[0] = TEXTOID; sprintf(buf, "select lt.tokid, map.dict_name from %s.pg_ts_cfgmap as map, %s.pg_ts_cfg as cfg, %s.token_type( $1 ) as lt where lt.alias = map.tok_alias and map.ts_name = cfg.ts_name and cfg.oid= $2 order by lt.tokid desc;", nsp, nsp, nsp); plan = SPI_prepare(buf, 2, arg); if (!plan) ts_error(ERROR, "SPI_prepare() failed"); pars[0] = PointerGetDatum(prsname); stat = SPI_execp(plan, pars, " ", 0); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed <= 0) ts_error(ERROR, "No parser with id %d", id); for (i = 0; i < SPI_processed; i++) { int lexid = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull)); ArrayType *toasted_a = (ArrayType *) PointerGetDatum(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull)); ArrayType *a; if (!cfg->map) { cfg->len = lexid + 1; cfg->map = (ListDictionary *) malloc(sizeof(ListDictionary) * cfg->len); if (!cfg->map) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); memset(cfg->map, 0, sizeof(ListDictionary) * cfg->len); } if (isnull) continue; a = (ArrayType *) PointerGetDatum(PG_DETOAST_DATUM(DatumGetPointer(toasted_a))); if (ARR_NDIM(a) != 1) ts_error(ERROR, "Wrong dimension"); if (ARRNELEMS(a) < 1) continue; if (ARR_HASNULL(a)) ts_error(ERROR, "Array must not contain nulls"); cfg->map[lexid].len = ARRNELEMS(a); cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len); if (!cfg->map[lexid].dict_id) ts_error(ERROR, "No memory"); memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len); ptr = (text *) ARR_DATA_PTR(a); oldcontext = MemoryContextSwitchTo(TopMemoryContext); for (j = 0; j < cfg->map[lexid].len; j++) { cfg->map[lexid].dict_id[j] = PointerGetDatum(ptextdup(ptr)); ptr = NEXTVAL(ptr); } MemoryContextSwitchTo(oldcontext); if (a != toasted_a) pfree(a); } SPI_freeplan(plan); SPI_finish(); cfg->prs_id = name2id_prs(prsname); pfree(prsname); pfree(nsp); for (i = 0; i < cfg->len; i++) { for (j = 0; j < cfg->map[i].len; j++) { ptr = (text *) DatumGetPointer(cfg->map[i].dict_id[j]); cfg->map[i].dict_id[j] = ObjectIdGetDatum(name2id_dict(ptr)); pfree(ptr); } } }
/* ** Allows the construction of a cube from 2 float[]'s */ Datum cube_a_f8_f8(PG_FUNCTION_ARGS) { ArrayType *ur = PG_GETARG_ARRAYTYPE_P(0); ArrayType *ll = PG_GETARG_ARRAYTYPE_P(1); NDBOX *result; int i; int dim; int size; bool point; double *dur, *dll; if (array_contains_nulls(ur) || array_contains_nulls(ll)) ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("cannot work with arrays containing NULLs"))); dim = ARRNELEMS(ur); if (dim > CUBE_MAX_DIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("can't extend cube"), errdetail("A cube cannot have more than %d dimensions.", CUBE_MAX_DIM))); if (ARRNELEMS(ll) != dim) ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("UR and LL arrays must be of same length"))); dur = ARRPTR(ur); dll = ARRPTR(ll); /* Check if it's a point */ point = true; for (i = 0; i < dim; i++) { if (dur[i] != dll[i]) { point = false; break; } } size = point ? POINT_SIZE(dim) : CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); SET_DIM(result, dim); for (i = 0; i < dim; i++) result->x[i] = dur[i]; if (!point) { for (i = 0; i < dim; i++) result->x[i + dim] = dll[i]; } else SET_POINT_BIT(result); PG_RETURN_NDBOX(result); }