foobara-postgresql-crud-driver 0.0.2 → 0.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/src/postgresql_crud_driver.rb +109 -79
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c6ce8966a4872d4a3e81a1bcfec564df6be8903cd20e7bf8b998b9fc6ba423b8
|
|
4
|
+
data.tar.gz: ead889be3b61d1293dd8c78ada43f3b2f3c68cbaa11af81ef6fbc3ce975fdc5f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d7bdb1286bc1a27ad62217f278155225722e88cb01c8faa193c80a932f1b07d441ef78bc0dac56ade1ce7e29c51d85e63f28e4b77c7913184ccd695a077caca
|
|
7
|
+
data.tar.gz: a4509b915954600c4c7001e0e078856a8ef38063298877ff076cdfd94bf76c1b37b08a2488453e54084c7458189189a19881762406b4019a8d186e4de2f032b9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [0.0.4] - 2025-11-09
|
|
2
|
+
|
|
3
|
+
- Support a few more column types
|
|
4
|
+
- Make sure an entity -> entity association is cast properly
|
|
5
|
+
|
|
6
|
+
## [0.0.3] - 2025-10-21
|
|
7
|
+
|
|
8
|
+
- Pass through options to EntityAttributesCrudDriver instead of disallowing them
|
|
9
|
+
|
|
1
10
|
## [0.0.2] - 2025-08-22
|
|
2
11
|
|
|
3
12
|
- Mark as compatible with Foobara 0.1.0
|
|
@@ -4,6 +4,18 @@ module Foobara
|
|
|
4
4
|
class NoSuchColumnOrTableError < StandardError; end
|
|
5
5
|
|
|
6
6
|
class UnsupportedPgColumnTypeError < StandardError
|
|
7
|
+
attr_accessor :pg_type, :attribute_name, :entity_class
|
|
8
|
+
|
|
9
|
+
def initialize(pg_type, entity_class)
|
|
10
|
+
# :nocov:
|
|
11
|
+
super("Unsupported column type #{pg_type} on #{entity_class.entity_name}")
|
|
12
|
+
# :nocov:
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class UnsupportedPgColumnTypeForAttributeError < StandardError
|
|
17
|
+
attr_accessor :pg_type, :attribute_name, :entity_class
|
|
18
|
+
|
|
7
19
|
def initialize(pg_type, attribute_name, entity_class)
|
|
8
20
|
# :nocov:
|
|
9
21
|
super("Unsupported column type #{pg_type} for attribute #{attribute_name} on #{entity_class.entity_name}")
|
|
@@ -16,7 +28,7 @@ module Foobara
|
|
|
16
28
|
@get_transaction_number ||= 0
|
|
17
29
|
@get_transaction_number += 1
|
|
18
30
|
if @get_transaction_number > 65_535
|
|
19
|
-
# TODO: test this
|
|
31
|
+
# TODO: test this code path somehow
|
|
20
32
|
# :nocov:
|
|
21
33
|
@get_transaction_number = 1
|
|
22
34
|
# :nocov:
|
|
@@ -39,10 +51,10 @@ module Foobara
|
|
|
39
51
|
|
|
40
52
|
attr_accessor :creds, :transaction_number
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
def initialize(connection_or_credentials = nil, **)
|
|
55
|
+
# We will manage the connections ourselves and don't want to automatically open one now
|
|
56
|
+
super(**, connect: false)
|
|
57
|
+
|
|
46
58
|
self.transaction_number = self.class.get_transaction_number
|
|
47
59
|
self.tables = {}
|
|
48
60
|
self.creds = case connection_or_credentials
|
|
@@ -59,7 +71,6 @@ module Foobara
|
|
|
59
71
|
# :nocov:
|
|
60
72
|
end
|
|
61
73
|
end
|
|
62
|
-
# rubocop:enable Lint/MissingSuper
|
|
63
74
|
|
|
64
75
|
def open_connection
|
|
65
76
|
PG.connect(creds)
|
|
@@ -268,9 +279,11 @@ module Foobara
|
|
|
268
279
|
info = column_info[attribute_name.to_s]
|
|
269
280
|
|
|
270
281
|
value = case info[:type]
|
|
271
|
-
when "integer", "
|
|
282
|
+
when "integer", "bigint",
|
|
283
|
+
"text", "character varying",
|
|
284
|
+
"timestamp without time zone"
|
|
272
285
|
value
|
|
273
|
-
when "jsonb"
|
|
286
|
+
when "jsonb", "json"
|
|
274
287
|
if value.nil?
|
|
275
288
|
unless info[:is_nullable]
|
|
276
289
|
# :nocov:
|
|
@@ -307,79 +320,19 @@ module Foobara
|
|
|
307
320
|
# :nocov:
|
|
308
321
|
end
|
|
309
322
|
|
|
310
|
-
pg_type = info[:type]
|
|
311
323
|
foobara_type = entity_class.model_type.element_types.element_types[attribute_name]
|
|
312
324
|
|
|
313
|
-
value =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
value.to_i
|
|
325
|
-
else
|
|
326
|
-
# :nocov:
|
|
327
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
328
|
-
# :nocov:
|
|
329
|
-
end
|
|
330
|
-
elsif foobara_type.extends?(:string) || foobara_type.extends?(:symbol)
|
|
331
|
-
case pg_type
|
|
332
|
-
when "text"
|
|
333
|
-
"'#{PG::Connection.escape(value.to_s)}'"
|
|
334
|
-
else
|
|
335
|
-
# :nocov:
|
|
336
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
337
|
-
# :nocov:
|
|
338
|
-
end
|
|
339
|
-
elsif foobara_type.extends?(:datetime)
|
|
340
|
-
case pg_type
|
|
341
|
-
when "timestamp without time zone"
|
|
342
|
-
"'#{PG::Connection.escape(value.inspect)}'"
|
|
343
|
-
else
|
|
344
|
-
# :nocov:
|
|
345
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
346
|
-
# :nocov:
|
|
347
|
-
end
|
|
348
|
-
elsif foobara_type.extends?(:model) || foobara_type.extends?(:attributes)
|
|
349
|
-
case pg_type
|
|
350
|
-
when "jsonb"
|
|
351
|
-
"'#{PG::Connection.escape(JSON.fast_generate(value))}'"
|
|
352
|
-
else
|
|
353
|
-
# :nocov:
|
|
354
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
355
|
-
# :nocov:
|
|
356
|
-
end
|
|
357
|
-
elsif foobara_type.extends?(:array)
|
|
358
|
-
element_type = foobara_type.element_type
|
|
359
|
-
|
|
360
|
-
if element_type.extends?(:detached_entity)
|
|
361
|
-
case pg_type
|
|
362
|
-
when "ARRAY"
|
|
363
|
-
elements_type = ARRAY_ELEMENT_ENCODERS[info[:element_type]]
|
|
364
|
-
array_string = PG::TextEncoder::Array.new(elements_type:).encode(value)
|
|
365
|
-
escaped = PG::Connection.escape(array_string)
|
|
366
|
-
|
|
367
|
-
"'#{escaped}'"
|
|
368
|
-
else
|
|
369
|
-
# :nocov:
|
|
370
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
371
|
-
# :nocov:
|
|
372
|
-
end
|
|
373
|
-
else
|
|
374
|
-
# :nocov:
|
|
375
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
376
|
-
# :nocov:
|
|
377
|
-
end
|
|
378
|
-
else
|
|
379
|
-
# :nocov:
|
|
380
|
-
raise UnsupportedPgColumnTypeError.new(pg_type, attribute_name, entity_class)
|
|
381
|
-
# :nocov:
|
|
382
|
-
end
|
|
325
|
+
value = begin
|
|
326
|
+
pg_cast_value(value, foobara_type, info)
|
|
327
|
+
rescue UnsupportedPgColumnTypeError => e
|
|
328
|
+
# :nocov:
|
|
329
|
+
raise UnsupportedPgColumnTypeForAttributeError.new(
|
|
330
|
+
e.pg_type,
|
|
331
|
+
attribute_name,
|
|
332
|
+
entity_class
|
|
333
|
+
)
|
|
334
|
+
# :nocov:
|
|
335
|
+
end
|
|
383
336
|
|
|
384
337
|
[PostgresqlCrudDriver.escape_identifier(attribute_name), value]
|
|
385
338
|
end
|
|
@@ -407,6 +360,83 @@ module Foobara
|
|
|
407
360
|
]
|
|
408
361
|
end
|
|
409
362
|
end
|
|
363
|
+
|
|
364
|
+
def pg_cast_value(value, foobara_type, pg_info)
|
|
365
|
+
pg_type = pg_info[:type]
|
|
366
|
+
|
|
367
|
+
if value.nil?
|
|
368
|
+
if pg_info[:is_nullable]
|
|
369
|
+
"NULL"
|
|
370
|
+
else
|
|
371
|
+
# :nocov:
|
|
372
|
+
raise "Unexpected nil value for #{attribute_name}"
|
|
373
|
+
# :nocov:
|
|
374
|
+
end
|
|
375
|
+
elsif foobara_type.extends?(:number)
|
|
376
|
+
case pg_type
|
|
377
|
+
when "integer", "bigint"
|
|
378
|
+
value.to_i
|
|
379
|
+
else
|
|
380
|
+
# :nocov:
|
|
381
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
382
|
+
# :nocov:
|
|
383
|
+
end
|
|
384
|
+
elsif foobara_type.extends?(:string) || foobara_type.extends?(:symbol)
|
|
385
|
+
case pg_type
|
|
386
|
+
when "text", "character varying"
|
|
387
|
+
"'#{PG::Connection.escape(value.to_s)}'"
|
|
388
|
+
else
|
|
389
|
+
# :nocov:
|
|
390
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
391
|
+
# :nocov:
|
|
392
|
+
end
|
|
393
|
+
elsif foobara_type.extends?(:datetime)
|
|
394
|
+
case pg_type
|
|
395
|
+
when "timestamp without time zone"
|
|
396
|
+
"'#{PG::Connection.escape(value.inspect)}'"
|
|
397
|
+
else
|
|
398
|
+
# :nocov:
|
|
399
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
400
|
+
# :nocov:
|
|
401
|
+
end
|
|
402
|
+
elsif foobara_type.extends?(:detached_entity)
|
|
403
|
+
pg_cast_value(value, foobara_type.target_class.primary_key_type, pg_info)
|
|
404
|
+
elsif foobara_type.extends?(:model) || foobara_type.extends?(:attributes)
|
|
405
|
+
case pg_type
|
|
406
|
+
when "jsonb", "json"
|
|
407
|
+
"'#{PG::Connection.escape(JSON.fast_generate(value))}'"
|
|
408
|
+
else
|
|
409
|
+
# :nocov:
|
|
410
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
411
|
+
# :nocov:
|
|
412
|
+
end
|
|
413
|
+
elsif foobara_type.extends?(:array)
|
|
414
|
+
element_type = foobara_type.element_type
|
|
415
|
+
|
|
416
|
+
if element_type.extends?(:detached_entity)
|
|
417
|
+
case pg_type
|
|
418
|
+
when "ARRAY"
|
|
419
|
+
elements_type = ARRAY_ELEMENT_ENCODERS[pg_info[:element_type]]
|
|
420
|
+
array_string = PG::TextEncoder::Array.new(elements_type:).encode(value)
|
|
421
|
+
escaped = PG::Connection.escape(array_string)
|
|
422
|
+
|
|
423
|
+
"'#{escaped}'"
|
|
424
|
+
else
|
|
425
|
+
# :nocov:
|
|
426
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
427
|
+
# :nocov:
|
|
428
|
+
end
|
|
429
|
+
else
|
|
430
|
+
# :nocov:
|
|
431
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
432
|
+
# :nocov:
|
|
433
|
+
end
|
|
434
|
+
else
|
|
435
|
+
# :nocov:
|
|
436
|
+
raise UnsupportedPgColumnTypeError.new(pg_type, entity_class)
|
|
437
|
+
# :nocov:
|
|
438
|
+
end
|
|
439
|
+
end
|
|
410
440
|
end
|
|
411
441
|
end
|
|
412
442
|
end
|