/* $Id: temp.sql 254 2008-07-20 22:27:16Z kate $ */ /* * Retrieve the name of the schema used for temporary tables in the * current session. * * PostgreSQL puts each temporary table into a schema (which is created * first if neccessary). The schema is named of the form 'pg_temp_X', * where X is the slot number of the session. Each session has one slot * only, and so by definition may have only one schema for temporary * tables. It may also have none, if no temporary tables have been * created. * * These schemas are listed in the information_schema for all * connections. We are interested only in the schema name for our * current session, which is what this function returns. * * Note that these schemas are not removed when the session terminates. * Rather like serial values, they increment only, for saftey during * rollbacks. This does not cause problems (rather, it solves them) - * to a newly-connected session, the "dead" temporary table schemas * appear as any other concurrent connection's do. * * Returns the name of the current temporary schema, or NULL if it does not * yet exist. */ CREATE FUNCTION _TempSchemaName() RETURNS TEXT LANGUAGE plpgsql STABLE STRICT AS $$ DECLARE schemas TEXT[]; tempschema TEXT; BEGIN SELECT currentschema INTO schemas FROM current_schemas(true) AS currentschema; /* * Note that PostgreSQL reserves pg_*, so we can assume that * there are no user-defined schemas under that name. (Or * rather that if there are, it is not our problem). */ SELECT schemas[i] INTO tempschema -- I'm just using generate_series here to avoid a for loop FROM generate_series(array_lower(schemas, 1), array_upper(schemas, 1)) AS i WHERE schemas[i] ~ '^pg_temp_[0-9]+$'; RETURN tempschema; END $$; /* * Ensure that a temporary table of the given name exists, and that it * contains no rows. * * Parameters: * $1 - The table name (case insensitive) * $2 - The name of a callback which creates the table if it does not * exist (also case insensitive). This takes no parameters and * returns void. */ CREATE FUNCTION _EnsureEmptyTableExists( TableName TEXT, CreateTable TEXT ) RETURNS void LANGUAGE plpgsql VOLATILE STRICT AS $$ DECLARE tempschema TEXT; BEGIN /* * This is dead simple; if the table exists already, we remove * the contents. If it dosen't, we call the callback to create it. */ SELECT _TempSchemaName() INTO tempschema; /* * If there's no temporary schema, there certinaly isn't * going to be a temporary table within that schema. */ IF tempschema IS NULL THEN /* This needs to be dynamic because TableName changes. (horrible) */ EXECUTE 'SELECT * FROM ' || CreateTable || '()'; RETURN; END IF; PERFORM table_name FROM information_schema.tables WHERE table_name = lower(TableName) AND table_type = 'LOCAL TEMPORARY' AND table_schema = tempschema; IF FOUND THEN /* (also horrible) */ EXECUTE 'TRUNCATE ' || TableName; RETURN; END IF; /* (and, also horrible) */ EXECUTE 'SELECT * FROM ' || CreateTable || '()'; PERFORM CT.assert_TableExists(tempschema, TableName); RETURN; END; $$;