@powersync/service-module-postgres 0.19.3 → 0.19.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/api/PostgresRouteAPIAdapter.d.ts +1 -1
  2. package/dist/api/PostgresRouteAPIAdapter.js +63 -72
  3. package/dist/api/PostgresRouteAPIAdapter.js.map +1 -1
  4. package/dist/module/PostgresModule.js.map +1 -1
  5. package/dist/replication/MissingReplicationSlotError.d.ts +41 -0
  6. package/dist/replication/MissingReplicationSlotError.js +33 -0
  7. package/dist/replication/MissingReplicationSlotError.js.map +1 -0
  8. package/dist/replication/PostgresErrorRateLimiter.js +1 -1
  9. package/dist/replication/PostgresErrorRateLimiter.js.map +1 -1
  10. package/dist/replication/SnapshotQuery.js +2 -2
  11. package/dist/replication/SnapshotQuery.js.map +1 -1
  12. package/dist/replication/WalStream.d.ts +35 -3
  13. package/dist/replication/WalStream.js +135 -9
  14. package/dist/replication/WalStream.js.map +1 -1
  15. package/dist/replication/WalStreamReplicationJob.js +6 -3
  16. package/dist/replication/WalStreamReplicationJob.js.map +1 -1
  17. package/dist/replication/replication-index.d.ts +3 -1
  18. package/dist/replication/replication-index.js +3 -1
  19. package/dist/replication/replication-index.js.map +1 -1
  20. package/dist/replication/replication-utils.d.ts +3 -11
  21. package/dist/replication/replication-utils.js +101 -164
  22. package/dist/replication/replication-utils.js.map +1 -1
  23. package/dist/replication/wal-budget-utils.d.ts +23 -0
  24. package/dist/replication/wal-budget-utils.js +57 -0
  25. package/dist/replication/wal-budget-utils.js.map +1 -0
  26. package/dist/types/registry.js +1 -1
  27. package/dist/types/registry.js.map +1 -1
  28. package/package.json +15 -11
  29. package/sql/check-source-configuration.plpgsql +13 -0
  30. package/sql/debug-tables-info-batched.plpgsql +230 -0
  31. package/CHANGELOG.md +0 -858
  32. package/src/api/PostgresRouteAPIAdapter.ts +0 -356
  33. package/src/index.ts +0 -1
  34. package/src/module/PostgresModule.ts +0 -122
  35. package/src/replication/ConnectionManagerFactory.ts +0 -33
  36. package/src/replication/PgManager.ts +0 -122
  37. package/src/replication/PgRelation.ts +0 -41
  38. package/src/replication/PostgresErrorRateLimiter.ts +0 -48
  39. package/src/replication/SnapshotQuery.ts +0 -213
  40. package/src/replication/WalStream.ts +0 -1137
  41. package/src/replication/WalStreamReplicationJob.ts +0 -138
  42. package/src/replication/WalStreamReplicator.ts +0 -53
  43. package/src/replication/replication-index.ts +0 -5
  44. package/src/replication/replication-utils.ts +0 -398
  45. package/src/types/registry.ts +0 -275
  46. package/src/types/resolver.ts +0 -227
  47. package/src/types/types.ts +0 -44
  48. package/src/utils/application-name.ts +0 -8
  49. package/src/utils/migration_lib.ts +0 -80
  50. package/src/utils/populate_test_data.ts +0 -37
  51. package/src/utils/populate_test_data_worker.ts +0 -53
  52. package/src/utils/postgres_version.ts +0 -8
  53. package/test/src/checkpoints.test.ts +0 -86
  54. package/test/src/chunked_snapshots.test.ts +0 -161
  55. package/test/src/env.ts +0 -11
  56. package/test/src/large_batch.test.ts +0 -241
  57. package/test/src/pg_test.test.ts +0 -729
  58. package/test/src/resuming_snapshots.test.ts +0 -160
  59. package/test/src/route_api_adapter.test.ts +0 -62
  60. package/test/src/schema_changes.test.ts +0 -655
  61. package/test/src/setup.ts +0 -12
  62. package/test/src/slow_tests.test.ts +0 -519
  63. package/test/src/storage_combination.test.ts +0 -35
  64. package/test/src/types/registry.test.ts +0 -149
  65. package/test/src/util.ts +0 -151
  66. package/test/src/validation.test.ts +0 -63
  67. package/test/src/wal_stream.test.ts +0 -607
  68. package/test/src/wal_stream_utils.ts +0 -284
  69. package/test/tsconfig.json +0 -27
  70. package/tsconfig.json +0 -34
  71. package/tsconfig.tsbuildinfo +0 -1
  72. package/vitest.config.ts +0 -3
