activerecord-materialize-adapter 0.2.0 → 0.3.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.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/lib/active_record/connection_adapters/materialize/column.rb +0 -9
  3. data/lib/active_record/connection_adapters/materialize/database_statements.rb +22 -41
  4. data/lib/active_record/connection_adapters/materialize/oid.rb +0 -12
  5. data/lib/active_record/connection_adapters/materialize/oid/type_map_initializer.rb +5 -48
  6. data/lib/active_record/connection_adapters/materialize/quoting.rb +1 -7
  7. data/lib/active_record/connection_adapters/materialize/schema/source_statements.rb +66 -0
  8. data/lib/active_record/connection_adapters/materialize/schema/view_statements.rb +22 -0
  9. data/lib/active_record/connection_adapters/materialize/schema_creation.rb +18 -53
  10. data/lib/active_record/connection_adapters/materialize/schema_definitions.rb +3 -6
  11. data/lib/active_record/connection_adapters/materialize/schema_dumper.rb +82 -22
  12. data/lib/active_record/connection_adapters/materialize/schema_statements.rb +102 -354
  13. data/lib/active_record/connection_adapters/materialize/version.rb +1 -1
  14. data/lib/active_record/connection_adapters/materialize_adapter.rb +100 -253
  15. metadata +9 -15
  16. data/lib/active_record/connection_adapters/materialize/oid/cidr.rb +0 -50
  17. data/lib/active_record/connection_adapters/materialize/oid/legacy_point.rb +0 -44
  18. data/lib/active_record/connection_adapters/materialize/oid/money.rb +0 -41
  19. data/lib/active_record/connection_adapters/materialize/oid/point.rb +0 -64
  20. data/lib/active_record/connection_adapters/materialize/oid/range.rb +0 -96
  21. data/lib/active_record/connection_adapters/materialize/oid/uuid.rb +0 -25
  22. data/lib/active_record/connection_adapters/materialize/oid/vector.rb +0 -28
  23. data/lib/active_record/connection_adapters/materialize/oid/xml.rb +0 -30
@@ -3,7 +3,7 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module Materialize
6
- VERSION = "0.2.0"
6
+ VERSION = "0.3.0"
7
7
  end
8
8
  end
9
9
  end
@@ -29,9 +29,12 @@ require "active_record/connection_adapters/materialize/schema_creation"
29
29
  require "active_record/connection_adapters/materialize/schema_definitions"
30
30
  require "active_record/connection_adapters/materialize/schema_dumper"
31
31
  require "active_record/connection_adapters/materialize/schema_statements"
32
+ require "active_record/connection_adapters/materialize/schema/source_statements"
33
+ require "active_record/connection_adapters/materialize/schema/view_statements"
32
34
  require "active_record/connection_adapters/materialize/type_metadata"
33
35
  require "active_record/connection_adapters/materialize/utils"
34
36
  require "active_record/tasks/materialize_database_tasks"
37
+ require 'materialize/errors/incomplete_input'
35
38
 
36
39
  module ActiveRecord
37
40
  module ConnectionHandling # :nodoc:
@@ -105,45 +108,24 @@ module ActiveRecord
105
108
  class_attribute :create_unlogged_tables, default: false
106
109
 
