/* * Create partitions and return an OID of the partition that contain value */ Oid create_partitions(Oid relid, Datum value, Oid value_type, bool *crashed) { int ret; RangeEntry *ranges; Datum vals[2]; Oid oids[] = {OIDOID, value_type}; bool nulls[] = {false, false}; char *sql; bool found; int pos; PartRelationInfo *prel; RangeRelation *rangerel; FmgrInfo cmp_func; char *schema; *crashed = false; schema = get_extension_schema(); prel = get_pathman_relation_info(relid, NULL); rangerel = get_pathman_range_relation(relid, NULL); ranges = dsm_array_get_pointer(&rangerel->ranges); /* Comparison function */ cmp_func = *get_cmp_func(value_type, prel->atttype); vals[0] = ObjectIdGetDatum(relid); vals[1] = value; /* Perform PL procedure */ sql = psprintf("SELECT %s.append_partitions_on_demand_internal($1, $2)", schema); PG_TRY(); { ret = SPI_execute_with_args(sql, 2, oids, vals, nulls, false, 0); if (ret > 0) { /* Update relation info */ free_dsm_array(&rangerel->ranges); free_dsm_array(&prel->children); load_check_constraints(relid, GetCatalogSnapshot(relid)); } } PG_CATCH(); { elog(WARNING, "Attempt to create new partitions failed"); if (crashed != NULL) *crashed = true; return 0; } PG_END_TRY(); /* Repeat binary search */ ranges = dsm_array_get_pointer(&rangerel->ranges); pos = range_binary_search(rangerel, &cmp_func, value, &found); if (found) return ranges[pos].child_oid; return 0; }
bool search(vector<int>& nums, int target) { int min_index = find_min_index(nums); printf("%d\n", min_index); int target_index = -1; if (min_index == 0) { target_index = range_binary_search(nums, 0, nums.size() - 1, target); } else { if (nums[0] <= target && target <= nums[min_index - 1]) { target_index = range_binary_search(nums, 0, min_index - 1, target); } else if (nums[min_index] <= target && target <= nums[nums.size() - 1]) { target_index = range_binary_search(nums, min_index, nums.size() - 1, target); } } return target_index != -1; }
/* * Returns partition oid for specified parent relid and value. * In case when partition isn't exist try to create one. */ Datum find_or_create_range_partition(PG_FUNCTION_ARGS) { int relid = DatumGetInt32(PG_GETARG_DATUM(0)); Datum value = PG_GETARG_DATUM(1); Oid value_type = get_fn_expr_argtype(fcinfo->flinfo, 1); int pos; bool found; RangeRelation *rangerel; RangeEntry *ranges; TypeCacheEntry *tce; PartRelationInfo *prel; Oid cmp_proc_oid; FmgrInfo cmp_func; tce = lookup_type_cache(value_type, TYPECACHE_EQ_OPR | TYPECACHE_LT_OPR | TYPECACHE_GT_OPR | TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO); prel = get_pathman_relation_info(relid, NULL); rangerel = get_pathman_range_relation(relid, NULL); if (!prel || !rangerel) PG_RETURN_NULL(); cmp_proc_oid = get_opfamily_proc(tce->btree_opf, value_type, prel->atttype, BTORDER_PROC); fmgr_info(cmp_proc_oid, &cmp_func); ranges = dsm_array_get_pointer(&rangerel->ranges); pos = range_binary_search(rangerel, &cmp_func, value, &found); /* * If found then just return oid. Else create new partitions */ if (found) PG_RETURN_OID(ranges[pos].child_oid); /* * If not found and value is between first and last partitions */ if (!found && pos >= 0) PG_RETURN_NULL(); else { Oid child_oid; bool crashed = false; /* Lock config before appending new partitions */ LWLockAcquire(pmstate->load_config_lock, LW_EXCLUSIVE); /* Restrict concurrent partition creation */ LWLockAcquire(pmstate->edit_partitions_lock, LW_EXCLUSIVE); /* * Check if someone else has already created partition. */ ranges = dsm_array_get_pointer(&rangerel->ranges); pos = range_binary_search(rangerel, &cmp_func, value, &found); if (found) { LWLockRelease(pmstate->edit_partitions_lock); LWLockRelease(pmstate->load_config_lock); PG_RETURN_OID(ranges[pos].child_oid); } /* Start background worker to create new partitions */ child_oid = create_partitions_bg_worker(relid, value, value_type, &crashed); // SPI_connect(); // child_oid = create_partitions(relid, value, value_type, &crashed); // SPI_finish(); // elog(WARNING, "Worker finished"); /* Release locks */ if (!crashed) { LWLockRelease(pmstate->edit_partitions_lock); LWLockRelease(pmstate->load_config_lock); } /* Repeat binary search */ ranges = dsm_array_get_pointer(&rangerel->ranges); pos = range_binary_search(rangerel, &cmp_func, value, &found); if (found) PG_RETURN_OID(child_oid); } PG_RETURN_NULL(); }