@@ -0,0 +1,230 @@
1
+ DO $$
2
+ DECLARE
3
+ input_patterns jsonb := current_setting('powersync.debug.table_patterns', true)::jsonb;
4
+ current_publication text := current_setting('powersync.debug.publication_name', true);
5
+ select_probe_results jsonb := '[]'::jsonb;
6
+ debug_cursor refcursor := 'powersync_debug_tables_cursor';
7
+ select_target record;
8
+ BEGIN
9
+ -- Capture per-table read failures without aborting the whole batch.
10
+ FOR select_target IN
11
+ WITH patterns AS (
12
+ SELECT *
13
+ FROM jsonb_to_recordset(input_patterns) AS p(
14
+ pattern_ord int,
15
+ schema_name text,
16
+ table_pattern text,
17
+ is_wildcard boolean,
18
+ table_prefix text,
19
+ input_name text
20
+ )
21
+ )
22
+ SELECT
23
+ p.pattern_ord,
24
+ p.schema_name,
25
+ c.relname AS table_name,
26
+ c.oid::int8 AS relid
27
+ FROM patterns p
28
+ JOIN pg_namespace n ON n.nspname = p.schema_name
29
+ JOIN pg_class c ON c.relnamespace = n.oid
30
+ WHERE c.relkind = 'r'
31
+ AND (
32
+ (p.is_wildcard AND c.relname LIKE p.table_pattern AND left(c.relname, length(p.table_prefix)) = p.table_prefix)
33
+ OR
34
+ (NOT p.is_wildcard AND c.relname = p.table_pattern)
35
+ )
36
+ ORDER BY p.pattern_ord, c.relname
37
+ LOOP
38
+ BEGIN
39
+ -- Query a single row from each table, to confirm that we can query the table
40
+ -- (no permission errors)
41
+ -- %I covers identifier escaping
42
+ EXECUTE format('SELECT 1 FROM %I.%I LIMIT 1', select_target.schema_name, select_target.table_name);
43
+ select_probe_results := select_probe_results || jsonb_build_array(
44
+ jsonb_build_object(
45
+ 'pattern_ord', select_target.pattern_ord,
46
+ 'relid', select_target.relid,
47
+ 'message', NULL
48
+ )
49
+ );
50
+ EXCEPTION WHEN OTHERS THEN
51
+ select_probe_results := select_probe_results || jsonb_build_array(
52
+ jsonb_build_object(
53
+ 'pattern_ord', select_target.pattern_ord,
54
+ 'relid', select_target.relid,
55
+ 'message', SQLERRM
56
+ )
57
+ );
58
+ END;
59
+ END LOOP;
60
+
61
+ -- OPEN debug_cursor to allow returning results
62
+ OPEN debug_cursor FOR
63
+ WITH patterns AS (
64
+ -- Rehydrate the requested patterns once for the bulk metadata pass.
65
+ SELECT *
66
+ FROM jsonb_to_recordset(input_patterns) AS p(
67
+ pattern_ord int,
68
+ schema_name text,
69
+ table_pattern text,
70
+ is_wildcard boolean,
71
+ table_prefix text,
72
+ input_name text
73
+ )
74
+ ),
75
+ matched AS (
76
+ -- Expand each requested pattern to the concrete tables that exist.
77
+ SELECT
78
+ p.pattern_ord,
79
+ p.schema_name,
80
+ p.table_pattern,
81
+ p.is_wildcard,
82
+ p.input_name,
83
+ c.relid,
84
+ c.table_name,
85
+ c.relreplident,
86
+ c.relrowsecurity
87
+ FROM patterns p
88
+ LEFT JOIN LATERAL (
89
+ SELECT
90
+ c.oid::int8 AS relid,
91
+ c.relname AS table_name,
92
+ c.relreplident,
93
+ c.relrowsecurity
94
+ FROM pg_namespace n
95
+ JOIN pg_class c ON c.relnamespace = n.oid
96
+ WHERE n.nspname = p.schema_name
97
+ AND c.relkind = 'r'
98
+ AND (
99
+ (p.is_wildcard AND c.relname LIKE p.table_pattern AND left(c.relname, length(p.table_prefix)) = p.table_prefix)
100
+ OR
101
+ (NOT p.is_wildcard AND c.relname = p.table_pattern)
102
+ )
103
+ ORDER BY c.relname
104
+ ) c ON true
105
+ WHERE NOT p.is_wildcard OR c.relid IS NOT NULL
106
+ ),
107
+ existing AS (
108
+ -- Deduplicate matched tables while carrying the pg_class metadata we already have.
109
+ SELECT DISTINCT
110
+ relid::oid AS relid,
111
+ CASE relreplident
112
+ WHEN 'd' THEN 'default'
113
+ WHEN 'n' THEN 'nothing'
114
+ WHEN 'f' THEN 'full'
115
+ WHEN 'i' THEN 'index'
116
+ END AS replication_identity,
117
+ relrowsecurity AS rls_enabled
118
+ FROM matched
119
+ WHERE relid IS NOT NULL
120
+ ),
121
+ replication_columns AS (
122
+ -- Resolve the actual replication-id columns for default/index/full modes.
123
+ SELECT
124
+ e.relid,
125
+ a.attname AS name,
126
+ a.attnum AS attnum
127
+ FROM existing e
128
+ JOIN pg_index i ON i.indrelid = e.relid AND i.indisprimary
129
+ JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
130
+ WHERE e.replication_identity = 'default' AND a.attnum > 0
131
+
132
+ UNION ALL
133
+
134
+ SELECT
135
+ e.relid,
136
+ a.attname AS name,
137
+ a.attnum AS attnum
138
+ FROM existing e
139
+ JOIN pg_index i ON i.indrelid = e.relid AND i.indisreplident
140
+ JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
141
+ WHERE e.replication_identity = 'index' AND a.attnum > 0
142
+
143
+ UNION ALL
144
+
145
+ SELECT
146
+ e.relid,
147
+ a.attname AS name,
148
+ a.attnum AS attnum
149
+ FROM existing e
150
+ JOIN pg_attribute a ON a.attrelid = e.relid
151
+ WHERE e.replication_identity = 'full' AND a.attnum > 0
152
+ ),
153
+ publication_membership AS (
154
+ -- Check publication membership in bulk instead of once per table.
155
+ SELECT
156
+ m.pattern_ord,
157
+ m.relid
158
+ FROM matched m
159
+ JOIN pg_publication_tables p
160
+ ON p.pubname = current_publication
161
+ AND p.schemaname = m.schema_name
162
+ AND p.tablename = m.table_name
163
+ WHERE m.relid IS NOT NULL
164
+ ),
165
+ user_info AS (
166
+ -- Current-role capabilities are constant across all tables in this batch.
167
+ SELECT
168
+ current_user AS username,
169
+ r.rolsuper AS is_superuser,
170
+ r.rolbypassrls AS bypasses_rls
171
+ FROM pg_roles r
172
+ WHERE r.rolname = current_user
173
+ ),
174
+ rls_check AS (
175
+ -- Pair role capabilities with the row-security metadata already carried from pg_class.
176
+ SELECT
177
+ e.relid::int8 AS relid,
178
+ e.rls_enabled,
179
+ u.username,
180
+ u.is_superuser,
181
+ u.bypasses_rls
182
+ FROM existing e
183
+ CROSS JOIN user_info u
184
+ ),
185
+ select_probes AS (
186
+ -- Rehydrate the recorded SELECT probe failures for the final result set.
187
+ SELECT *
188
+ FROM jsonb_to_recordset(select_probe_results) AS s(
189
+ pattern_ord int,
190
+ relid int8,
191
+ message text
192
+ )
193
+ )
194
+ SELECT
195
+ m.pattern_ord,
196
+ m.schema_name,
197
+ COALESCE(m.table_name, m.input_name) AS name,
198
+ m.relid AS relation_id,
199
+ e.replication_identity,
200
+ COALESCE(
201
+ jsonb_agg(rc.name ORDER BY rc.attnum) FILTER (WHERE rc.name IS NOT NULL),
202
+ '[]'::jsonb
203
+ )::text AS replication_id_json,
204
+ sp.message AS select_error,
205
+ (pm.relid IS NOT NULL) AS in_publication,
206
+ rls.rls_enabled,
207
+ rls.username,
208
+ rls.is_superuser,
209
+ rls.bypasses_rls
210
+ FROM matched m
211
+ LEFT JOIN existing e ON e.relid = m.relid
212
+ LEFT JOIN replication_columns rc ON rc.relid = m.relid
213
+ LEFT JOIN publication_membership pm ON pm.pattern_ord = m.pattern_ord AND pm.relid = m.relid
214
+ LEFT JOIN rls_check rls ON rls.relid = m.relid
215
+ LEFT JOIN select_probes sp ON sp.pattern_ord = m.pattern_ord AND sp.relid = m.relid
216
+ GROUP BY
217
+ m.pattern_ord,
218
+ m.schema_name,
219
+ COALESCE(m.table_name, m.input_name),
220
+ m.relid,
221
+ e.replication_identity,
222
+ sp.message,
223
+ pm.relid,
224
+ rls.rls_enabled,
225
+ rls.username,
226
+ rls.is_superuser,
227
+ rls.bypasses_rls
228
+ ORDER BY m.pattern_ord, COALESCE(m.table_name, m.input_name);
229
+ END
230
+ $$