22 #include "../postgis_config.h"
27 #include "access/htup_details.h"
28 #include "access/stratnum.h"
29 #include "catalog/namespace.h"
30 #include "catalog/pg_opfamily.h"
31 #include "catalog/pg_type_d.h"
32 #include "catalog/pg_am_d.h"
33 #include "nodes/supportnodes.h"
34 #include "nodes/nodeFuncs.h"
35 #include "nodes/makefuncs.h"
36 #include "optimizer/optimizer.h"
37 #include "parser/parse_func.h"
38 #include "utils/array.h"
39 #include "utils/builtins.h"
40 #include "utils/lsyscache.h"
41 #include "utils/numeric.h"
42 #include "utils/syscache.h"
46 #include "lwgeom_pg.h"
120 if (first_type == postgis_oid(GEOMETRYOID))
125 if (first_type == postgis_oid(GEOGRAPHYOID))
130 return InvalidStrategy;
190 {
"gist_geometry_ops_2d", 2},
191 {
"gist_geometry_ops_nd", 3},
192 {
"brin_geometry_inclusion_ops_2d", 2},
193 {
"brin_geometry_inclusion_ops_3d", 3},
194 {
"brin_geometry_inclusion_ops_4d", 3},
195 {
"spgist_geometry_ops_2d", 2},
196 {
"spgist_geometry_ops_3d", 3},
197 {
"spgist_geometry_ops_nd", 3},
213 const char *fn_name = get_func_name(funcid);
217 if(strcmp(idxfns->
fn_name, fn_name) == 0)
237 return idxdims->
dims;
254 Form_pg_opfamily familyform;
257 HeapTuple familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
258 if (!HeapTupleIsValid(familytup))
259 elog(ERROR,
"cache lookup failed for operator family %u", opfamilyoid);
260 familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
261 opfamilyam = familyform->opfmethod;
262 opfamilyname = NameStr(familyform->opfname);
263 elog(DEBUG3,
"%s: found opfamily %s [%u]", __func__, opfamilyname, opfamilyam);
267 ReleaseSysCache(familytup);
280 const Oid radiustype = FLOAT8OID;
281 const Oid expandfn_args[2] = {geotype, radiustype};
282 const bool noError =
true;
284 char *nspname = get_namespace_name(get_func_namespace(callingfunc));
285 List *expandfn_name = list_make2(makeString(nspname), makeString(
"st_expand"));
286 Oid expandfn_oid = LookupFuncName(expandfn_name, 2, expandfn_args, noError);
287 if (expandfn_oid == InvalidOid)
295 expandfn_name = list_make2(makeString(nspname), makeString(
"_st_expand"));
296 expandfn_oid = LookupFuncName(expandfn_name, 2, expandfn_args, noError);
297 if (expandfn_oid == InvalidOid)
298 elog(ERROR,
"%s: unable to lookup 'st_expand(Oid[%u], Oid[%u])'", __func__, geotype, radiustype);
322 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
329 postgis_initialize_cache();
331 if (IsA(rawreq, SupportRequestSelectivity))
333 SupportRequestSelectivity *req = (SupportRequestSelectivity *) rawreq;
343 POSTGIS_DEBUGF(2,
"%s: got selectivity %g", __func__, req->selectivity);
344 PG_RETURN_POINTER(req);
351 if (IsA(rawreq, SupportRequestIndexCondition))
353 SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
355 if (is_funcclause(req->node))
357 FuncExpr *clause = (FuncExpr *) req->node;
358 Oid funcid = clause->funcid;
360 Oid opfamilyoid = req->opfamily;
364 int nargs = list_length(clause->args);
365 Node *leftarg, *rightarg;
366 Oid leftdatatype, rightdatatype, oproid;
367 bool swapped =
false;
376 uint8_t opfamilydims;
378 if (opfamilyam != GIST_AM_OID &&
379 opfamilyam != SPGIST_AM_OID &&
380 opfamilyam != BRIN_AM_OID)
382 PG_RETURN_POINTER((Node *)NULL);
389 if (req->indexarg > 1)
390 PG_RETURN_POINTER((Node *)NULL);
397 if (opfamilydims == 3 && idxfn.dims != 3)
398 PG_RETURN_POINTER((Node *)NULL);
403 if (nargs < 2 || nargs < idxfn.expand_arg)
404 elog(ERROR,
"%s: associated with function with %d arguments", __func__, nargs);
416 if (req->indexarg == 0)
418 leftarg = linitial(clause->args);
419 rightarg = lsecond(clause->args);
423 rightarg = linitial(clause->args);
424 leftarg = lsecond(clause->args);
432 leftdatatype = exprType(leftarg);
433 rightdatatype = exprType(rightarg);
440 oproid = get_opfamily_member(opfamilyoid,
444 if (!OidIsValid(oproid))
446 "no spatial operator found for '%s': opfamily %u type %d",
458 if (idxfn.expand_arg)
461 Node *radiusarg = (Node *) list_nth(clause->args, idxfn.expand_arg-1);
464 FuncExpr *expandexpr = makeFuncExpr(expandfn_oid, rightdatatype,
465 list_make2(rightarg, radiusarg),
466 InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
472 #if POSTGIS_PGSQL_VERSION >= 140
473 if (!is_pseudo_constant_for_index(req->root, (Node*)expandexpr, req->index))
475 if (!is_pseudo_constant_for_index((Node*)expandexpr, req->index))
477 PG_RETURN_POINTER((Node*)NULL);
480 expr = make_opclause(oproid, BOOLOID,
false,
481 (Expr *) leftarg, (Expr *) expandexpr,
482 InvalidOid, InvalidOid);
484 ret = (Node *)(list_make1(expr));
499 #if POSTGIS_PGSQL_VERSION >= 140
500 if (!is_pseudo_constant_for_index(req->root, rightarg, req->index))
502 if (!is_pseudo_constant_for_index(rightarg, req->index))
504 PG_RETURN_POINTER((Node*)NULL);
513 oproid = get_commutator(oproid);
514 if (!OidIsValid(oproid))
515 PG_RETURN_POINTER((Node *)NULL);
518 expr = make_opclause(oproid, BOOLOID,
false,
519 (Expr *) leftarg, (Expr *) rightarg,
520 InvalidOid, InvalidOid);
522 ret = (Node *)(list_make1(expr));
532 PG_RETURN_POINTER(ret);
536 elog(WARNING,
"support function '%s' called from unsupported spatial function", __func__);
541 PG_RETURN_POINTER(ret);
static const IndexableFunction IndexableFunctions[]
static const int16 GeometryStrategies[]
@ ST_LINECROSSINGDIRECTION_IDX
@ ST_CONTAINSPROPERLY_IDX
static bool needsSpatialIndex(Oid funcid, IndexableFunction *idxfn)
Datum postgis_index_supportfn(PG_FUNCTION_ARGS)
static Oid expandFunctionOid(Oid geotype, Oid callingfunc)
PG_FUNCTION_INFO_V1(postgis_index_supportfn)
static const OpFamilyDim OpFamilyDims[]
static Oid opFamilyAmOid(Oid opfamilyoid, uint8_t *dims)
float8 gserialized_sel_internal(PlannerInfo *root, List *args, int varRelid, int mode)
This function should return an estimation of the number of rows returned by a query involving an over...
float8 gserialized_joinsel_internal(PlannerInfo *root, List *args, JoinType jointype, int mode)
static uint8_t opFamilyDim(const char *opfamily)
static const int16 GeographyStrategies[]
static int16 get_strategy_by_type(Oid first_type, uint16_t index)
This library is the generic geometry handling section of PostGIS.
const char * opfamilyname