torque-postgresql 4.0.0.rc1 → 4.0.0
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.
- checksums.yaml +4 -4
- data/lib/generators/torque/function_generator.rb +13 -0
- data/lib/generators/torque/templates/function.sql.erb +4 -0
- data/lib/generators/torque/templates/type.sql.erb +2 -0
- data/lib/generators/torque/templates/view.sql.erb +3 -0
- data/lib/generators/torque/type_generator.rb +13 -0
- data/lib/generators/torque/view_generator.rb +16 -0
- data/lib/torque/postgresql/adapter/database_statements.rb +48 -10
- data/lib/torque/postgresql/adapter/schema_definitions.rb +22 -0
- data/lib/torque/postgresql/adapter/schema_dumper.rb +47 -1
- data/lib/torque/postgresql/adapter/schema_statements.rb +45 -0
- data/lib/torque/postgresql/arel/nodes.rb +14 -0
- data/lib/torque/postgresql/arel/visitors.rb +4 -0
- data/lib/torque/postgresql/attributes/builder/full_text_search.rb +16 -28
- data/lib/torque/postgresql/base.rb +2 -1
- data/lib/torque/postgresql/config.rb +35 -1
- data/lib/torque/postgresql/function.rb +33 -0
- data/lib/torque/postgresql/railtie.rb +26 -1
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +7 -2
- data/lib/torque/postgresql/relation/buckets.rb +124 -0
- data/lib/torque/postgresql/relation/distinct_on.rb +7 -2
- data/lib/torque/postgresql/relation/inheritance.rb +18 -8
- data/lib/torque/postgresql/relation/join_series.rb +112 -0
- data/lib/torque/postgresql/relation/merger.rb +17 -3
- data/lib/torque/postgresql/relation.rb +18 -28
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/postgresql/versioned_commands/command_migration.rb +146 -0
- data/lib/torque/postgresql/versioned_commands/generator.rb +57 -0
- data/lib/torque/postgresql/versioned_commands/migration_context.rb +83 -0
- data/lib/torque/postgresql/versioned_commands/migrator.rb +39 -0
- data/lib/torque/postgresql/versioned_commands/schema_table.rb +101 -0
- data/lib/torque/postgresql/versioned_commands.rb +161 -0
- data/spec/fixtures/migrations/20250101000001_create_users.rb +0 -0
- data/spec/fixtures/migrations/20250101000002_create_function_count_users_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000003_create_internal_users.rb +0 -0
- data/spec/fixtures/migrations/20250101000004_update_function_count_users_v2.sql +0 -0
- data/spec/fixtures/migrations/20250101000005_create_view_all_users_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000006_create_type_user_id_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000007_remove_function_count_users_v2.sql +0 -0
- data/spec/initialize.rb +9 -0
- data/spec/schema.rb +2 -4
- data/spec/spec_helper.rb +6 -1
- data/spec/tests/full_text_seach_test.rb +30 -2
- data/spec/tests/relation_spec.rb +229 -0
- data/spec/tests/schema_spec.rb +4 -1
- data/spec/tests/versioned_commands_spec.rb +513 -0
- metadata +33 -3
@@ -0,0 +1,513 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'VersionedCommands' do
|
4
|
+
let(:connection) { ActiveRecord::Base.connection }
|
5
|
+
|
6
|
+
context 'on migration' do
|
7
|
+
it 'does not have any of the schema methods' do
|
8
|
+
expect(connection).not_to respond_to(:create_function)
|
9
|
+
expect(connection).not_to respond_to(:create_type)
|
10
|
+
expect(connection).not_to respond_to(:create_view)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'does not have the methods available in a migration' do
|
14
|
+
instance = Class.new(ActiveRecord::Migration::Current).allocate
|
15
|
+
expect(instance).not_to respond_to(:create_function)
|
16
|
+
expect(instance).not_to respond_to(:create_type)
|
17
|
+
expect(instance).not_to respond_to(:create_view)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does have the methods in schema definition' do
|
21
|
+
instance = ActiveRecord::Schema[ActiveRecord::Migration.current_version].allocate
|
22
|
+
expect(instance).to respond_to(:create_function)
|
23
|
+
expect(instance).to respond_to(:create_type)
|
24
|
+
expect(instance).to respond_to(:create_view)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'on context' do
|
28
|
+
let(:context) { connection.pool.migration_context }
|
29
|
+
let(:path) { Pathname.new(__FILE__).join('../../fixtures/migrations').expand_path.to_s }
|
30
|
+
|
31
|
+
before { context.instance_variable_set(:@migrations_paths, [path]) }
|
32
|
+
|
33
|
+
it 'list all migrations accordingly' do
|
34
|
+
result = context.migrations.map { |m| File.basename(m.filename) }
|
35
|
+
expect(result[0]).to eq('20250101000001_create_users.rb')
|
36
|
+
expect(result[1]).to eq('20250101000002_create_function_count_users_v1.sql')
|
37
|
+
expect(result[2]).to eq('20250101000003_create_internal_users.rb')
|
38
|
+
expect(result[3]).to eq('20250101000004_update_function_count_users_v2.sql')
|
39
|
+
expect(result[4]).to eq('20250101000005_create_view_all_users_v1.sql')
|
40
|
+
expect(result[5]).to eq('20250101000006_create_type_user_id_v1.sql')
|
41
|
+
expect(result[6]).to eq('20250101000007_remove_function_count_users_v2.sql')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'correctly report the status of all migrations' do
|
45
|
+
result = context.migrations_status.reject { |s| s[1].start_with?('0') }
|
46
|
+
expect(result[0]).to eq(['down', '20250101000001', 'Create users'])
|
47
|
+
expect(result[1]).to eq(['down', '20250101000002', 'Create Function count_users (v1)'])
|
48
|
+
expect(result[2]).to eq(['down', '20250101000003', 'Create internal users'])
|
49
|
+
expect(result[3]).to eq(['down', '20250101000004', 'Update Function count_users (v2)'])
|
50
|
+
expect(result[4]).to eq(['down', '20250101000005', 'Create View all_users (v1)'])
|
51
|
+
expect(result[5]).to eq(['down', '20250101000006', 'Create Type user_id (v1)'])
|
52
|
+
expect(result[6]).to eq(['down', '20250101000007', 'Remove Function count_users (v2)'])
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'reports for invalid names' do
|
56
|
+
allow(context).to receive(:command_files).and_return(['something.sql'])
|
57
|
+
error = ::Torque::PostgreSQL::IllegalCommandTypeError
|
58
|
+
expect { context.migrations }.to raise_error(error)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'on validation' do
|
63
|
+
let(:base) { Torque::PostgreSQL::VersionedCommands }
|
64
|
+
|
65
|
+
context 'on function' do
|
66
|
+
it 'prevents multiple functions definition' do
|
67
|
+
content = <<~SQL
|
68
|
+
CREATE FUNCTION test(a integer);
|
69
|
+
CREATE FUNCTION other_test(a varchar);
|
70
|
+
SQL
|
71
|
+
|
72
|
+
expect do
|
73
|
+
base.validate!(:function, content, 'test')
|
74
|
+
end.to raise_error(ArgumentError)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'prevents same name but different schema' do
|
78
|
+
content = <<~SQL
|
79
|
+
CREATE FUNCTION internal.test(a integer);
|
80
|
+
CREATE FUNCTION external.test(a varchar);
|
81
|
+
SQL
|
82
|
+
|
83
|
+
expect do
|
84
|
+
base.validate!(:function, content, 'test')
|
85
|
+
end.to raise_error(ArgumentError)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'requires OR REPLACE clause' do
|
89
|
+
content = <<~SQL
|
90
|
+
CREATE OR REPLACE FUNCTION test(a integer);
|
91
|
+
CREATE FUNCTION test(a varchar);
|
92
|
+
SQL
|
93
|
+
|
94
|
+
expect do
|
95
|
+
base.validate!(:function, content, 'test')
|
96
|
+
end.to raise_error(ArgumentError)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'requires matching name' do
|
100
|
+
content = <<~SQL
|
101
|
+
CREATE OR REPLACE FUNCTION other_test(a integer);
|
102
|
+
CREATE OR REPLACE FUNCTION other_test(a varchar);
|
103
|
+
SQL
|
104
|
+
|
105
|
+
expect do
|
106
|
+
base.validate!(:function, content, 'test')
|
107
|
+
end.to raise_error(ArgumentError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'works when setup correctly' do
|
111
|
+
content = <<~SQL
|
112
|
+
CREATE OR REPLACE FUNCTION test(a integer);
|
113
|
+
CREATE OR REPLACE FUNCTION test(a varchar);
|
114
|
+
CREATE OR REPLACE FUNCTION TEST(a date);
|
115
|
+
SQL
|
116
|
+
|
117
|
+
expect { base.validate!(:function, content, 'test') }.not_to raise_error
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'supports name with schema' do
|
121
|
+
content = <<~SQL
|
122
|
+
CREATE OR REPLACE FUNCTION internal.test(a integer);
|
123
|
+
CREATE OR REPLACE FUNCTION internal.test(a varchar);
|
124
|
+
CREATE OR REPLACE FUNCTION internal.TEST(a date);
|
125
|
+
SQL
|
126
|
+
|
127
|
+
expect { base.validate!(:function, content, 'internal_test') }.not_to raise_error
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'on type' do
|
132
|
+
it 'prevents multiple type definitions' do
|
133
|
+
content = <<~SQL
|
134
|
+
CREATE TYPE test AS;
|
135
|
+
CREATE TYPE other_test AS;
|
136
|
+
SQL
|
137
|
+
|
138
|
+
expect do
|
139
|
+
base.validate!(:type, content, 'test')
|
140
|
+
end.to raise_error(ArgumentError)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'prevents same name but different schema' do
|
144
|
+
content = <<~SQL
|
145
|
+
DROP TYPE IF EXISTS internal.test;
|
146
|
+
CREATE TYPE external.test AS;
|
147
|
+
SQL
|
148
|
+
|
149
|
+
expect do
|
150
|
+
base.validate!(:type, content, 'test')
|
151
|
+
end.to raise_error(ArgumentError)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'prevents multiple type drops' do
|
155
|
+
content = <<~SQL
|
156
|
+
DROP TYPE IF EXISTS test;
|
157
|
+
DROP TYPE IF EXISTS other_test;
|
158
|
+
CREATE TYPE test AS;
|
159
|
+
SQL
|
160
|
+
|
161
|
+
expect do
|
162
|
+
base.validate!(:type, content, 'test')
|
163
|
+
end.to raise_error(ArgumentError)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'requires DROP TYPE clause' do
|
167
|
+
content = <<~SQL
|
168
|
+
CREATE TYPE test AS;
|
169
|
+
SQL
|
170
|
+
|
171
|
+
expect do
|
172
|
+
base.validate!(:type, content, 'test')
|
173
|
+
end.to raise_error(ArgumentError)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'prevents dropping other types' do
|
177
|
+
content = <<~SQL
|
178
|
+
DROP TYPE IF EXISTS other_test;
|
179
|
+
CREATE TYPE test AS;
|
180
|
+
SQL
|
181
|
+
|
182
|
+
expect do
|
183
|
+
base.validate!(:type, content, 'test')
|
184
|
+
end.to raise_error(ArgumentError)
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'requires matching name' do
|
188
|
+
content = <<~SQL
|
189
|
+
DROP TYPE IF EXISTS other_test;
|
190
|
+
CREATE TYPE other_test AS;
|
191
|
+
SQL
|
192
|
+
|
193
|
+
expect do
|
194
|
+
base.validate!(:type, content, 'test')
|
195
|
+
end.to raise_error(ArgumentError)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'works when setup correctly' do
|
199
|
+
content = <<~SQL
|
200
|
+
DROP TYPE IF EXISTS test;
|
201
|
+
CREATE TYPE TEST AS;
|
202
|
+
SQL
|
203
|
+
|
204
|
+
expect { base.validate!(:type, content, 'test') }.not_to raise_error
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'supports name with schema' do
|
208
|
+
content = <<~SQL
|
209
|
+
DROP TYPE IF EXISTS internal.test;
|
210
|
+
CREATE TYPE INTERNAL.TEST AS;
|
211
|
+
SQL
|
212
|
+
|
213
|
+
expect { base.validate!(:type, content, 'internal_test') }.not_to raise_error
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'on view' do
|
218
|
+
it 'requires a proper definition' do
|
219
|
+
content = <<~SQL
|
220
|
+
CREATE TEMP MATERIALIZED VIEW test AS;
|
221
|
+
SQL
|
222
|
+
|
223
|
+
expect do
|
224
|
+
base.validate!(:view, content, 'test')
|
225
|
+
end.to raise_error(ArgumentError)
|
226
|
+
end
|
227
|
+
it 'prevents multiple view definitions' do
|
228
|
+
content = <<~SQL
|
229
|
+
CREATE VIEW test AS;
|
230
|
+
CREATE VIEW other_test AS;
|
231
|
+
SQL
|
232
|
+
|
233
|
+
expect do
|
234
|
+
base.validate!(:view, content, 'test')
|
235
|
+
end.to raise_error(ArgumentError)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'requires OR REPLACE clause' do
|
239
|
+
content = <<~SQL
|
240
|
+
CREATE VIEW test AS;
|
241
|
+
SQL
|
242
|
+
|
243
|
+
expect do
|
244
|
+
base.validate!(:view, content, 'test')
|
245
|
+
end.to raise_error(ArgumentError)
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'requires matching name' do
|
249
|
+
content = <<~SQL
|
250
|
+
CREATE OR REPLACE VIEW other_test AS;
|
251
|
+
SQL
|
252
|
+
|
253
|
+
expect do
|
254
|
+
base.validate!(:view, content, 'test')
|
255
|
+
end.to raise_error(ArgumentError)
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'works when setup correctly' do
|
259
|
+
content = <<~SQL
|
260
|
+
CREATE OR REPLACE VIEW TEST AS;
|
261
|
+
SQL
|
262
|
+
|
263
|
+
expect { base.validate!(:view, content, 'test') }.not_to raise_error
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'supports materialized views' do
|
267
|
+
content = <<~SQL
|
268
|
+
DROP MATERIALIZED VIEW IF EXISTS test;
|
269
|
+
CREATE MATERIALIZED VIEW test AS;
|
270
|
+
SQL
|
271
|
+
|
272
|
+
expect { base.validate!(:view, content, 'test') }.not_to raise_error
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'supports name with schema' do
|
276
|
+
content = <<~SQL
|
277
|
+
CREATE OR REPLACE VIEW internal.test AS;
|
278
|
+
SQL
|
279
|
+
|
280
|
+
expect { base.validate!(:view, content, 'internal_test') }.not_to raise_error
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'on running' do
|
286
|
+
let(:base) { Torque::PostgreSQL::VersionedCommands }
|
287
|
+
let(:sql) { 'CREATE TYPE test;' }
|
288
|
+
let(:command) do
|
289
|
+
base::CommandMigration.new('test.sql', 1, 'create', 'type', 'test', 1)
|
290
|
+
end
|
291
|
+
|
292
|
+
before do
|
293
|
+
allow_any_instance_of(ActiveRecord::Migration).to receive(:puts) # Disable messages
|
294
|
+
|
295
|
+
allow(File).to receive(:expand_path, &:itself)
|
296
|
+
allow(File).to receive(:read).with('test.sql').and_return(sql)
|
297
|
+
|
298
|
+
# Validations are better tested above
|
299
|
+
allow(base).to receive(:validate!).and_return(true)
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'has the right name' do
|
303
|
+
expect(command.name).to eq('create_type_test_v1')
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'creates the type properly' do
|
307
|
+
expect(connection).to receive(:execute).with(sql)
|
308
|
+
command.migrate(:up)
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'reverts to the previous file' do
|
312
|
+
sql2 = 'CREATE TYPE test_v1;'
|
313
|
+
command.op_version = 2
|
314
|
+
expect(base).to receive(:fetch_command).with(Array, 'type', 'test', 1).and_return(sql2)
|
315
|
+
expect(connection).to receive(:execute).with(sql2)
|
316
|
+
command.migrate(:down)
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'reverts to the same version when reverting a remove' do
|
320
|
+
command.op = 'remove'
|
321
|
+
command.op_version = 2
|
322
|
+
expect(base).to receive(:fetch_command).with(Array, 'type', 'test', 2).and_return(sql)
|
323
|
+
expect(connection).to receive(:execute).with(sql)
|
324
|
+
command.migrate(:down)
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'properly drops functions' do
|
328
|
+
command.type = 'function'
|
329
|
+
|
330
|
+
sql.replace('CREATE FUNCTION test;')
|
331
|
+
expect(connection).to receive(:execute).with('DROP FUNCTION test;')
|
332
|
+
command.migrate(:down)
|
333
|
+
|
334
|
+
sql.replace('CREATE FUNCTION test();')
|
335
|
+
expect(connection).to receive(:execute).with('DROP FUNCTION test();')
|
336
|
+
command.migrate(:down)
|
337
|
+
|
338
|
+
sql.replace('CREATE FUNCTION test(int); CREATE FUNCTION test(float);')
|
339
|
+
expect(connection).to receive(:execute).with('DROP FUNCTION test(int), test(float);')
|
340
|
+
command.migrate(:down)
|
341
|
+
end
|
342
|
+
|
343
|
+
it 'properly drops types' do
|
344
|
+
command.type = 'type'
|
345
|
+
|
346
|
+
sql.replace('CREATE TYPE test;')
|
347
|
+
expect(connection).to receive(:execute).with('DROP TYPE test;')
|
348
|
+
command.migrate(:down)
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'properly drops views' do
|
352
|
+
command.type = 'view'
|
353
|
+
|
354
|
+
sql.replace('CREATE VIEW test AS SELECT 1;')
|
355
|
+
expect(connection).to receive(:execute).with('DROP VIEW test;')
|
356
|
+
command.migrate(:down)
|
357
|
+
|
358
|
+
sql.replace('CREATE MATERIALIZED VIEW test AS SELECT 1;')
|
359
|
+
expect(connection).to receive(:execute).with('DROP MATERIALIZED VIEW test;')
|
360
|
+
command.migrate(:down)
|
361
|
+
|
362
|
+
sql.replace('CREATE RECURSIVE VIEW test AS SELECT 1;')
|
363
|
+
expect(connection).to receive(:execute).with('DROP VIEW test;')
|
364
|
+
command.migrate(:down)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
context 'on migrator' do
|
369
|
+
let(:base) { Torque::PostgreSQL::VersionedCommands }
|
370
|
+
let(:table) { base::SchemaTable.new(connection.pool) }
|
371
|
+
let(:context) { connection.pool.migration_context }
|
372
|
+
let(:versions) { migrations.map(&:version).map(&:to_i) }
|
373
|
+
let(:migrations) { [ActiveRecord::Migration.new('base', 1)] }
|
374
|
+
|
375
|
+
before do
|
376
|
+
allow_any_instance_of(ActiveRecord::Migration).to receive(:puts) # Disable messages
|
377
|
+
allow(File).to receive(:expand_path, &:itself)
|
378
|
+
|
379
|
+
# Validations are better tested above
|
380
|
+
allow(base).to receive(:validate!).and_return(true)
|
381
|
+
allow(context).to receive(:migrations).and_return(migrations)
|
382
|
+
allow(context.schema_migration).to receive(:integer_versions).and_return(versions)
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'expect the table to not exist by default' do
|
386
|
+
expect(table.table_exists?).to be_falsey
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'creates the table on first migration' do
|
390
|
+
migration('CREATE TYPE test;')
|
391
|
+
|
392
|
+
expect(table.table_exists?).to be_falsey
|
393
|
+
context.up(2)
|
394
|
+
expect(table.table_exists?).to be_truthy
|
395
|
+
expect(table.count).to eq(1)
|
396
|
+
expect(table.versions_of('type')).to eq([['test_2', 1]])
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'drops the table if all versions are removed' do
|
400
|
+
migrations << ActiveRecord::Migration.new('other', 2)
|
401
|
+
versions << 2
|
402
|
+
|
403
|
+
migration('CREATE TYPE test;')
|
404
|
+
|
405
|
+
expect(table.table_exists?).to be_falsey
|
406
|
+
context.up(3)
|
407
|
+
expect(table.table_exists?).to be_truthy
|
408
|
+
expect(table.count).to eq(1)
|
409
|
+
|
410
|
+
versions << 3
|
411
|
+
context.down(2)
|
412
|
+
expect(table.table_exists?).to be_falsey
|
413
|
+
expect(table.count).to eq(0)
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'does no drop the table if there are still records' do
|
417
|
+
migration('CREATE TYPE test;')
|
418
|
+
migration('CREATE TYPE other;')
|
419
|
+
|
420
|
+
expect(table.table_exists?).to be_falsey
|
421
|
+
context.up(3)
|
422
|
+
expect(table.table_exists?).to be_truthy
|
423
|
+
expect(table.count).to eq(2)
|
424
|
+
|
425
|
+
versions << 2
|
426
|
+
versions << 3
|
427
|
+
context.down(2)
|
428
|
+
expect(table.table_exists?).to be_truthy
|
429
|
+
expect(table.count).to eq(1)
|
430
|
+
end
|
431
|
+
|
432
|
+
def migration(command)
|
433
|
+
version = migrations.size + 1
|
434
|
+
file = "test_#{version}.sql"
|
435
|
+
name = file.split('.').first
|
436
|
+
allow(File).to receive(:read).with(file).and_return(command)
|
437
|
+
migrations << base::CommandMigration.new(file, version, 'create', 'type', name, 1)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
context 'on schema dumper' do
|
443
|
+
let(:source) { ActiveRecord::Base.connection_pool }
|
444
|
+
let(:schema_table) { double(commands_table.name) }
|
445
|
+
let(:commands_table) { Torque::PostgreSQL::VersionedCommands::SchemaTable }
|
446
|
+
let(:dump_result) do
|
447
|
+
ActiveRecord::SchemaDumper.dump(source, (dump_result = StringIO.new))
|
448
|
+
dump_result.string
|
449
|
+
end
|
450
|
+
|
451
|
+
before do
|
452
|
+
allow(commands_table).to receive(:new).and_return(schema_table)
|
453
|
+
allow(schema_table).to receive(:versions_of).and_return([])
|
454
|
+
allow(schema_table).to receive(:table_name).and_return('versioned_commands_tbl')
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'does not include versioned commands info by default' do
|
458
|
+
expect(dump_result).not_to include('"versioned_commands_tbl"')
|
459
|
+
expect(dump_result).not_to include('# These are types managed by versioned commands')
|
460
|
+
expect(dump_result).not_to include('# These are functions managed by versioned commands')
|
461
|
+
expect(dump_result).not_to include('# These are views managed by versioned commands')
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'includes all types' do
|
465
|
+
connection.execute('CREATE TYPE test;')
|
466
|
+
connection.execute('CREATE TYPE internal.other;')
|
467
|
+
|
468
|
+
allow(schema_table).to receive(:versions_of).with('type').and_return([
|
469
|
+
['test', 1],
|
470
|
+
['internal_other', 2],
|
471
|
+
['remove', 1],
|
472
|
+
])
|
473
|
+
|
474
|
+
expect(dump_result).to include('# These are types managed by versioned commands')
|
475
|
+
expect(dump_result).to include('create_type "test", version: 1')
|
476
|
+
expect(dump_result).to include('create_type "internal_other", version: 2')
|
477
|
+
expect(dump_result).not_to include('create_type "removed", version: 1')
|
478
|
+
end
|
479
|
+
|
480
|
+
it 'includes all functions' do
|
481
|
+
body = 'RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql'
|
482
|
+
connection.execute("CREATE FUNCTION test() #{body};")
|
483
|
+
connection.execute("CREATE FUNCTION internal.other() #{body};")
|
484
|
+
|
485
|
+
allow(schema_table).to receive(:versions_of).with('function').and_return([
|
486
|
+
['test', 1],
|
487
|
+
['internal_other', 2],
|
488
|
+
['remove', 1],
|
489
|
+
])
|
490
|
+
|
491
|
+
expect(dump_result).to include('# These are functions managed by versioned commands')
|
492
|
+
expect(dump_result).to include('create_function "test", version: 1')
|
493
|
+
expect(dump_result).to include('create_function "internal_other", version: 2')
|
494
|
+
expect(dump_result).not_to include('create_function "removed", version: 1')
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'includes all views' do
|
498
|
+
connection.execute('CREATE VIEW test AS SELECT 1;')
|
499
|
+
connection.execute('CREATE MATERIALIZED VIEW internal.other AS SELECT 2;')
|
500
|
+
|
501
|
+
allow(schema_table).to receive(:versions_of).with('view').and_return([
|
502
|
+
['test', 1],
|
503
|
+
['internal_other', 2],
|
504
|
+
['remove', 1],
|
505
|
+
])
|
506
|
+
|
507
|
+
expect(dump_result).to include('# These are views managed by versioned commands')
|
508
|
+
expect(dump_result).to include('create_view "test", version: 1')
|
509
|
+
expect(dump_result).to include('create_view "internal_other", version: 2')
|
510
|
+
expect(dump_result).not_to include('create_view "removed", version: 1')
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: torque-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -133,6 +133,12 @@ files:
|
|
133
133
|
- MIT-LICENSE
|
134
134
|
- README.rdoc
|
135
135
|
- Rakefile
|
136
|
+
- lib/generators/torque/function_generator.rb
|
137
|
+
- lib/generators/torque/templates/function.sql.erb
|
138
|
+
- lib/generators/torque/templates/type.sql.erb
|
139
|
+
- lib/generators/torque/templates/view.sql.erb
|
140
|
+
- lib/generators/torque/type_generator.rb
|
141
|
+
- lib/generators/torque/view_generator.rb
|
136
142
|
- lib/torque-postgresql.rb
|
137
143
|
- lib/torque/postgresql.rb
|
138
144
|
- lib/torque/postgresql/adapter.rb
|
@@ -209,8 +215,10 @@ files:
|
|
209
215
|
- lib/torque/postgresql/reflection/through_reflection.rb
|
210
216
|
- lib/torque/postgresql/relation.rb
|
211
217
|
- lib/torque/postgresql/relation/auxiliary_statement.rb
|
218
|
+
- lib/torque/postgresql/relation/buckets.rb
|
212
219
|
- lib/torque/postgresql/relation/distinct_on.rb
|
213
220
|
- lib/torque/postgresql/relation/inheritance.rb
|
221
|
+
- lib/torque/postgresql/relation/join_series.rb
|
214
222
|
- lib/torque/postgresql/relation/merger.rb
|
215
223
|
- lib/torque/postgresql/schema_cache.rb
|
216
224
|
- lib/torque/postgresql/schema_cache/bound_schema_reflection.rb
|
@@ -218,6 +226,12 @@ files:
|
|
218
226
|
- lib/torque/postgresql/schema_cache/schema_reflection.rb
|
219
227
|
- lib/torque/postgresql/table_name.rb
|
220
228
|
- lib/torque/postgresql/version.rb
|
229
|
+
- lib/torque/postgresql/versioned_commands.rb
|
230
|
+
- lib/torque/postgresql/versioned_commands/command_migration.rb
|
231
|
+
- lib/torque/postgresql/versioned_commands/generator.rb
|
232
|
+
- lib/torque/postgresql/versioned_commands/migration_context.rb
|
233
|
+
- lib/torque/postgresql/versioned_commands/migrator.rb
|
234
|
+
- lib/torque/postgresql/versioned_commands/schema_table.rb
|
221
235
|
- spec/en.yml
|
222
236
|
- spec/factories/authors.rb
|
223
237
|
- spec/factories/comments.rb
|
@@ -227,6 +241,13 @@ files:
|
|
227
241
|
- spec/factories/texts.rb
|
228
242
|
- spec/factories/users.rb
|
229
243
|
- spec/factories/videos.rb
|
244
|
+
- spec/fixtures/migrations/20250101000001_create_users.rb
|
245
|
+
- spec/fixtures/migrations/20250101000002_create_function_count_users_v1.sql
|
246
|
+
- spec/fixtures/migrations/20250101000003_create_internal_users.rb
|
247
|
+
- spec/fixtures/migrations/20250101000004_update_function_count_users_v2.sql
|
248
|
+
- spec/fixtures/migrations/20250101000005_create_view_all_users_v1.sql
|
249
|
+
- spec/fixtures/migrations/20250101000006_create_type_user_id_v1.sql
|
250
|
+
- spec/fixtures/migrations/20250101000007_remove_function_count_users_v2.sql
|
230
251
|
- spec/initialize.rb
|
231
252
|
- spec/mocks/cache_query.rb
|
232
253
|
- spec/mocks/create_table.rb
|
@@ -273,6 +294,7 @@ files:
|
|
273
294
|
- spec/tests/relation_spec.rb
|
274
295
|
- spec/tests/schema_spec.rb
|
275
296
|
- spec/tests/table_inheritance_spec.rb
|
297
|
+
- spec/tests/versioned_commands_spec.rb
|
276
298
|
homepage: https://github.com/crashtech/torque-postgresql
|
277
299
|
licenses:
|
278
300
|
- MIT
|
@@ -298,7 +320,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
298
320
|
- !ruby/object:Gem::Version
|
299
321
|
version: 1.8.11
|
300
322
|
requirements: []
|
301
|
-
rubygems_version: 3.
|
323
|
+
rubygems_version: 3.5.22
|
302
324
|
signing_key:
|
303
325
|
specification_version: 4
|
304
326
|
summary: ActiveRecord extension to access PostgreSQL advanced resources
|
@@ -312,6 +334,13 @@ test_files:
|
|
312
334
|
- spec/factories/texts.rb
|
313
335
|
- spec/factories/users.rb
|
314
336
|
- spec/factories/videos.rb
|
337
|
+
- spec/fixtures/migrations/20250101000001_create_users.rb
|
338
|
+
- spec/fixtures/migrations/20250101000002_create_function_count_users_v1.sql
|
339
|
+
- spec/fixtures/migrations/20250101000003_create_internal_users.rb
|
340
|
+
- spec/fixtures/migrations/20250101000004_update_function_count_users_v2.sql
|
341
|
+
- spec/fixtures/migrations/20250101000005_create_view_all_users_v1.sql
|
342
|
+
- spec/fixtures/migrations/20250101000006_create_type_user_id_v1.sql
|
343
|
+
- spec/fixtures/migrations/20250101000007_remove_function_count_users_v2.sql
|
315
344
|
- spec/initialize.rb
|
316
345
|
- spec/mocks/cache_query.rb
|
317
346
|
- spec/mocks/create_table.rb
|
@@ -358,3 +387,4 @@ test_files:
|
|
358
387
|
- spec/tests/relation_spec.rb
|
359
388
|
- spec/tests/schema_spec.rb
|
360
389
|
- spec/tests/table_inheritance_spec.rb
|
390
|
+
- spec/tests/versioned_commands_spec.rb
|