I have the following query in which the forelast parameter should be false if the corresponding table is empty, and true otherwise:
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), ' ||
CASE WHEN (SELECT COUNT(*) FROM quote_ident(tablename))=0 THEN FALSE
ELSE TRUE
END ||
') FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
But instead it always evaluates to true.
Indeed the result of the subquery SELECT COUNT(*) FROM quote_ident(tablename) is always 1:
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), ' ||
(SELECT COUNT(*) FROM quote_ident(tablename))||
') FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
But I have no idea why.
For a minimal working example try:
create table empty(id serial, name varchar);
create table notempty(id serial, name varchar);
insert into notempty(name) values('foobar');
Now when you execute the query from above it evaluates for both tables true respectively 1:
SELECT SETVAL('public.empty_id_seq', COALESCE(MAX(id), -->1<--), 1) FROM public.empty;
SELECT SETVAL('public.notempty_id_seq', COALESCE(MAX(id), 1), 1) FROM public.notempty;
JOINsyntax. Easier to write (without errors), easier to read (and maintain), and easier to convert to outer join if needed.SELECT COUNT(*) FROM quote_ident(tablename)will always return 1 because it's not part of your dynamic sql statement. You are selecting the count of literally calling that function, rather than selecting a count from a table, and that function returns one row.