/* * Judge if we have to_regclass or not. */ bool pool_has_to_regclass(void) { /* * Query to know if to_regclass exists. */ #define HAS_TOREGCLASSQUERY "SELECT count(*) from (SELECT has_function_privilege('%s', 'pg_catalog.to_regclass(cstring)', 'execute') WHERE EXISTS(SELECT * FROM pg_catalog.pg_proc AS p WHERE p.proname = 'to_regclass')) AS s" bool result; static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; char *user; backend = pool_get_session_context(false)->backend; user = MASTER_CONNECTION(backend)->sp->user; if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, HAS_TOREGCLASSQUERY, int_register_func, int_unregister_func, false); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking to_regclass presence"))); return false; } } result = pool_search_relcache(relcache, backend, user) == 0 ? 0 : 1; return result; }
/* * Check if the function is stable. */ static bool is_immutable_function(char *fname) { /* * Query to know if the function is IMMUTABLE */ #define IS_STABLE_FUNCTION_QUERY "SELECT count(*) FROM pg_catalog.pg_proc AS p WHERE p.proname = '%s' AND p.provolatile = 'i'" bool result; static POOL_RELCACHE *relcache; POOL_CONNECTION_POOL *backend; backend = pool_get_session_context()->backend; if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, IS_STABLE_FUNCTION_QUERY, int_register_func, int_unregister_func, false); if (relcache == NULL) { pool_error("is_immutable_function: pool_create_relcache error"); return false; } pool_debug("is_immutable_function: relcache created"); } result = pool_search_relcache(relcache, backend, fname)==0?0:1; pool_debug("is_immutable_function: search result:%d", result); return result; }
/* * Judge if we have pgpool_regclass or not. */ bool pool_has_pgpool_regclass(void) { /* * Query to know if pgpool_regclass exists. */ #define HASPGPOOL_REGCLASSQUERY "SELECT count(*) from (SELECT has_function_privilege('%s', 'pgpool_regclass(cstring)', 'execute') WHERE EXISTS(SELECT * FROM pg_catalog.pg_proc AS p WHERE p.proname = 'pgpool_regclass')) AS s" bool result; static POOL_RELCACHE *relcache; POOL_CONNECTION_POOL *backend; char *user; backend = pool_get_session_context()->backend; user = MASTER_CONNECTION(backend)->sp->user; if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, HASPGPOOL_REGCLASSQUERY, int_register_func, int_unregister_func, false); if (relcache == NULL) { pool_error("has_pgpool_regclass: pool_create_relcache error"); return false; } } result = pool_search_relcache(relcache, backend, user)==0?0:1; return result; }
/* * Convert table_name(possibly including schema name) to oid */ int pool_table_name_to_oid(char *table_name) { /* * Query to convert table name to oid */ #define TABLE_TO_OID_QUERY "SELECT pgpool_regclass('%s')" #define TABLE_TO_OID_QUERY2 "SELECT oid FROM pg_class WHERE relname = '%s'" int oid = 0; static POOL_RELCACHE *relcache; POOL_CONNECTION_POOL *backend; char *query; if (table_name == NULL) { return oid; } backend = pool_get_session_context()->backend; if (pool_has_pgpool_regclass()) { query = TABLE_TO_OID_QUERY; } else { query = TABLE_TO_OID_QUERY2; } /* * If relcache does not exist, create it. */ if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, true); if (relcache == NULL) { pool_error("table_name_to_oid: pool_create_relcache error"); return oid; } /* Se do not cache if pgpool_regclass() returns 0, which indicates * there's no such a table. In this case we do not want to cache the * state because the table might be created later in this session. */ relcache->no_cache_if_zero = true; } /* * Search relcache. */ oid = (int)(intptr_t)pool_search_relcache(relcache, backend, table_name); return oid; }
static TSRel* relcache_lookup(TSRewriteContext *ctx) { #define ATTRDEFQUERY "SELECT attname, d.adsrc, coalesce((d.adsrc LIKE '%%now()%%' OR d.adsrc LIKE '%%''now''::text%%')" \ " AND (a.atttypid = 'timestamp'::regtype::oid OR" \ " a.atttypid = 'timestamp with time zone'::regtype::oid OR" \ " a.atttypid = 'date'::regtype::oid OR" \ " a.atttypid = 'time'::regtype::oid OR" \ " a.atttypid = 'time with time zone'::regtype::oid)" \ " , false)" \ " FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a " \ " LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid = d.adrelid AND a.attnum = d.adnum)" \ " WHERE c.oid = a.attrelid AND a.attnum >= 1 AND a.attisdropped = 'f' AND c.relname = '%s'" \ " ORDER BY a.attnum" #define ATTRDEFQUERY2 "SELECT attname, d.adsrc, coalesce((d.adsrc LIKE '%%now()%%' OR d.adsrc LIKE '%%''now''::text%%')" \ " AND (a.atttypid = 'timestamp'::regtype::oid OR" \ " a.atttypid = 'timestamp with time zone'::regtype::oid OR" \ " a.atttypid = 'date'::regtype::oid OR" \ " a.atttypid = 'time'::regtype::oid OR" \ " a.atttypid = 'time with time zone'::regtype::oid)" \ " , false)" \ " FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a " \ " LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid = d.adrelid AND a.attnum = d.adnum)" \ " WHERE c.oid = a.attrelid AND a.attnum >= 1 AND a.attisdropped = 'f' AND c.oid = pgpool_regclass('%s')" \ " ORDER BY a.attnum" char *query; if (pool_has_pgpool_regclass()) { query = ATTRDEFQUERY2; } else { query = ATTRDEFQUERY; } if (!ts_relcache) { ts_relcache = pool_create_relcache(pool_config->relcache_size, query, ts_register_func, ts_unregister_func, false); if (ts_relcache == NULL) { pool_error("relcache_lookup: pool_create_relcache error"); return NULL; } } return (TSRel *) pool_search_relcache(ts_relcache, ctx->backend, ctx->relname); }
/* * Judge the table used in a query is a view or not. */ bool is_view(char *table_name) { /* * Query to know if the target table is a view. */ #define ISVIEWQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.relname = '%s' AND c.relkind = 'v'" #define ISVIEWQUERY2 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('%s') AND c.relkind = 'v'" static POOL_RELCACHE *relcache; POOL_CONNECTION_POOL *backend; bool result; char *query; if (table_name == NULL) { return false; } backend = pool_get_session_context()->backend; /* pgpool_regclass has been installed */ if (pool_has_pgpool_regclass()) { query = ISVIEWQUERY2; } else { query = ISVIEWQUERY; } if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, false); if (relcache == NULL) { pool_error("is_view: pool_create_relcache error"); return false; } } /* * Search relcache. */ result = pool_search_relcache(relcache, backend, table_name)==0?false:true; return result; }
/* * Check if the function is stable. */ static bool is_immutable_function(char *fname) { /* * Query to know if the function is IMMUTABLE */ #define IS_STABLE_FUNCTION_QUERY "SELECT count(*) FROM pg_catalog.pg_proc AS p WHERE p.proname = '%s' AND p.provolatile = 'i'" bool result; static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; backend = pool_get_session_context(false)->backend; if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, IS_STABLE_FUNCTION_QUERY, int_register_func, int_unregister_func, false); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking if the function is immutable"))); return false; } ereport(DEBUG1, (errmsg("checking if the function is IMMUTABLE"), errdetail("relcache created"))); } result = (pool_search_relcache(relcache, backend, fname) == 0) ? 0 : 1; ereport(DEBUG1, (errmsg("checking if the function is IMMUTABLE"), errdetail("search result = %d", result))); return result; }
/* * Judge the table used in a query is a view or not. */ bool is_view(char *table_name) { /* * Query to know if the target table is a view (including a materialized view). */ #define ISVIEWQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.relname = '%s' AND (c.relkind = 'v' OR c.relkind = 'm')" #define ISVIEWQUERY2 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('%s') AND (c.relkind = 'v' OR c.relkind = 'm')" #define ISVIEWQUERY3 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pg_catalog.to_regclass('%s') AND (c.relkind = 'v' OR c.relkind = 'm')" static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; bool result; char *query; if (table_name == NULL) { return false; } if (!pool_has_to_regclass() && !pool_has_pgpool_regclass()) table_name = remove_quotes_and_schema_from_relname(table_name); backend = pool_get_session_context(false)->backend; /* PostgreSQL 9.4 or later has to_regclass() */ if (pool_has_to_regclass()) { query = ISVIEWQUERY3; } /* pgpool_regclass has been installed */ else if (pool_has_pgpool_regclass()) { query = ISVIEWQUERY2; } else { query = ISVIEWQUERY; } if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, false); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for view"))); return false; } } /* * Search relcache. */ result = pool_search_relcache(relcache, backend, table_name) == 0 ? false : true; return result; }
/* * Judge the table used in a query represented by node is a unlogged * table or not. */ bool is_unlogged_table(char *table_name) { /* * Query to know if pg_class has relpersistence column or not. * PostgreSQL 9.1 or later has this. */ #define HASRELPERSISTENCEQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c, pg_catalog.pg_attribute AS a WHERE c.relname = 'pg_class' AND a.attrelid = c.oid AND a.attname = 'relpersistence'" /* * Query to know if the target table is a unlogged one. This query * is valid in PostgreSQL 9.1 or later. */ #define ISUNLOGGEDQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.relname = '%s' AND c.relpersistence = 'u'" #define ISUNLOGGEDQUERY2 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('%s') AND c.relpersistence = 'u'" #define ISUNLOGGEDQUERY3 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pg_catalog.to_regclass('%s') AND c.relpersistence = 'u'" int hasrelpersistence; static POOL_RELCACHE * hasrelpersistence_cache; static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; if (table_name == NULL) { return false; } if (!pool_has_to_regclass() && !pool_has_pgpool_regclass()) table_name = remove_quotes_and_schema_from_relname(table_name); backend = pool_get_session_context(false)->backend; /* * Check backend version */ if (!hasrelpersistence_cache) { hasrelpersistence_cache = pool_create_relcache(pool_config->relcache_size, HASRELPERSISTENCEQUERY, int_register_func, int_unregister_func, false); if (hasrelpersistence_cache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for unlogged table"))); return false; } } hasrelpersistence = pool_search_relcache(hasrelpersistence_cache, backend, "pg_class") == 0 ? 0 : 1; if (hasrelpersistence) { bool result; char *query; /* PostgreSQL 9.4 or later has to_regclass() */ if (pool_has_to_regclass()) { query = ISUNLOGGEDQUERY3; } /* pgpool_regclass has been installed */ else if (pool_has_pgpool_regclass()) { query = ISUNLOGGEDQUERY2; } else { query = ISUNLOGGEDQUERY; } /* * If relcache does not exist, create it. */ if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, false); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for unlogged table"))); return false; } } /* * Search relcache. */ result = pool_search_relcache(relcache, backend, table_name) == 0 ? false : true; return result; } else { return false; } }
static bool is_temp_table(char *table_name) { /* * Query to know if pg_class has relistemp column or not. * PostgreSQL 8.4 and 9.0 have this. */ #define HASRELITEMPPQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c, pg_attribute AS a WHERE c.relname = 'pg_class' AND a.attrelid = c.oid AND a.attname = 'relistemp'" /* * Query to know if the target table is a temporary one. This query * is valid in PostgreSQL 7.3 to 8.3 and 9.1 or later. We do not use * regclass (or its variant) here, because temporary tables never have * schema qualified name. */ #define ISTEMPQUERY83 "SELECT count(*) FROM pg_catalog.pg_class AS c, pg_namespace AS n WHERE c.relname = '%s' AND c.relnamespace = n.oid AND n.nspname ~ '^pg_temp_'" /* * Query to know if the target table is a temporary one. This query * is valid in PostgreSQL 8.4 and 9.0. We do not use regclass (or its * variant) here, because temporary tables never have schema qualified * name. */ #define ISTEMPQUERY84 "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.relname = '%s' AND c.relistemp" int hasrelistemp; bool result; static POOL_RELCACHE * hasrelistemp_cache; char *query; POOL_CONNECTION_POOL *backend; if (table_name == NULL) { return false; } backend = pool_get_session_context(false)->backend; /* * Check backend version */ if (!hasrelistemp_cache) { hasrelistemp_cache = pool_create_relcache(pool_config->relcache_size, HASRELITEMPPQUERY, int_register_func, int_unregister_func, false); if (hasrelistemp_cache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for temporary table"))); return false; } } hasrelistemp = pool_search_relcache(hasrelistemp_cache, backend, "pg_class") == 0 ? 0 : 1; if (hasrelistemp) query = ISTEMPQUERY84; else query = ISTEMPQUERY83; /* * If relcache does not exist, create it. */ if (!is_temp_table_relcache) { is_temp_table_relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, true); if (is_temp_table_relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for temporary table"))); return false; } } /* * Search relcache. */ result = pool_search_relcache(is_temp_table_relcache, backend, table_name) == 0 ? false : true; return result; }
/* * Judge the table used in a query represented by node is a system * catalog or not. */ static bool is_system_catalog(char *table_name) { /* * Query to know if pg_namespace exists. PostgreSQL 7.2 or before doesn't have. */ #define HASPGNAMESPACEQUERY "SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.relname = '%s'" /* * Query to know if the target table belongs pg_catalog schema. */ #define ISBELONGTOPGCATALOGQUERY "SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.relname = '%s' AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'" #define ISBELONGTOPGCATALOGQUERY2 "SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = pgpool_regclass('\"%s\"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'" #define ISBELONGTOPGCATALOGQUERY3 "SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = pg_catalog.to_regclass('\"%s\"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'" int hasreliscatalog; bool result; static POOL_RELCACHE * hasreliscatalog_cache; static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; if (table_name == NULL) { return false; } if (!pool_has_to_regclass() && !pool_has_pgpool_regclass()) table_name = remove_quotes_and_schema_from_relname(table_name); backend = pool_get_session_context(false)->backend; /* * Check if pg_namespace exists */ if (!hasreliscatalog_cache) { char *query; query = HASPGNAMESPACEQUERY; hasreliscatalog_cache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, false); if (hasreliscatalog_cache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for system catalog"))); return false; } } hasreliscatalog = pool_search_relcache(hasreliscatalog_cache, backend, "pg_namespace") == 0 ? 0 : 1; if (hasreliscatalog) { /* * If relcache does not exist, create it. */ if (!relcache) { char *query; /* PostgreSQL 9.4 or later has to_regclass() */ if (pool_has_to_regclass()) { query = ISBELONGTOPGCATALOGQUERY3; } /* pgpool_regclass has been installed */ else if (pool_has_pgpool_regclass()) { query = ISBELONGTOPGCATALOGQUERY2; } else { query = ISBELONGTOPGCATALOGQUERY; } relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, false); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, while checking for system catalog"))); return false; } } /* * Search relcache. */ result = pool_search_relcache(relcache, backend, table_name) == 0 ? false : true; return result; } /* * Pre 7.3. Just check whether the table starts with "pg_". */ return (strcasecmp(table_name, "pg_") == 0); }
/* * Convert table_name(possibly including schema name) to oid */ int pool_table_name_to_oid(char *table_name) { /* * Query to convert table name to oid */ #define TABLE_TO_OID_QUERY "SELECT pgpool_regclass('%s')" #define TABLE_TO_OID_QUERY2 "SELECT oid FROM pg_class WHERE relname = '%s'" #define TABLE_TO_OID_QUERY3 "SELECT COALESCE(pg_catalog.to_regclass('%s')::oid, 0)" int oid = 0; static POOL_RELCACHE * relcache; POOL_CONNECTION_POOL *backend; char *query; if (table_name == NULL) { return oid; } if (!pool_has_to_regclass() && !pool_has_pgpool_regclass()) table_name = remove_quotes_and_schema_from_relname(table_name); backend = pool_get_session_context(false)->backend; if (pool_has_to_regclass()) { query = TABLE_TO_OID_QUERY3; } else if (pool_has_pgpool_regclass()) { query = TABLE_TO_OID_QUERY; } else { query = TABLE_TO_OID_QUERY2; } /* * If relcache does not exist, create it. */ if (!relcache) { relcache = pool_create_relcache(pool_config->relcache_size, query, int_register_func, int_unregister_func, true); if (relcache == NULL) { ereport(WARNING, (errmsg("unable to create relcache, getting OID from table name"))); return oid; } /* * Se do not cache if pgpool_regclass() returns 0, which indicates * there's no such a table. In this case we do not want to cache the * state because the table might be created later in this session. */ relcache->no_cache_if_zero = true; } /* * Search relcache. */ oid = (int) (intptr_t) pool_search_relcache(relcache, backend, table_name); return oid; }