107
110
  NATIVE_DATABASE_TYPES = {
108
- primary_key: "bigserial primary key",
111
+ primary_key: "bigint",
109
112
  string: { name: "character varying" },
110
113
  text: { name: "text" },
111
- integer: { name: "integer", limit: 4 },
112
- float: { name: "float" },
114
+ integer: { name: "integer" },
115
+ bigint: { name: "int8" },
116
+ float: { name: "float4" },
117
+ double: { name: "float8" },
113
118
  decimal: { name: "decimal" },
114
119
  datetime: { name: "timestamp" },
120
+ timestampz: { name: "timestamp with time zone" },
115
121
  time: { name: "time" },
116
122
  date: { name: "date" },
117
- daterange: { name: "daterange" },
118
- numrange: { name: "numrange" },
119
- tsrange: { name: "tsrange" },
120
- tstzrange: { name: "tstzrange" },
121
- int4range: { name: "int4range" },
122
- int8range: { name: "int8range" },
123
123
  binary: { name: "bytea" },
124
124
  boolean: { name: "boolean" },
125
- xml: { name: "xml" },
126
- tsvector: { name: "tsvector" },
127
- hstore: { name: "hstore" },
128
- inet: { name: "inet" },
129
- cidr: { name: "cidr" },
130
- macaddr: { name: "macaddr" },
131
- uuid: { name: "uuid" },
132
- json: { name: "json" },
133
- jsonb: { name: "jsonb" },
134
- ltree: { name: "ltree" },
135
- citext: { name: "citext" },
136
- point: { name: "point" },
137
- line: { name: "line" },
138
- lseg: { name: "lseg" },
139
- box: { name: "box" },
140
- path: { name: "path" },
141
- polygon: { name: "polygon" },
142
- circle: { name: "circle" },
143
- bit: { name: "bit" },
144
- bit_varying: { name: "bit varying" },
145
- money: { name: "money" },
125
+ map: { name: "map" },
126
+ json: { name: "jsonb" },
146
127
  interval: { name: "interval" },
128
+ record: { name: "record" },
147
129
  oid: { name: "oid" },
148
130
  }
149
131
 
@@ -153,74 +135,31 @@ module ActiveRecord
153
135
  include Materialize::ReferentialIntegrity
154
136
  include Materialize::SchemaStatements
155
137
  include Materialize::DatabaseStatements
138
+ include Materialize::Schema::SourceStatements
139
+ include Materialize::Schema::ViewStatements
156
140
 
157
141
  def supports_bulk_alter?
158
142
  true
159
143
  end
160
144
 
161
- def supports_index_sort_order?
162
- true
163
- end
164
-
165
- def supports_partitioned_indexes?
166
- database_version >= 110_000
167
- end
168
-
169
- def supports_partial_index?
170
- true
171
- end
172
-
173
- def supports_expression_index?
174
- true
175
- end
176
-
145
+ # TODO: test transaction isolation
177
146
  def supports_transaction_isolation?
178
147
  true
179
148
  end
180
149
 
181
- def supports_foreign_keys?
182
- true
183
- end
184
-
185
- def supports_validate_constraints?
186
- true
187
- end
188
-
189
150
  def supports_views?
190
151
  true
191
152
  end
192
153
 
193
- def supports_datetime_with_precision?
194
- true
195
- end
196
-
197
154
  def supports_json?
198
155
  true
199
156
  end
200
157
 
201
- def supports_comments?
202
- true
203
- end
204
-
205
- def supports_savepoints?
206
- true
207
- end
208
-
158
+ # TODO: test insert returning
209
159
  def supports_insert_returning?
210
160
  true
211
161
  end
212
162
 
213
- def supports_insert_on_conflict?
214
- database_version >= 90500
215
- end
216
- alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
217
- alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
218
- alias supports_insert_conflict_target? supports_insert_on_conflict?
219
-
220
- def index_algorithms
221
- { concurrently: "CONCURRENTLY" }
222
- end
223
-
224
163
  class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
225
164
  def initialize(connection, max)
226
165
  super(max)
@@ -266,7 +205,6 @@ module ActiveRecord
266
205
  @type_map = Type::HashLookupTypeMap.new
267
206
  initialize_type_map
268
207
  @local_tz = execute("SHOW TIMEZONE", "SCHEMA").first["TimeZone"]
269
- @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
270
208
  end
271
209
 
272
210
  def self.database_exists?(config)
@@ -339,10 +277,6 @@ module ActiveRecord
339
277
  true
340
278
  end
341
279
 
342
- def supports_extensions?
343
- true
344
- end
345
-
346
280
  def supports_ranges?
347
281
  true
348
282
  end
@@ -352,14 +286,6 @@ module ActiveRecord
352
286
  true
