Datum jsquery_hash(PG_FUNCTION_ARGS) { JsQuery *jq = PG_GETARG_JSQUERY(0); pg_crc32 res; INIT_CRC32(res); hashJsQuery(VARDATA(jq), 0, &res); FIN_CRC32(res); PG_FREE_IF_COPY(jq, 0); PG_RETURN_INT32(res); }
Datum jsquery_hash(PG_FUNCTION_ARGS) { JsQuery *jq = PG_GETARG_JSQUERY(0); JsQueryItem v; pg_crc32 res; INIT_CRC32(res); jsqInit(&v, jq); hashJsQuery(&v, &res); FIN_CRC32(res); PG_FREE_IF_COPY(jq, 0); PG_RETURN_INT32(res); }
static void hashJsQuery(JsQueryItem *v, pg_crc32 *crc) { JsQueryItem elem; check_stack_depth(); COMP_CRC32(*crc, &v->type, sizeof(v->type)); switch(v->type) { case jqiNull: COMP_CRC32(*crc, "null", 5); break; case jqiKey: case jqiString: { int32 len; char *s; s = jsqGetString(v, &len); if (v->type == jqiKey) len++; /* include trailing '\0' */ COMP_CRC32(*crc, s, len); } break; case jqiNumeric: *crc ^= (pg_crc32)DatumGetInt32(DirectFunctionCall1( hash_numeric, PointerGetDatum(jsqGetNumeric(v)))); break; case jqiBool: { bool b = jsqGetBool(v); COMP_CRC32(*crc, &b, 1); } break; case jqiArray: COMP_CRC32(*crc, &v->array.nelems, sizeof(v->array.nelems)); while(jsqIterateArray(v, &elem)) hashJsQuery(&elem, crc); break; case jqiAnd: case jqiOr: jsqGetLeftArg(v, &elem); hashJsQuery(&elem, crc); jsqGetRightArg(v, &elem); hashJsQuery(&elem, crc); break; case jqiNot: case jqiEqual: case jqiIn: case jqiLess: case jqiGreater: case jqiLessOrEqual: case jqiGreaterOrEqual: case jqiContains: case jqiContained: case jqiOverlap: jsqGetArg(v, &elem); hashJsQuery(&elem, crc); break; case jqiCurrent: case jqiLength: case jqiAny: case jqiAnyArray: case jqiAnyKey: case jqiAll: case jqiAllArray: case jqiAllKey: break; default: elog(ERROR, "Unknown JsQueryItem type: %d", v->type); } }
static void hashJsQuery(char *base, int32 pos, pg_crc32 *crc) { int32 type; int32 nextPos; check_stack_depth(); pos = readJsQueryHeader(base, pos, &type, &nextPos); COMP_CRC32(*crc, &type, sizeof(type)); switch(type) { case jqiNull: COMP_CRC32(*crc, "null", 5); break; case jqiKey: case jqiString: { int32 len; read_int32(len, base, pos); if (type == jqiKey) len++; /* include trailing '\0' */ COMP_CRC32(*crc, base + pos, len); } break; case jqiNumeric: *crc ^= (pg_crc32)DatumGetInt32(DirectFunctionCall1( hash_numeric, PointerGetDatum((Numeric)(base + pos)))); break; case jqiBool: { bool v; read_byte(v, base, pos); COMP_CRC32(*crc, &v, 1); } break; case jqiArray: { int32 i, nelems, *arrayPos; read_int32(nelems, base, pos); arrayPos = (int32*)(base + pos); COMP_CRC32(*crc, &nelems, sizeof(nelems)); for(i=0; i<nelems; i++) hashJsQuery(base, arrayPos[i], crc); } break; case jqiAnd: case jqiOr: { int32 left, right; read_int32(left, base, pos); read_int32(right, base, pos); hashJsQuery(base, left, crc); hashJsQuery(base, right, crc); } break; case jqiNot: case jqiEqual: case jqiIn: case jqiLess: case jqiGreater: case jqiLessOrEqual: case jqiGreaterOrEqual: case jqiContains: case jqiContained: case jqiOverlap: { int32 arg; read_int32(arg, base, pos); hashJsQuery(base, arg, crc); } break; case jqiAny: case jqiAnyArray: break; default: elog(ERROR, "Unknown JsQueryItem type: %d", type); } }