Depending on what you do exactly in your scripts, there are ways to work around it. I'll assume
SELECT only for the purpose of this answer. But
DELETE are possible, too ...
VIEW would be an option, like @Andriy commented. If you need the current table to stay in place as is, things get more complicated, but still possible. You could mask the table with a
VIEW of the same name in another schema listed before the schema of the table in the schema
search_path. I actually did that on several occasions to preserve interfaces I could not adapt after updates to the DB schema.
Basic sample code:
CREATE SCHEMA override;
CREATE VIEW override.tbl AS
SELECT *, foo AS bar -- to add the column a second time
-- tbl_id, foo AS bar -- to replace the column
Only grant the
USAGE privilege on the schema to
public to avoid abuse:
GRANT USAGE ON SCHEMA override TO public;
override as 1st schema in your
search_path and your original query "magically" includes another column.
If you don't want to mess with people's
search_path, you can do that dynamically in your scripts at the start of each session:
EXECUTE (SELECT 'SET search_path = override,' || setting
FROM pg_catalog.pg_settings WHERE name = 'search_path');
This is safe against SQL injection, because the subquery returns a valid search path.
Similar use case masking a function:
Or you can just create a temporary view to mask the table:
CREATE TEMP VIEW tbl AS
SELECT *, foo AS bar FROM tbl;
Temporary objects are only visible inside the same session and die with it.
You may need to do more for
DELETE. Most utility commands (DML) can't be fooled like that.
Postgres does not have generated columns per se, but you can use a function that looks and works just like one:
CREATE TABLE tbl (tbl_id int, foo text);
INSERT INTO tbl VALUES (1, 'hello');
CREATE FUNCTION bar(tbl) RETURNS text LANGUAGE sql STABLE AS 'SELECT $1.foo';
SELECT *, t.bar
FROM tbl t;