353
287
  end
354
288
 
355
- def supports_foreign_tables?
356
- true
357
- end
358
-
359
- def supports_pgcrypto_uuid?
360
- database_version >= 90400
361
- end
362
-
363
289
  def supports_optimizer_hints?
364
290
  unless defined?(@has_pg_hint_plan)
365
291
  @has_pg_hint_plan = extension_available?("pg_hint_plan")
@@ -389,33 +315,9 @@ module ActiveRecord
389
315
  query_value("SELECT pg_advisory_unlock(#{lock_id})")
390
316
  end
391
317
 
392
- def enable_extension(name)
393
- exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
394
- reload_type_map
395
- }
396
- end
397
-
398
- def disable_extension(name)
399
- exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap {
400
- reload_type_map
401
- }
402
- end
403
-
404
- def extension_available?(name)
405
- query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
406
- end
407
-
408
- def extension_enabled?(name)
409
- query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
410
- end
411
-
412
- def extensions
413
- exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
414
- end
415
-
416
318
  # Returns the configured supported identifier length supported by Materialize
417
319
  def max_identifier_length
418
- @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
320
+ @max_identifier_length || 64
419
321
  end
420
322
 
421
323
  # Set the authorized user for this session
@@ -424,10 +326,6 @@ module ActiveRecord
424
326
  execute("SET SESSION AUTHORIZATION #{user}")
425
327
  end
426
328
 
427
- def use_insert_returning?
428
- @use_insert_returning
429
- end
430
-
431
329
  def column_name_for_operation(operation, node) # :nodoc:
432
330
  OPERATION_ALIASES.fetch(operation) { operation.downcase }
433
331
  end
@@ -520,44 +418,52 @@ module ActiveRecord
520
418
  }
521
419
  end
522
420
 
