X-Git-Url: http://sigaev.ru/git/gitweb.cgi?p=smlar.git;a=blobdiff_plain;f=smlar.c;h=13c8169ba49a2b6a7e6432146baea0e639095100;hp=84fc3444c15122efb0d2a1eed0f282b5711dfc43;hb=92dc9c753b98700a2533d160c243b6ee24606943;hpb=0bc52593d34ce24b38cbd4fb6225d97601c5b871 diff --git a/smlar.c b/smlar.c index 84fc344..13c8169 100644 --- a/smlar.c +++ b/smlar.c @@ -3,6 +3,7 @@ #include "fmgr.h" #include "access/genam.h" #include "access/heapam.h" +#include "access/htup_details.h" #include "access/nbtree.h" #include "catalog/indexing.h" #include "catalog/pg_am.h" @@ -11,6 +12,7 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_type.h" #include "executor/spi.h" +#include "utils/catcache.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -20,8 +22,14 @@ PG_MODULE_MAGIC; +#if (PG_VERSION_NUM >= 90400) +#define SNAPSHOT NULL +#else +#define SNAPSHOT SnapshotNow +#endif + static Oid -getDefaultOpclass(Oid amoid, Oid typid) +getDefaultOpclass(Oid amoid, Oid typid) { ScanKeyData skey; SysScanDesc scan; @@ -29,16 +37,16 @@ getDefaultOpclass(Oid amoid, Oid typid) Relation heapRel; Oid opclassOid = InvalidOid; - heapRel = heap_open(OperatorClassRelationId, AccessShareLock); + heapRel = heap_open(OperatorClassRelationId, AccessShareLock); ScanKeyInit(&skey, Anum_pg_opclass_opcmethod, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(amoid)); - scan = systable_beginscan(heapRel, - OpclassAmNameNspIndexId, true, - SnapshotNow, 1, &skey); + scan = systable_beginscan(heapRel, + OpclassAmNameNspIndexId, true, + SNAPSHOT, 1, &skey); while (HeapTupleIsValid((tuple = systable_getnext(scan)))) { @@ -59,7 +67,7 @@ getDefaultOpclass(Oid amoid, Oid typid) } static Oid -getAMProc(Oid amoid, Oid typid) +getAMProc(Oid amoid, Oid typid) { Oid opclassOid = getDefaultOpclass(amoid, typid); Oid procOid = InvalidOid; @@ -83,13 +91,18 @@ getAMProc(Oid amoid, Oid typid) /* * Search binary-coercible type */ +#ifdef SearchSysCacheList1 + catlist = SearchSysCacheList1(CASTSOURCETARGET, + ObjectIdGetDatum(typid)); +#else catlist = SearchSysCacheList(CASTSOURCETARGET, 1, ObjectIdGetDatum(typid), 0, 0, 0); +#endif for (i = 0; i < catlist->n_members; i++) { - HeapTuple tuple = &catlist->members[i]->tuple; + HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_cast castForm = (Form_pg_cast)GETSTRUCT(tuple); if ( castForm->castfunc == InvalidOid && castForm->castcontext == COERCION_CODE_IMPLICIT ) @@ -103,7 +116,7 @@ getAMProc(Oid amoid, Oid typid) ReleaseSysCacheList(catlist); } - + if ( !OidIsValid(opclassOid) ) return InvalidOid; @@ -130,7 +143,7 @@ getAMProc(Oid amoid, Oid typid) #endif scan = systable_beginscan(heapRel, AccessMethodProcedureIndexId, true, - SnapshotNow, + SNAPSHOT, #if PG_VERSION_NUM >= 90200 4, #else @@ -163,6 +176,10 @@ getAMProc(Oid amoid, Oid typid) static ProcTypeInfo *cacheProcs = NULL; static int nCacheProcs = 0; +#ifndef TupleDescAttr +#define TupleDescAttr(tupdesc, i) ((tupdesc)->attrs[(i)]) +#endif + static ProcTypeInfo fillProcs(Oid typid) { @@ -184,7 +201,7 @@ fillProcs(Oid typid) if (tupdesc->natts != 2) elog(ERROR,"Composite type has wrong number of fields"); - if (tupdesc->attrs[1]->atttypid != FLOAT4OID) + if (TupleDescAttr(tupdesc, 1)->atttypid != FLOAT4OID) elog(ERROR,"Second field of composite type is not float4"); oldcontext = MemoryContextSwitchTo(TopMemoryContext); @@ -193,10 +210,12 @@ fillProcs(Oid typid) ReleaseTupleDesc(tupdesc); - info->cmpFuncOid = getAMProc(BTREE_AM_OID, info->tupDesc->attrs[0]->atttypid); - info->hashFuncOid = getAMProc(HASH_AM_OID, info->tupDesc->attrs[0]->atttypid); - } - else + info->cmpFuncOid = getAMProc(BTREE_AM_OID, + TupleDescAttr(info->tupDesc, 0)->atttypid); + info->hashFuncOid = getAMProc(HASH_AM_OID, + TupleDescAttr(info->tupDesc, 0)->atttypid); + } + else { info->tupDesc = NULL; @@ -246,7 +265,7 @@ cmpProcTypeInfo(const void *a, const void *b) Assert( av->typid != bv->typid ); - return ( av->typid > bv->typid ) ? 1 : -1; + return ( av->typid > bv->typid ) ? 1 : -1; } ProcTypeInfo @@ -256,7 +275,7 @@ findProcs(Oid typid) if ( nCacheProcs == 1 ) { - if ( cacheProcs[0]->typid == typid ) + if ( cacheProcs[0]->typid == typid ) { /*cacheProcs[0]->hashFuncInited = cacheProcs[0]->cmpFuncInited = false;*/ return cacheProcs[0]; @@ -265,7 +284,7 @@ findProcs(Oid typid) else if ( nCacheProcs > 1 ) { ProcTypeInfo *StopMiddle; - ProcTypeInfo *StopLow = cacheProcs, + ProcTypeInfo *StopLow = cacheProcs, *StopHigh = cacheProcs + nCacheProcs; while (StopLow < StopHigh) { @@ -287,7 +306,7 @@ findProcs(Oid typid) } info = fillProcs(typid); - if ( nCacheProcs == 0 ) + if ( nCacheProcs == 0 ) { cacheProcs = malloc(sizeof(ProcTypeInfo)); @@ -371,11 +390,11 @@ cmpArrayElem(const void *a, const void *b, void *arg) { ProcTypeInfo info = (ProcTypeInfo)arg; - if (info->tupDesc) + if (info->tupDesc) /* composite type */ return DatumGetInt32( FCall2( &info->cmpFunc, - deconstructCompositeType(info, *(Datum*)a, NULL), - deconstructCompositeType(info, *(Datum*)b, NULL) ) ); + deconstructCompositeType(info, *(Datum*)a, NULL), + deconstructCompositeType(info, *(Datum*)b, NULL) ) ); return DatumGetInt32( FCall2( &info->cmpFunc, *(Datum*)a, *(Datum*)b ) ); @@ -405,13 +424,13 @@ typedef struct cmpArrayElemData { static int cmpArrayElemArg(const void *a, const void *b, void *arg) { - cmpArrayElemData *data = (cmpArrayElemData*)arg; - int res; + cmpArrayElemData *data = (cmpArrayElemData*)arg; + int res; if (data->info->tupDesc) res = DatumGetInt32( FCall2( &data->info->cmpFunc, - deconstructCompositeType(data->info, *(Datum*)a, NULL), - deconstructCompositeType(data->info, *(Datum*)b, NULL) ) ); + deconstructCompositeType(data->info, *(Datum*)a, NULL), + deconstructCompositeType(data->info, *(Datum*)b, NULL) ) ); else res = DatumGetInt32( FCall2( &data->info->cmpFunc, *(Datum*)a, *(Datum*)b ) ); @@ -446,7 +465,7 @@ Array2SimpleArrayU(ProcTypeInfo info, ArrayType *a, void *cache) if ( s->nelems > 1 ) { cmpArrayElemData data; - int i; + int i; getFmgrInfoCmp(s->info); data.info = s->info; @@ -504,13 +523,13 @@ Array2SimpleArrayU(ProcTypeInfo info, ArrayType *a, void *cache) break; default: elog(ERROR,"Unknown TF method: %d", tfm); - } + } } else { s->df[i] = 0.0; /* unknown word */ } - } + } } } else if ( cache ) @@ -525,7 +544,7 @@ Array2SimpleArrayU(ProcTypeInfo info, ArrayType *a, void *cache) } } } - else if (s->nelems > 0 && cache) + else if (s->nelems > 0 && cache) { stat = fingArrayStat(cache, s->info->typid, s->elems[0], stat); if ( stat ) @@ -638,12 +657,12 @@ arraysml(PG_FUNCTION_ARGS) { ArrayType *a, *b; SimpleArray *sa, *sb; - - fcinfo->flinfo->fn_extra = SearchArrayCache( + + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(0), &a, &sa, NULL); - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(1), &b, &sb, NULL); @@ -656,10 +675,10 @@ arraysml(PG_FUNCTION_ARGS) switch(getSmlType()) { - case ST_TFIDF: + case ST_TFIDF: PG_RETURN_FLOAT4( TFIDFSml(sa, sb) ); break; - case ST_COSINE: + case ST_COSINE: { int cnt; double power; @@ -670,7 +689,7 @@ arraysml(PG_FUNCTION_ARGS) PG_RETURN_FLOAT4( ((double)cnt) / sqrt( power ) ); } break; - case ST_OVERLAP: + case ST_OVERLAP: { float4 res = (float4)numOfIntersect(sa, sb); @@ -681,7 +700,7 @@ arraysml(PG_FUNCTION_ARGS) elog(ERROR,"Unsupported formula type of similarity"); } - PG_RETURN_FLOAT4(0.0); /* keep compiler quiet */ + PG_RETURN_FLOAT4(0.0); /* keep compiler quiet */ } PG_FUNCTION_INFO_V1(arraysmlw); @@ -692,20 +711,19 @@ arraysmlw(PG_FUNCTION_ARGS) ArrayType *a, *b; SimpleArray *sa, *sb; bool useIntersect = PG_GETARG_BOOL(2); - double numerator = 0.0; - double denominatorA = 0.0, + double numerator = 0.0; + double denominatorA = 0.0, denominatorB = 0.0, tmpA, tmpB; int cmp; ProcTypeInfo info; int ai = 0, bi = 0; - - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(0), &a, &sa, NULL); - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(1), &b, &sb, NULL); @@ -774,12 +792,12 @@ arraysml_op(PG_FUNCTION_ARGS) ArrayType *a, *b; SimpleArray *sa, *sb; double power = 0.0; - - fcinfo->flinfo->fn_extra = SearchArrayCache( + + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(0), &a, &sa, NULL); - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(1), &b, &sb, NULL); @@ -792,10 +810,10 @@ arraysml_op(PG_FUNCTION_ARGS) switch(getSmlType()) { - case ST_TFIDF: + case ST_TFIDF: power = TFIDFSml(sa, sb); break; - case ST_COSINE: + case ST_COSINE: { int cnt; @@ -808,7 +826,7 @@ arraysml_op(PG_FUNCTION_ARGS) power = ((double)cnt) / power; } break; - case ST_OVERLAP: + case ST_OVERLAP: power = (double)numOfIntersect(sa, sb); break; default: @@ -837,13 +855,13 @@ arraysml_func(PG_FUNCTION_ARGS) bool isnull; void *plan; int stat; - text *formula = PG_GETARG_TEXT_P(2); - - fcinfo->flinfo->fn_extra = SearchArrayCache( + text *formula = PG_GETARG_TEXT_P(2); + + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(0), &a, &sa, NULL); - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(1), &b, &sb, NULL); @@ -861,7 +879,6 @@ arraysml_func(PG_FUNCTION_ARGS) SPI_connect(); - if ( cachedPlan == NULL || cachedLen != VARSIZE(formula) - VARHDRSZ || memcmp( cachedFormula, VARDATA(formula), VARSIZE(formula) - VARHDRSZ ) != 0 ) { @@ -890,7 +907,7 @@ arraysml_func(PG_FUNCTION_ARGS) SPI_freeplan(plan); cachedLen = VARSIZE(formula) - VARHDRSZ; - memcpy( cachedFormula, VARDATA(formula), VARSIZE(formula) - VARHDRSZ ); + memcpy( cachedFormula, VARDATA(formula), VARSIZE(formula) - VARHDRSZ ); } plan = cachedPlan; @@ -944,14 +961,14 @@ inarray(PG_FUNCTION_ARGS) { ArrayType *a; SimpleArray *sa; - Datum query = PG_GETARG_DATUM(1); + Datum query = PG_GETARG_DATUM(1); Oid queryTypeOid; Datum *StopLow, *StopHigh, *StopMiddle; int cmp; - fcinfo->flinfo->fn_extra = SearchArrayCache( + fcinfo->flinfo->fn_extra = SearchArrayCache( fcinfo->flinfo->fn_extra, fcinfo->flinfo->fn_mcxt, PG_GETARG_DATUM(0), &a, &sa, NULL); @@ -968,7 +985,7 @@ inarray(PG_FUNCTION_ARGS) StopLow = sa->elems; StopHigh = sa->elems + sa->nelems; - while (StopLow < StopHigh) + while (StopLow < StopHigh) { StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); cmp = cmpArrayElem(StopMiddle, &query, sa->info);