From: Marko Kreen Date: Thu, 11 Oct 2012 12:16:58 +0000 (+0300) Subject: Table invalidation X-Git-Tag: plproxy_2_5_rc1~5 X-Git-Url: http://git.postgresql.org/gitweb/static/%22display.php?a=commitdiff_plain;h=ccc9dbb8e6af5b050abbc76cad38a58f05b32cee;p=plproxy.git Table invalidation On each call, recheck type relation rowstamp. If it proves to be noticeable, we can use syscache callback infrastructure for that, but it will be much more complex. --- diff --git a/src/function.c b/src/function.c index b30e00e..6107795 100644 --- a/src/function.c +++ b/src/function.c @@ -426,13 +426,14 @@ fn_refresh_record(FunctionCallInfo fcinfo, TypeFuncClass rtc; TupleDesc tuple_current, tuple_cached; MemoryContext old_ctx; + Oid tuple_oid; int natts; /* * Compare cached tuple to current one. */ tuple_cached = func->ret_composite->tupdesc; - rtc = get_call_result_type(fcinfo, NULL, &tuple_current); + rtc = get_call_result_type(fcinfo, &tuple_oid, &tuple_current); Assert(rtc == TYPEFUNC_COMPOSITE); if (equalTupleDescs(tuple_current, tuple_cached)) return; @@ -448,7 +449,7 @@ fn_refresh_record(FunctionCallInfo fcinfo, pfree(func->remote_sql); /* construct new data */ - func->ret_composite = plproxy_composite_info(func, tuple_current); + func->ret_composite = plproxy_composite_info(func, tuple_current); natts = func->ret_composite->tupdesc->natts; func->result_map = plproxy_func_alloc(func, natts * sizeof(int)); func->remote_sql = plproxy_standard_query(func, true); @@ -551,6 +552,11 @@ plproxy_compile(FunctionCallInfo fcinfo, bool validate) /* in case of untyped RECORD, check if cached type is valid */ fn_refresh_record(fcinfo, f, proc_tuple); } + else if (f->ret_composite) + { + if (!plproxy_composite_valid(f->ret_composite)) + fn_refresh_record(fcinfo, f, proc_tuple); + } ReleaseSysCache(proc_tuple); diff --git a/src/plproxy.h b/src/plproxy.h index fc6d9b6..c262b72 100644 --- a/src/plproxy.h +++ b/src/plproxy.h @@ -298,6 +298,8 @@ typedef struct ProxyComposite char **name_list; /* Quoted column names */ int nfields; /* number of non-dropped fields */ bool use_binary; /* True if all columns support binary recv */ + bool alterable; /* if it's real table that can change */ + RowStamp stamp; } ProxyComposite; /* Temp structure for query parsing */ @@ -427,6 +429,7 @@ Datum plproxy_recv_type(ProxyType *type, char *str, int len, bool bin); HeapTuple plproxy_recv_composite(ProxyComposite *meta, char **values, int *lengths, int *fmts); void plproxy_free_type(ProxyType *type); void plproxy_free_composite(ProxyComposite *meta); +bool plproxy_composite_valid(ProxyComposite *type); /* cluster.c */ void plproxy_cluster_cache_init(void); diff --git a/src/type.c b/src/type.c index e091891..313cd59 100644 --- a/src/type.c +++ b/src/type.c @@ -71,6 +71,33 @@ static bool usable_binary(Oid oid) } } +bool +plproxy_composite_valid(ProxyComposite *type) +{ + HeapTuple type_tuple; + HeapTuple rel_tuple; + Form_pg_type pg_type; + Oid oid = type->tupdesc->tdtypeid; + bool res; + + if (!type->alterable) + return true; + type_tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(oid), 0, 0, 0); + if (!HeapTupleIsValid(type_tuple)) + elog(ERROR, "cache lookup failed for type %u", oid); + + pg_type = (Form_pg_type) GETSTRUCT(type_tuple); + rel_tuple = SearchSysCache(RELOID, ObjectIdGetDatum(pg_type->typrelid), 0, 0, 0); + if (!HeapTupleIsValid(rel_tuple)) + elog(ERROR, "cache lookup failed for type relation %u", pg_type->typrelid); + + res = plproxy_check_stamp(&type->stamp, rel_tuple); + + ReleaseSysCache(rel_tuple); + ReleaseSysCache(type_tuple); + + return res; +} /* * Collects info about fields of a composite type. * @@ -86,6 +113,7 @@ plproxy_composite_info(ProxyFunction *func, TupleDesc tupdesc) Form_pg_attribute a; ProxyType *type; const char *name; + Oid oid = tupdesc->tdtypeid; old_ctx = MemoryContextSwitchTo(func->ctx); @@ -95,6 +123,29 @@ plproxy_composite_info(ProxyFunction *func, TupleDesc tupdesc) ret->tupdesc = BlessTupleDesc(tupdesc); ret->use_binary = 1; + ret->alterable = 0; + if (oid != RECORDOID) + { + HeapTuple type_tuple; + HeapTuple rel_tuple; + Form_pg_type pg_type; + + type_tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(oid), 0, 0, 0); + if (!HeapTupleIsValid(type_tuple)) + elog(ERROR, "cache lookup failed for type %u", oid); + pg_type = (Form_pg_type) GETSTRUCT(type_tuple); + rel_tuple = SearchSysCache(RELOID, ObjectIdGetDatum(pg_type->typrelid), 0, 0, 0); + if (!HeapTupleIsValid(rel_tuple)) + elog(ERROR, "cache lookup failed for type relation %u", pg_type->typrelid); + plproxy_set_stamp(&ret->stamp, rel_tuple); + ReleaseSysCache(rel_tuple); + ReleaseSysCache(type_tuple); + ret->alterable = 1; + + if (ret->tupdesc->tdtypeid != oid) + elog(ERROR, "lost oid"); + } + MemoryContextSwitchTo(old_ctx); ret->nfields = 0; diff --git a/test/expected/plproxy_table.out b/test/expected/plproxy_table.out index 6774a5f..91c7b44 100644 --- a/test/expected/plproxy_table.out +++ b/test/expected/plproxy_table.out @@ -33,7 +33,12 @@ select * from test_table1(); -- add column alter table ret_table add column data2 text; ---select * from test_table1(); -- invalidate does not work +select * from test_table1(); + id | data | data2 +----+-------+------- + 1 | Data1 | Data2 +(1 row) + \c regression select * from test_table1(); id | data | data2 @@ -44,6 +49,12 @@ select * from test_table1(); -- drop & add alter table ret_table drop column data2; alter table ret_table add column data3 text; +select * from test_table1(); + id | data | data3 +----+-------+------- + 1 | Data1 | Data3 +(1 row) + \c regression select * from test_table1(); id | data | data3 @@ -51,3 +62,34 @@ select * from test_table1(); 1 | Data1 | Data3 (1 row) +-- drop +alter table ret_table drop column data3; +select * from test_table1(); + id | data +----+------- + 1 | Data1 +(1 row) + +\c regression +select * from test_table1(); + id | data +----+------- + 1 | Data1 +(1 row) + +-- add again +alter table ret_table add column data3 text; +alter table ret_table add column data2 text; +select * from test_table1(); + id | data | data3 | data2 +----+-------+-------+------- + 1 | Data1 | Data3 | Data2 +(1 row) + +\c regression +select * from test_table1(); + id | data | data3 | data2 +----+-------+-------+------- + 1 | Data1 | Data3 | Data2 +(1 row) + diff --git a/test/sql/plproxy_table.sql b/test/sql/plproxy_table.sql index 2be6691..595ce19 100644 --- a/test/sql/plproxy_table.sql +++ b/test/sql/plproxy_table.sql @@ -31,14 +31,27 @@ select * from test_table1(); -- add column alter table ret_table add column data2 text; ---select * from test_table1(); -- invalidate does not work +select * from test_table1(); \c regression select * from test_table1(); -- drop & add alter table ret_table drop column data2; alter table ret_table add column data3 text; +select * from test_table1(); +\c regression +select * from test_table1(); + +-- drop +alter table ret_table drop column data3; +select * from test_table1(); \c regression select * from test_table1(); +-- add again +alter table ret_table add column data3 text; +alter table ret_table add column data2 text; +select * from test_table1(); +\c regression +select * from test_table1();