421
+ def load_additional_types(oids = nil)
422
+ initializer = OID::TypeMapInitializer.new(type_map)
423
+
424
+ query = <<~SQL
425
+ SELECT t.id, t.oid, t.schema_id, t.name
426
+ FROM mz_types as t
427
+ LEFT JOIN mz_schemas s ON t.schema_id = s.id
428
+ LEFT JOIN mz_databases d ON s.database_id = d.id
429
+ WHERE
430
+ (d.name = #{quote(current_database)} OR s.name = 'pg_catalog')
431
+ SQL
432
+
433
+ if oids
434
+ query += "AND t.oid IN (%s)" % oids.join(", ")
435
+ else
436
+ query += initializer.query_conditions_for_initial_load
437
+ end
438
+
439
+ execute_and_clear(query, "SCHEMA", []) do |records|
440
+ initializer.run(records)
441
+ end
442
+ end
443
+
523
444
  def initialize_type_map(m = type_map)
524
445
  m.register_type "int2", Type::Integer.new(limit: 2)
525
446
  m.register_type "int4", Type::Integer.new(limit: 4)
526
447
  m.register_type "int8", Type::Integer.new(limit: 8)
448
+ m.alias_type "int", "int4"
449
+ m.alias_type "integer", "int4"
450
+ m.alias_type "bigint", "int8"
527
451
  m.register_type "oid", OID::Oid.new
528
452
  m.register_type "float4", Type::Float.new
529
453
  m.alias_type "float8", "float4"
454
+ m.alias_type "double", "float4"
530
455
  m.register_type "text", Type::Text.new
531
- register_class_with_limit m, "varchar", Type::String
532
- m.alias_type "char", "varchar"
533
- m.alias_type "name", "varchar"
534
- m.alias_type "bpchar", "varchar"
535
- m.register_type "bool", Type::Boolean.new
536
- register_class_with_limit m, "bit", OID::Bit
537
- register_class_with_limit m, "varbit", OID::BitVarying
456
+ m.alias_type "varchar", "text"
457
+
458
+ m.register_type "boolean", Type::Boolean.new
459
+ register_class_with_limit m, "bytea", OID::BitVarying
460
+
538
461
  m.alias_type "timestamptz", "timestamp"
539
462
  m.register_type "date", OID::Date.new
540
463
 
541
- m.register_type "money", OID::Money.new
542
464
  m.register_type "bytea", OID::Bytea.new
543
- m.register_type "point", OID::Point.new
544
- m.register_type "hstore", OID::Hstore.new
545
- m.register_type "json", Type::Json.new
546
465
  m.register_type "jsonb", OID::Jsonb.new
547
- m.register_type "cidr", OID::Cidr.new
548
- m.register_type "inet", OID::Inet.new
549
- m.register_type "uuid", OID::Uuid.new
550
- m.register_type "xml", OID::Xml.new
551
- m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
552
- m.register_type "macaddr", OID::SpecializedString.new(:macaddr)
553
- m.register_type "citext", OID::SpecializedString.new(:citext)
554
- m.register_type "ltree", OID::SpecializedString.new(:ltree)
555
- m.register_type "line", OID::SpecializedString.new(:line)
556
- m.register_type "lseg", OID::SpecializedString.new(:lseg)
557
- m.register_type "box", OID::SpecializedString.new(:box)
558
- m.register_type "path", OID::SpecializedString.new(:path)
559
- m.register_type "polygon", OID::SpecializedString.new(:polygon)
560
- m.register_type "circle", OID::SpecializedString.new(:circle)
466
+ m.alias_type "json", "jsonb"
561
467
 
562
468
  m.register_type "interval" do |_, _, sql_type|
563
469
  precision = extract_precision(sql_type)
@@ -567,25 +473,7 @@ module ActiveRecord
567
473
  register_class_with_precision m, "time", Type::Time
568
474
  register_class_with_precision m, "timestamp", OID::DateTime
569
475
 
570
- m.register_type "numeric" do |_, fmod, sql_type|
571
- precision = extract_precision(sql_type)
572
- scale = extract_scale(sql_type)
573
-
574
- # The type for the numeric depends on the width of the field,
575
- # so we'll do something special here.
576
- #
577
- # When dealing with decimal columns:
578
- #
579
- # places after decimal = fmod - 4 & 0xffff
580
- # places before decimal = (fmod - 4) >> 16 & 0xffff
581
- if fmod && (fmod - 4 & 0xffff).zero?
582
- # FIXME: Remove this class, and the second argument to
583
- # lookups on PG
584
- Type::DecimalWithoutScale.new(precision: precision)
585
- else
586
- OID::Decimal.new(precision: precision, scale: scale)
587
- end
588
- end
476
+ load_additional_types
589
477
  end
590
478
 
591
479
  # Extracts the value from a Materialize column default definition.
@@ -623,26 +511,6 @@ module ActiveRecord
623
511
  !default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
624
512
  end
625
513
 
626
- def load_additional_types(oids = nil)
627
- initializer = OID::TypeMapInitializer.new(type_map)
628
-
629
- query = <<~SQL
630
- SELECT t.oid, t.typname, t.typelem, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
631
- FROM pg_type as t
632
- LEFT JOIN pg_range as r ON oid = rngtypid
633
- SQL
634
-
635
- if oids
636
- query += "WHERE t.oid IN (%s)" % oids.join(", ")
637
- else
638
- query += initializer.query_conditions_for_initial_load
639
- end
640
-
641
- execute_and_clear(query, "SCHEMA", []) do |records|
642
- initializer.run(records)
643
- end
644
- end
645
-
646
514
  FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
647
515
 
648
516
  def execute_and_clear(sql, name, binds, prepare: false)
@@ -652,10 +520,8 @@ module ActiveRecord
652
520
 
653
521
  if without_prepared_statement?(binds)
654
522
  result = exec_no_cache(sql, name, [])
655
- elsif !prepare
656
- result = exec_no_cache(sql, name, binds)
657
523
  else
658
- result = exec_cache(sql, name, binds)
524
+ result = exec_no_cache(sql, name, binds)
659
525
  end
660
526
  ret = yield result
661
527
  result.clear
@@ -669,39 +535,18 @@ module ActiveRecord
669
535
  # made since we established the connection
670
536
  update_typemap_for_default_timezone
671
537
 
672
- type_casted_binds = type_casted_binds(binds)
673
- log(sql, name, binds, type_casted_binds) do
538
+ typed_binds = type_casted_binds(binds)
539
+ log(sql, name, binds, typed_binds) do
674
540
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
675
- @connection.exec_params(sql, type_casted_binds)
541
+ @connection.exec_params(prepare_statement(sql, typed_binds), [])
676
542
  end
677
543
  end
678
- end
679
-
680
- def exec_cache(sql, name, binds)
681
- materialize_transactions
682
- update_typemap_for_default_timezone
683
-
684
- stmt_key = prepare_statement(sql, binds)
685
- type_casted_binds = type_casted_binds(binds)
686
-
687
- log(sql, name, binds, type_casted_binds, stmt_key) do
688
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
689
- @connection.exec_prepared(stmt_key, type_casted_binds)
690
- end
691
- end
692
- rescue ActiveRecord::StatementInvalid => e
693
- raise unless is_cached_plan_failure?(e)
694
-
695
- # Nothing we can do if we are in a transaction because all commands
696
- # will raise InFailedSQLTransaction
697
- if in_transaction?
698
- raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
544
+ rescue ActiveRecord::StatementInvalid,
545
+ PG::InternalError => error
546
+ if error.message.include? "At least one input has no complete timestamps yet"
547
+ raise ::Materialize::Errors::IncompleteInput, error.message
699
548
  else
700
- @lock.synchronize do
701
- # outside of transactions we can simply flush this query and retry
702
- @statements.delete sql_key(sql)
703
- end
704
- retry
549
+ raise
705
550
  end
706
551
  end
707
552
 
@@ -730,27 +575,33 @@ module ActiveRecord
730
575
  # Returns the statement identifier for the client side cache
731
576
  # of statements
732
577
  def sql_key(sql)
733
- "#{schema_search_path}-#{sql}"
578
+ "#{sql}"
734
579
  end
735
580
 
736
- # Prepare the statement if it hasn't been prepared, return
737
- # the statement key.
738
581
  def prepare_statement(sql, binds)
739
- @lock.synchronize do
740
- sql_key = sql_key(sql)
741
- unless @statements.key? sql_key
742
- nextkey = @statements.next_key
743
- begin
744
- @connection.prepare nextkey, sql
745
- rescue => e
746
- raise translate_exception_class(e, sql, binds)
582
+ parametrized_statement = sql.split(/\s+/)
583
+ binds.each_with_index do |n, i|
584
+ index = i + 1
585
+ part = \
586
+ case n
587
+ when String
588
+ "'#{quote_string(n)}'"
589
+ when Numeric
590
+ n.to_s
747
591
  end
748
- # Clear the queue
749
- @connection.get_last_result
750
- @statements[sql_key] = nextkey
592
+
593
+ parametrized_statement = parametrized_statement.map do |token|
594
+ token
595
+ .gsub("$#{index}", part)
596
+ .gsub("($#{index}", "(#{part}")
597
+ .gsub("$#{index})", "#{part})")
598
+ .gsub("($#{index})", "(#{part})")
599
+ .gsub(",$#{index}", ",#{part}")
600
+ .gsub("$#{index},", "#{part},")
601
+ .gsub(",$#{index},", ",#{part},")
751
602
  end
752
- @statements[sql_key]
753
603
  end
604
+ parametrized_statement.join ' '
754
605
  end
755
606
 
756
607
  # Connects to a Materialize server and sets up the adapter depending on the
@@ -768,7 +619,6 @@ module ActiveRecord
768
619
  if @config[:encoding]
769
620
  @connection.set_client_encoding(@config[:encoding])
770
621
  end
771
- self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
772
622
 
773
623
  variables = @config.fetch(:variables, {}).stringify_keys
774
624
 
@@ -814,16 +664,20 @@ module ActiveRecord
814
664
  # - ::regclass is a function that gives the id for a table name
815
665
  def column_definitions(table_name)
816
666
  query(<<~SQL, "SCHEMA")
817
- SELECT a.attname, format_type(a.atttypid, a.atttypmod),
818
- pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
819
- c.collname, col_description(a.attrelid, a.attnum) AS comment
820
- FROM pg_attribute a
821
- LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
822
- LEFT JOIN pg_type t ON a.atttypid = t.oid
823
- LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
824
- WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
825
- AND a.attnum > 0 AND NOT a.attisdropped
826
- ORDER BY a.attnum
667
+ SELECT
668
+ c.name,
669
+ c.type AS format_type,
670
+ c.nullable,
671
+ NULL AS default,
672
+ NULL AS comment
673
+ FROM mz_columns c
674
+ LEFT JOIN mz_tables t ON c.id = t.id
675
+ LEFT JOIN mz_schemas s ON t.schema_id = s.id
676
+ LEFT JOIN mz_databases d ON s.database_id = d.id
677
+ WHERE
678
+ t.name = #{quote(table_name)}
679
+ AND d.name = #{quote(current_database)}
680
+ ORDER BY c.position
827
681
  SQL
828
682
  end
829
683
 
@@ -890,10 +744,15 @@ module ActiveRecord
890
744
  "int2" => PG::TextDecoder::Integer,
891
745
  "int4" => PG::TextDecoder::Integer,
892
746
  "int8" => PG::TextDecoder::Integer,
747
+ "integer" => PG::TextDecoder::Integer,
748
+ "bigint" => PG::TextDecoder::Integer,
893
749
  "oid" => PG::TextDecoder::Integer,
750
+ "float" => PG::TextDecoder::Float,
894
751
  "float4" => PG::TextDecoder::Float,
895
752
  "float8" => PG::TextDecoder::Float,
753
+ "double" => PG::TextDecoder::Float,
896
754
  "bool" => PG::TextDecoder::Boolean,
755
+ "boolean" => PG::TextDecoder::Boolean,
897
756
  }
