|
13 | 13 | #include "relation_info.h" |
14 | 14 | #include "utils.h" |
15 | 15 | #include "xact_handling.h" |
| 16 | +#include "fmgr.h" |
16 | 17 |
|
17 | 18 | #include "access/htup_details.h" |
18 | 19 | #include "access/nbtree.h" |
19 | 20 | #include "access/xact.h" |
20 | 21 | #include "catalog/indexing.h" |
| 22 | +#include "catalog/pg_type.h" |
| 23 | +#include "catalog/pg_proc.h" |
21 | 24 | #include "commands/sequence.h" |
22 | 25 | #include "commands/tablespace.h" |
23 | 26 | #include "miscadmin.h" |
|
28 | 31 | #include "utils/lsyscache.h" |
29 | 32 | #include "utils/syscache.h" |
30 | 33 | #include "utils/typcache.h" |
| 34 | +#include "utils/jsonb.h" |
| 35 | +#include "utils/fmgroids.h" |
31 | 36 |
|
32 | 37 |
|
33 | 38 | /* declarations */ |
@@ -57,7 +62,8 @@ PG_FUNCTION_INFO_V1( lock_partitioned_relation ); |
57 | 62 | PG_FUNCTION_INFO_V1( prevent_relation_modification ); |
58 | 63 | PG_FUNCTION_INFO_V1( debug_capture ); |
59 | 64 | PG_FUNCTION_INFO_V1( get_rel_tablespace_name ); |
60 | | - |
| 65 | +PG_FUNCTION_INFO_V1( validate_on_partition_created_callback ); |
| 66 | +PG_FUNCTION_INFO_V1( invoke_on_partition_created_callback ); |
61 | 67 |
|
62 | 68 | static void on_partitions_created_internal(Oid partitioned_table, bool add_callbacks); |
63 | 69 | static void on_partitions_updated_internal(Oid partitioned_table, bool add_callbacks); |
@@ -776,3 +782,87 @@ get_rel_tablespace_name(PG_FUNCTION_ARGS) |
776 | 782 | result = get_tablespace_name(tablespace_id); |
777 | 783 | PG_RETURN_TEXT_P(cstring_to_text(result)); |
778 | 784 | } |
| 785 | + |
| 786 | +/* |
| 787 | + * Checks that callback function meets specific requirements. Particularly it |
| 788 | + * must have the only JSONB argument and VOID return type |
| 789 | + */ |
| 790 | +Datum |
| 791 | +validate_on_partition_created_callback(PG_FUNCTION_ARGS) |
| 792 | +{ |
| 793 | + HeapTuple tp; |
| 794 | + Oid callback = PG_GETARG_OID(0); |
| 795 | + Form_pg_proc functup; |
| 796 | + |
| 797 | + tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(callback)); |
| 798 | + if (!HeapTupleIsValid(tp)) |
| 799 | + elog(ERROR, "cache lookup failed for function %u", callback); |
| 800 | + functup = (Form_pg_proc) GETSTRUCT(tp); |
| 801 | + |
| 802 | + if (functup->pronargs != 1 || functup->proargtypes.values[0] != JSONBOID || |
| 803 | + functup->prorettype != VOIDOID) |
| 804 | + elog(ERROR, |
| 805 | + "Callback function must have only one JSNOB argument " |
| 806 | + "and return VOID"); |
| 807 | + |
| 808 | + ReleaseSysCache(tp); |
| 809 | + PG_RETURN_VOID(); |
| 810 | +} |
| 811 | + |
| 812 | +/* |
| 813 | + * Builds JSONB object containing new partition parameters and invoke the |
| 814 | + * callback |
| 815 | + */ |
| 816 | +Datum |
| 817 | +invoke_on_partition_created_callback(PG_FUNCTION_ARGS) |
| 818 | +{ |
| 819 | + char *json; |
| 820 | + Datum jsonb; |
| 821 | + Oid parent_oid = PG_GETARG_OID(0); |
| 822 | + Oid partition_oid = PG_GETARG_OID(1); |
| 823 | + Oid type = get_fn_expr_argtype(fcinfo->flinfo, 2); |
| 824 | + Datum start_value = PG_GETARG_DATUM(2); |
| 825 | + Datum end_value = PG_GETARG_DATUM(3); |
| 826 | + const PartRelationInfo *prel; |
| 827 | + |
| 828 | + if ((prel = get_pathman_relation_info(parent_oid)) == NULL) |
| 829 | + elog(ERROR, |
| 830 | + "Relation %s isn't partitioned by pg_pathman", |
| 831 | + get_rel_name(parent_oid)); |
| 832 | + |
| 833 | + /* If there is no callback function specified then we're done */ |
| 834 | + if (!prel->callback) |
| 835 | + PG_RETURN_VOID(); |
| 836 | + |
| 837 | + /* Convert ANYELEMENT arguments to jsonb */ |
| 838 | + start_value = convert_to_jsonb(start_value, type); |
| 839 | + end_value = convert_to_jsonb(end_value, type); |
| 840 | + |
| 841 | + /* |
| 842 | + * Build jsonb object to pass into callback |
| 843 | + * |
| 844 | + * XXX it would be nice to have this rewrited with pushJsonbValue() to get |
| 845 | + * rid of string formatting and parsing. See jsonb_build_object() for |
| 846 | + * example |
| 847 | + */ |
| 848 | + json = psprintf("{" |
| 849 | + "\"parent\": %u," |
| 850 | + "\"partition\": %u," |
| 851 | + "\"part_type\": %u," |
| 852 | + "\"start\": %s," |
| 853 | + "\"end\": %s," |
| 854 | + "\"value_type\": %u}", |
| 855 | + parent_oid, |
| 856 | + partition_oid, |
| 857 | + prel->parttype, |
| 858 | + datum_to_cstring(start_value, JSONBOID), |
| 859 | + datum_to_cstring(end_value, JSONBOID), |
| 860 | + type |
| 861 | + ); |
| 862 | + jsonb = OidFunctionCall1(F_JSONB_IN, CStringGetDatum(json)); |
| 863 | + |
| 864 | + /* Invoke callback */ |
| 865 | + OidFunctionCall1(prel->callback, JsonbGetDatum(jsonb)); |
| 866 | + |
| 867 | + PG_RETURN_JSONB(jsonb); |
| 868 | +} |
0 commit comments