@@ -147,7 +147,7 @@ const char * const SQL_SITEID_SELECT_ROWID0 =
147147 "SELECT site_id FROM cloudsync_site_id WHERE id = 0;" ;
148148
149149const char * const SQL_DATA_VERSION =
150- "SELECT 1 " ; // TODO: PostgreSQL equivalent of sqlite "PRAGMA data_version", "SELECT txid_current();" is not equivalent
150+ "SELECT SELECT txid_snapshot_xmin(txid_current_snapshot()); " ; // was "PRAGMA data_version"
151151
152152const char * const SQL_SCHEMA_VERSION =
153153 "SELECT 1;" ; // TODO: PostgreSQL equivalent of sqlite "PRAGMA schema_version", "SELECT current_schema();" is not equivalent
@@ -165,27 +165,40 @@ const char * const SQL_BUILD_SELECT_NONPK_COLS_BY_ROWID =
165165 "WHERE table_name = $1 AND constraint_name LIKE '%_pkey'"
166166 ");" ; // TODO: build full SELECT ... WHERE ctid=? analog with ordered columns like SQLite
167167
168- const char * const SQL_BUILD_SELECT_NONPK_COLS_BY_PK =
169- "WITH nonpk AS ("
170- " SELECT string_agg(quote_ident(column_name), ',' ORDER BY ordinal_position) AS cols "
171- " FROM information_schema.columns "
172- " WHERE table_schema = current_schema() AND table_name = '%s' AND ordinal_position NOT IN ("
173- " SELECT ordinal_position FROM information_schema.columns c "
174- " WHERE table_schema = current_schema() AND table_name = '%s' AND column_name IN ("
175- " SELECT column_name FROM information_schema.key_column_usage "
176- " WHERE table_schema = current_schema() AND table_name = '%s' AND constraint_name LIKE '%%_pkey'"
177- " )"
178- " )"
179- "), pk_cols AS ("
180- " SELECT column_name, row_number() OVER (ORDER BY position_in_unique_constraint) AS rn "
181- " FROM information_schema.key_column_usage "
182- " WHERE table_schema = current_schema() AND table_name = '%s' AND constraint_name LIKE '%%_pkey'"
183- "), pk AS ("
184- " SELECT string_agg(quote_ident(column_name) || ' = $' || rn, ' AND ' ORDER BY rn) AS clause "
185- " FROM pk_cols"
168+ const char * const SQL_BUILD_SELECT_NONPK_COLS_BY_PK_PG =
169+ "WITH tbl AS ("
170+ " SELECT to_regclass(%L) AS oid"
171+ "), "
172+ "pk AS ("
173+ " SELECT a.attname, k.ord "
174+ " FROM pg_index x "
175+ " JOIN tbl t ON t.oid = x.indrelid "
176+ " JOIN LATERAL unnest(x.indkey) WITH ORDINALITY AS k(attnum, ord) ON true "
177+ " JOIN pg_attribute a ON a.attrelid = x.indrelid AND a.attnum = k.attnum "
178+ " WHERE x.indisprimary "
179+ " ORDER BY k.ord"
180+ "), "
181+ "nonpk AS ("
182+ " SELECT a.attname "
183+ " FROM pg_attribute a "
184+ " JOIN tbl t ON t.oid = a.attrelid "
185+ " WHERE a.attnum > 0 AND NOT a.attisdropped "
186+ " AND a.attnum NOT IN ("
187+ " SELECT k.attnum "
188+ " FROM pg_index x "
189+ " JOIN tbl t2 ON t2.oid = x.indrelid "
190+ " JOIN LATERAL unnest(x.indkey) AS k(attnum) ON true "
191+ " WHERE x.indisprimary"
192+ " ) "
193+ " ORDER BY a.attnum"
186194 ") "
187- "SELECT 'SELECT ' || COALESCE((SELECT cols FROM nonpk), '*') || ' FROM ' || quote_ident('%s') || ' WHERE ' || clause || ';' "
188- "FROM pk;" ; // Generates full SELECT with ordered non-PK columns and PK WHERE clause for cloudsync_memory_mprintf
195+ "SELECT "
196+ " 'SELECT '"
197+ " || (SELECT string_agg(format('%%I', attname), ',') FROM nonpk)"
198+ " || ' FROM ' || (SELECT (oid::regclass)::text FROM tbl)"
199+ " || ' WHERE '"
200+ " || (SELECT string_agg(format('%%I=?', attname), ' AND ') FROM pk)"
201+ " || ';';" ;
189202
190203const char * const SQL_DELETE_ROW_BY_ROWID =
191204 "DELETE FROM %s WHERE ctid = $1;" ; // TODO: consider using PK-based deletion; ctid is unstable
0 commit comments