898
757
 
899
758
  if defined?(PG::TextDecoder::TimestampUtc)
@@ -929,24 +788,12 @@ module ActiveRecord
929
788
  end
930
789
 
931
790
  ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :materialize)
932
- ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :materialize)
933
- ActiveRecord::Type.register(:bit, OID::Bit, adapter: :materialize)
934
- ActiveRecord::Type.register(:bit_varying, OID::BitVarying, adapter: :materialize)
935
791
  ActiveRecord::Type.register(:binary, OID::Bytea, adapter: :materialize)
936
- ActiveRecord::Type.register(:cidr, OID::Cidr, adapter: :materialize)
937
792
  ActiveRecord::Type.register(:date, OID::Date, adapter: :materialize)
938
793
  ActiveRecord::Type.register(:datetime, OID::DateTime, adapter: :materialize)
939
794
  ActiveRecord::Type.register(:decimal, OID::Decimal, adapter: :materialize)
940
795
  ActiveRecord::Type.register(:enum, OID::Enum, adapter: :materialize)
941
- ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :materialize)
942
- ActiveRecord::Type.register(:inet, OID::Inet, adapter: :materialize)
943
796
  ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :materialize)
944
- ActiveRecord::Type.register(:money, OID::Money, adapter: :materialize)
945
- ActiveRecord::Type.register(:point, OID::Point, adapter: :materialize)
946
- ActiveRecord::Type.register(:legacy_point, OID::LegacyPoint, adapter: :materialize)
947
- ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :materialize)
948
- ActiveRecord::Type.register(:vector, OID::Vector, adapter: :materialize)
949
- ActiveRecord::Type.register(:xml, OID::Xml, adapter: :materialize)
950
797
  end
951
798
  end
952
799
  end