* array_contain_compare : * compares two arrays for overlap/containment * * When matchall is true, return true if all members of array1 are in array2. * When matchall is false, return true if any members of array1 are in array2. */
| 4268 | * When matchall is false, return true if any members of array1 are in array2. |
| 4269 | */ |
| 4270 | static bool |
| 4271 | array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, |
| 4272 | bool matchall, void **fn_extra) |
| 4273 | { |
| 4274 | LOCAL_FCINFO(locfcinfo, 2); |
| 4275 | bool result = matchall; |
| 4276 | Oid element_type = AARR_ELEMTYPE(array1); |
| 4277 | TypeCacheEntry *typentry; |
| 4278 | int nelems1; |
| 4279 | Datum *values2; |
| 4280 | bool *nulls2; |
| 4281 | int nelems2; |
| 4282 | int typlen; |
| 4283 | bool typbyval; |
| 4284 | char typalign; |
| 4285 | int i; |
| 4286 | int j; |
| 4287 | array_iter it1; |
| 4288 | |
| 4289 | if (element_type != AARR_ELEMTYPE(array2)) |
| 4290 | ereport(ERROR, |
| 4291 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
| 4292 | errmsg("cannot compare arrays of different element types"))); |
| 4293 | |
| 4294 | /* |
| 4295 | * We arrange to look up the equality function only once per series of |
| 4296 | * calls, assuming the element type doesn't change underneath us. The |
| 4297 | * typcache is used so that we have no memory leakage when being used as |
| 4298 | * an index support function. |
| 4299 | */ |
| 4300 | typentry = (TypeCacheEntry *) *fn_extra; |
| 4301 | if (typentry == NULL || |
| 4302 | typentry->type_id != element_type) |
| 4303 | { |
| 4304 | typentry = lookup_type_cache(element_type, |
| 4305 | TYPECACHE_EQ_OPR_FINFO); |
| 4306 | if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) |
| 4307 | ereport(ERROR, |
| 4308 | (errcode(ERRCODE_UNDEFINED_FUNCTION), |
| 4309 | errmsg("could not identify an equality operator for type %s", |
| 4310 | format_type_be(element_type)))); |
| 4311 | *fn_extra = (void *) typentry; |
| 4312 | } |
| 4313 | typlen = typentry->typlen; |
| 4314 | typbyval = typentry->typbyval; |
| 4315 | typalign = typentry->typalign; |
| 4316 | |
| 4317 | /* |
| 4318 | * Since we probably will need to scan array2 multiple times, it's |
| 4319 | * worthwhile to use deconstruct_array on it. We scan array1 the hard way |
| 4320 | * however, since we very likely won't need to look at all of it. |
| 4321 | */ |
| 4322 | if (VARATT_IS_EXPANDED_HEADER(array2)) |
| 4323 | { |
| 4324 | /* This should be safe even if input is read-only */ |
| 4325 | deconstruct_expanded_array(&(array2->xpn)); |
| 4326 | values2 = array2->xpn.dvalues; |
| 4327 | nulls2 = array2->xpn.dnulls; |
no test coverage detected