kudu_adapter 0.1.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 (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +8 -0
  4. data/Gemfile +9 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +178 -0
  7. data/kudu_adapter.gemspec +33 -0
  8. data/lib/active_record/connection_adapters/kudu/column.rb +17 -0
  9. data/lib/active_record/connection_adapters/kudu/database_statements.rb +41 -0
  10. data/lib/active_record/connection_adapters/kudu/quoting.rb +51 -0
  11. data/lib/active_record/connection_adapters/kudu/schema_creation.rb +89 -0
  12. data/lib/active_record/connection_adapters/kudu/schema_statements.rb +507 -0
  13. data/lib/active_record/connection_adapters/kudu/sql_type_metadata.rb +16 -0
  14. data/lib/active_record/connection_adapters/kudu/table_definition.rb +32 -0
  15. data/lib/active_record/connection_adapters/kudu/type/big_int.rb +22 -0
  16. data/lib/active_record/connection_adapters/kudu/type/boolean.rb +23 -0
  17. data/lib/active_record/connection_adapters/kudu/type/char.rb +17 -0
  18. data/lib/active_record/connection_adapters/kudu/type/date_time.rb +21 -0
  19. data/lib/active_record/connection_adapters/kudu/type/double.rb +17 -0
  20. data/lib/active_record/connection_adapters/kudu/type/float.rb +18 -0
  21. data/lib/active_record/connection_adapters/kudu/type/integer.rb +22 -0
  22. data/lib/active_record/connection_adapters/kudu/type/small_int.rb +22 -0
  23. data/lib/active_record/connection_adapters/kudu/type/string.rb +17 -0
  24. data/lib/active_record/connection_adapters/kudu/type/time.rb +30 -0
  25. data/lib/active_record/connection_adapters/kudu/type/tiny_int.rb +22 -0
  26. data/lib/active_record/connection_adapters/kudu_adapter.rb +173 -0
  27. data/lib/active_record/tasks/kudu_database_tasks.rb +29 -0
  28. data/lib/arel/visitors/kudu.rb +7 -0
  29. data/lib/kudu_adapter/bind_substitution.rb +15 -0
  30. data/lib/kudu_adapter/table_definition_extensions.rb +28 -0
  31. data/lib/kudu_adapter/version.rb +5 -0
  32. data/lib/kudu_adapter.rb +5 -0
  33. data/spec/spec_config.yaml.template +8 -0
  34. data/spec/spec_helper.rb +124 -0
  35. metadata +205 -0
@@ -0,0 +1,507 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/connection_adapters/kudu/column'
4
+ require 'active_record/connection_adapters/kudu/schema_creation'
5
+ require 'active_record/connection_adapters/kudu/sql_type_metadata'
6
+ require 'active_record/connection_adapters/kudu/table_definition'
7
+ require 'active_record/migration/join_table'
8
+
9
+ # :nodoc:
10
+ module ActiveRecord
11
+ module ConnectionAdapters
12
+ module Kudu
13
+ include ::ActiveRecord::Migration::JoinTable
14
+
15
+ # TODO methods delegate :quote_column_name, :quote_default_expression, :type_to_sql,
16
+ # :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?,
17
+ # :foreign_key_options, to: :@conn
18
+ # ^^^ THOSE ARE FROM SCHEMACREATION ^^^
19
+
20
+ # :nodoc:
21
+ module SchemaStatements
22
+
23
+ def table_options(table_name)
24
+ nil
25
+ end
26
+
27
+ def table_comment(table_name)
28
+ raise NotImplementedError, '#table_comment Comments not implemented'
29
+ end
30
+
31
+ def table_alias_for(table_name)
32
+ table_name.tr('.', '_')
33
+ end
34
+
35
+ def data_sources
36
+ tables | views
37
+ end
38
+
39
+ def data_source_exists?(name)
40
+ data_sources.include? name.to_s
41
+ end
42
+
43
+ def tables
44
+ connection.query('SHOW TABLES').map { |table| table[:name] }
45
+ end
46
+
47
+ def table_exists?(table_name)
48
+ tables.include? table_name.to_s
49
+ end
50
+
51
+ # Return list of existing views. As we are not supporting them,
52
+ # this list will be always empty
53
+ def views
54
+ []
55
+ end
56
+
57
+ # Check if given view exists. As we are not supporting views,
58
+ # it'll be always false
59
+ def view_exists?(_)
60
+ false
61
+ end
62
+
63
+ def indexes(table_name, name = nil)
64
+ []
65
+ end
66
+
67
+ def index_exists?(table_name, column_name, options = {})
68
+ raise NotImplementedError, '#index_exists? Indexing not implemented'
69
+ end
70
+
71
+ def columns(table_name)
72
+ table_structure(table_name).map do |col_def|
73
+ type = if col_def[:type] == 'int'
74
+ :integer
75
+ elsif col_def[:type] == 'bigint' && /_at$/ =~ col_def[:name]
76
+ :datetime
77
+ else
78
+ col_def[:type].to_sym
79
+ end
80
+ stm = ::ActiveRecord::ConnectionAdapters::Kudu::SqlTypeMetadata.new(sql_type: col_def[:type], type: type)
81
+ ::ActiveRecord::ConnectionAdapters::Kudu::Column.new(
82
+ col_def[:name],
83
+ col_def[:default_value]&.empty? ? nil : col_def[:default_value],
84
+ stm,
85
+ col_def[:null] == 'true',
86
+ table_name,
87
+ col_def[:comment]
88
+ )
89
+ end
90
+ end
91
+
92
+ def column_exists?(table_name, column_name, type = nil, options = {})
93
+ column_name = column_name.to_s
94
+ checks = []
95
+ checks << lambda { |c| c.name == column_name }
96
+ checks << lambda { |c| c.type == type } if type
97
+ column_options_keys.each do |attr|
98
+ checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
99
+ end
100
+ columns(table_name).any? { |c| checks.all? { |check| check[c] } }
101
+ end
102
+
103
+ def primary_key(table_name)
104
+ pks = table_structure(table_name).select { |col| col[:primary_key] == 'true' }
105
+ pks.map! { |pk| pk[:name] }
106
+ pks.size == 1 ? pks.first : pks
107
+ end
108
+
109
+ def create_table(table_name, comment: nil, **options)
110
+ td = create_table_definition table_name, options[:temporary], options[:options], options[:as], comment: comment
111
+ if options[:id] != false && !options[:as]
112
+ pk = options.fetch(:primary_key) do
113
+ Base.get_primary_key table_name.to_s.singularize
114
+ end
115
+
116
+ if pk.is_a?(Array)
117
+ td.primary_keys pk
118
+ else
119
+ td.primary_key pk, options.fetch(:id, :primary_key), options
120
+ end
121
+ end
122
+
123
+ yield td if block_given?
124
+
125
+ options[:force] && drop_table(table_name, **options, if_exists: true)
126
+
127
+ result = execute schema_creation.accept td
128
+
129
+ unless supports_indexes_in_create?
130
+ td.indexes.each do |column_name, index_options|
131
+ add_index(table_name, column_name, index_options)
132
+ end
133
+ end
134
+
135
+ if supports_comments? && !supports_comments_in_create?
136
+ change_table_comment(table_name, comment) if comment.present?
137
+ td.columns.each do |column|
138
+ change_column_comment(table_name, column.name, column.comment) if column.comment.present?
139
+ end
140
+ end
141
+
142
+ result
143
+ end
144
+
145
+ def drop_table(table_name, **options)
146
+ execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
147
+ end
148
+
149
+ def drop_temp_tables
150
+ tbl = tables
151
+ to_delete = tbl.select {|tbl| tbl.include? '_temp' }
152
+ to_delete.each do |dt|
153
+ drop_table(dt)
154
+ end
155
+ end
156
+
157
+ def create_join_table(table_1, table_2, colum_options: {}, **options)
158
+ join_table_name = find_join_table_name(table_1, table_2, options)
159
+
160
+ column_options = options.delete(:column_options) || {}
161
+ column_options.reverse_merge!(null: false)
162
+ column_options.merge!(primary_key: true)
163
+
164
+ t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }
165
+
166
+ create_table(join_table_name, options.merge!(id: false)) do |td|
167
+ td.string t1_column, column_options
168
+ td.string t2_column, column_options
169
+ yield td if block_given?
170
+ end
171
+ end
172
+
173
+ def drop_join_table(table_1, table_2, options = {})
174
+ join_table_name = find_join_table_name(table_1, table_2, options)
175
+ drop_table join_table_name
176
+ end
177
+
178
+ def change_table(table_name, options = {})
179
+ if supports_bulk_alter? && options[:bulk]
180
+ recorder = ActiveRecord::Migration::CommandRecorder.new(self)
181
+ yield update_table_definition(table_name, recorder)
182
+ bulk_change_table(table_name, recorder.commands)
183
+ else
184
+ yield update_table_definition(table_name, self)
185
+ end
186
+ end
187
+
188
+ def rename_table(table_name, new_name)
189
+ db_name = Rails.configuration.database_configuration[Rails.env]['database']
190
+ execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
191
+ execute "ALTER TABLE #{quote_table_name(new_name)} SET TblProperties('kudu.table_name' = 'impala::#{db_name}.#{new_name}')"
192
+ end
193
+
194
+ def add_column(table_name, column_name, type, options = {})
195
+ if options_has_primary_key(options)
196
+ # be aware of primary key columns
197
+ redefine_table_add_primary_key(table_name, column_name, type, options)
198
+ else
199
+ at = create_alter_table table_name
200
+ at.add_column(column_name, type, options)
201
+ execute schema_creation.accept at
202
+ end
203
+ end
204
+
205
+ def remove_columns(table_name, column_names)
206
+ raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)") if column_names.empty?
207
+ column_names.each do |column_name|
208
+ remove_column(table_name, column_name)
209
+ end
210
+ end
211
+
212
+ def remove_column(table_name, column_name, type = nil, options = {})
213
+ if primary_keys_contain_column_name(table_name, column_name)
214
+ # be aware of primary key columns
215
+ #raise ArgumentError.new("You cannot drop primary key fields")
216
+ redefine_table_drop_primary_key(table_name, column_name, type, options)
217
+ else
218
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
219
+ end
220
+ end
221
+
222
+ def change_column(table_name, column_name, type, options)
223
+ raise NotImplementedError, '#change_column Altering columns not implemented'
224
+ end
225
+
226
+ def change_column_default(table_name, column_name, default_or_changes)
227
+ raise NotImplementedError, '#change_column_default Altering column defaults not implemented'
228
+ end
229
+
230
+ def change_column_null(table_name, column_name, null, default = nil)
231
+ raise NotImplementedError, '#change_column_null Altering column null not implemented'
232
+ end
233
+
234
+ def rename_column(table_name, column_name, new_column_name)
235
+ raise ArgumentError.new('You cannot rename primary key fields') if primary_keys_contain_column_name(table_name, column_name)
236
+ column = columns(table_name).find { |c| c.name.to_s == column_name.to_s }
237
+ execute "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{column.sql_type}"
238
+ end
239
+
240
+ # It will reload all data from temp table name into new one.
241
+ # We're seeking for table_name_temp while we inserting data with additional new column and it's value.
242
+ # At the end table_name_temp is dropped indeed.
243
+ def reload_table_data(table_name, column_name, options = {})
244
+ temp_table_name = table_name + '_temp'
245
+
246
+ # get table structure and remove our column name
247
+ columns = table_structure table_name
248
+ columns.reject! { |c| c[:name] == column_name.to_s }
249
+
250
+ select_qry = columns.map {|col| col[:name].to_s }.join(',')
251
+
252
+ # values with additional column name
253
+ values = select_qry + ',' + column_name.to_s
254
+ # fetch values with our column name and value to insert
255
+ fetch_values = select_qry + ',' + quote(options[:default]) + ' AS ' + column_name.to_s
256
+
257
+ insert_qry = "INSERT INTO #{quote_table_name(table_name)} (#{values}) SELECT #{fetch_values} FROM #{quote_table_name(temp_table_name)}"
258
+ execute insert_qry
259
+
260
+ drop_table(temp_table_name)
261
+ end
262
+
263
+ def add_index(table_name, column_name, options = {})
264
+ p '(add_index) Indexing not supported by Apache KUDU'
265
+ end
266
+
267
+ def remove_index(table_name, options = {})
268
+ p '(remove_index) Indexing not supported by Apache KUDU'
269
+ end
270
+
271
+ def rename_index(table_name, old_name, new_name)
272
+ p '(rename_index) Indexing not supported by Apache KUDU'
273
+ end
274
+
275
+ def index_name(table_name, options)
276
+ p '(index_name) Indexing not supported by Apache KUDU'
277
+ end
278
+
279
+ def index_name_exists?(table_name, index_name, default = nil)
280
+ p '(index_name_exists?) Indexing not supported by Apache KUDU'
281
+ end
282
+
283
+ def add_reference(table_name, ref_name, **options)
284
+ p '(add_reference) Traditional referencing not supported by Apache KUDU'
285
+ end
286
+ alias add_belongs_to add_reference
287
+
288
+ def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
289
+ p '(remove_reference) Traditional referencing not supported by Apache KUDU'
290
+ end
291
+
292
+ def foreign_keys(table_name)
293
+ p '(foreign_keys) Foreign keys not supported by Apache KUDU'
294
+ end
295
+
296
+ def add_foreign_key(from_table, to_table, options = {})
297
+ p '(add_foreign_key) Foreign keys not supported by Apache KUDU'
298
+ end
299
+
300
+ def remove_foreign_key(from_table, options_or_to_table = {})
301
+ p '(remove_foreign_key) Foreign keys not supported by Apache KUDU'
302
+ end
303
+
304
+ def foreign_key_exists?(from_table, options_or_to_table = {})
305
+ p '(foreign_key_exists?) Foreign keys not supported by Apache KUDU'
306
+ end
307
+
308
+ def foreign_key_for(from_table, options_or_to_table = {})
309
+ p '(foreign_key_for?) Foreign keys not supported by Apache KUDU'
310
+ end
311
+
312
+ def foreign_key_for!(from_table, options_or_to_table = {})
313
+ p '(foreign_key_for!) Foreign keys not supported by Apache KUDU'
314
+ end
315
+
316
+ def foreign_key_for_column_for(table_name)
317
+ p '(foreign_key_for_column_for) Foreign keys not supported by Apache KUDU'
318
+ end
319
+
320
+ def foreign_key_options(from_table, to_table, options)
321
+ p '(foreign_key_options) Foreign keys not supported by Apache KUDU'
322
+ end
323
+
324
+ def assume_migrated_upto_version(version, migrations_paths)
325
+ migrations_paths = Array(migrations_paths)
326
+ version = version.to_i
327
+ sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
328
+
329
+ migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
330
+ versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
331
+ ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
332
+ end
333
+
334
+ unless migrated.include?(version)
335
+ execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version.to_s)})"
336
+ end
337
+
338
+ inserting = (versions - migrated).select { |v| v < version }
339
+ if inserting.any?
340
+ if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
341
+ raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
342
+ end
343
+ if supports_multi_insert?
344
+ execute insert_versions_sql(inserting)
345
+ else
346
+ inserting.each do |v|
347
+ execute insert_versions_sql(v.to_s)
348
+ end
349
+ end
350
+ end
351
+ end
352
+
353
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
354
+ case type
355
+ when 'integer'
356
+ case limit
357
+ when 1 then 'TINYINT'
358
+ when 2 then 'SMALLINT'
359
+ when 3..4, nil then 'INT'
360
+ when 5..8 then 'BIGINT'
361
+ else
362
+ raise(ActiveRecordError, 'Invalid integer precision')
363
+ end
364
+ else
365
+ super
366
+ end
367
+ end
368
+
369
+ def columns_for_distinct(columns, orders)
370
+ columns
371
+ end
372
+
373
+ def add_timestamps(table_name, options = {})
374
+ options[:null] = false if options[:null].nil?
375
+ add_column table_name, :created_at, :bigint, options
376
+ add_column table_name, :updated_at, :bigint, options
377
+ end
378
+
379
+ def remove_timestamps(table_name, options = {})
380
+ remove_column table_name, :updated_at
381
+ remove_column table_name, :created_at
382
+ end
383
+
384
+ def update_table_definition(table_name, base)
385
+ Table.new(table_name, base)
386
+ end
387
+
388
+ def add_index_options(table_name, column_name, comment: nil, **options)
389
+ p '(add_index_options) Indexing not supported by Apache KUDU'
390
+ end
391
+
392
+ def options_include_default?(options)
393
+ options.include?(:default) && !(options[:null] == false && options[:default].nil?)
394
+ end
395
+
396
+ def change_table_comment(table_name, comment)
397
+ p '(change_table_comment) Altering table comments not supported by Apache KUDU'
398
+ end
399
+
400
+ def change_column_comment(table_name, column_name, comment)
401
+ p '(change_column_comment) Altering column comments not supported by Apache KUDU'
402
+ end
403
+
404
+ private
405
+
406
+ def schema_creation
407
+ ::ActiveRecord::ConnectionAdapters::Kudu::SchemaCreation.new(self)
408
+ end
409
+
410
+ def create_table_definition(*args)
411
+ ::ActiveRecord::ConnectionAdapters::Kudu::TableDefinition.new(*args)
412
+ end
413
+
414
+ def table_structure(table_name)
415
+ quoted = quote_table_name table_name
416
+ connection.query('DESCRIBE ' + quoted)
417
+ end
418
+
419
+ # check if options contains primary_key
420
+ def options_has_primary_key(options)
421
+ options[:primary_key] = false if options[:primary_key].nil?
422
+ options[:primary_key]
423
+ end
424
+
425
+ def primary_keys_contain_column_name(table_name, column_name)
426
+ pks = primary_key(table_name)
427
+ pks.include? column_name.to_s
428
+ end
429
+
430
+ def set_options_from_column_definition(column)
431
+ opt = {}
432
+ opt[:primary_key] = ActiveModel::Type::Boolean.new.cast(column[:primary_key]) if column[:primary_key].present?
433
+ opt[:null] = ActiveModel::Type::Boolean.new.cast(column[:nullable]) if column[:nullable].present?
434
+ opt[:default] = lookup_cast_type(column[:type]).serialize(column[:default_value]) if column[:default_value].present?
435
+ # TODO: Do we have more options ?
436
+ opt
437
+ end
438
+
439
+ # This method will copy existing structure of table with added new field.
440
+ # It works only if we're adding new primary key on existing table.
441
+ def redefine_table_add_primary_key(table_name, column_name, type, options = {})
442
+
443
+ redefined_table_name = table_name + '_redefined'
444
+ temp_table_name = table_name + '_temp'
445
+
446
+ columns = table_structure table_name
447
+ pk_columns = columns.select {|c| c[:primary_key] == 'true'}
448
+ non_pk_columns = columns.select {|c| c[:primary_key] == 'false'}
449
+
450
+ create_table(redefined_table_name, { id: false }) do |td|
451
+
452
+ # existing pk columns
453
+ pk_columns.each do |col|
454
+ td.send col[:type].to_sym, col[:name], set_options_from_column_definition(col)
455
+ end
456
+
457
+ # add new column
458
+ td.send type, column_name, options
459
+
460
+ non_pk_columns.each do |col|
461
+ td.send col[:type].to_sym, col[:name], set_options_from_column_definition(col)
462
+ end
463
+
464
+ end
465
+
466
+ # rename existing table to temp
467
+ rename_table(table_name, temp_table_name)
468
+ # rename newly created to active one
469
+ rename_table(redefined_table_name, table_name)
470
+
471
+ end
472
+
473
+ # This method will copy existing structure of table with primary key field removed.
474
+ # It works only if we're removing primary key on existing table.
475
+ def redefine_table_drop_primary_key(table_name, column_name, type, options = {})
476
+
477
+ redefined_table_name = table_name + '_redefined'
478
+ temp_table_name = table_name + '_temp'
479
+
480
+ columns = table_structure table_name
481
+ columns.reject! { |c| c[:name] == column_name.to_s }
482
+
483
+ create_table(redefined_table_name, { id: false }) do |td|
484
+ columns.each do |col|
485
+ td.send col[:type].to_sym, col[:name], set_options_from_column_definition(col)
486
+ end
487
+ end
488
+
489
+ # rename existing table to temp
490
+ rename_table(table_name, temp_table_name)
491
+ # rename newly created to active one
492
+ rename_table(redefined_table_name, table_name)
493
+
494
+ # copy reduced existing data into new table
495
+ select_qry = columns.map {|col| col[:name].to_s }.join(',')
496
+ copy_qry = "INSERT INTO #{quote_table_name(table_name)} (#{select_qry}) SELECT #{select_qry} FROM #{quote_table_name(temp_table_name)}"
497
+ execute copy_qry
498
+
499
+ # finally, drop temp table
500
+ drop_table(temp_table_name)
501
+
502
+ end
503
+
504
+ end
505
+ end
506
+ end
507
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/connection_adapters/sql_type_metadata'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ # :nodoc:
9
+ class SqlTypeMetadata < ::ActiveRecord::ConnectionAdapters::SqlTypeMetadata
10
+ def initialize(sql_type: nil, type: nil)
11
+ super(sql_type: sql_type, type: type, limit: nil, precision: nil, scale: nil)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/connection_adapters/abstract/schema_definitions'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ # :nodoc:
9
+ class TableDefinition < ::ActiveRecord::ConnectionAdapters::TableDefinition
10
+ attr_reader :external
11
+ attr_reader :partitions_count
12
+ attr_reader :partition_columns
13
+
14
+ def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
15
+ super
16
+ @external = options&.[](:external)
17
+ @partitions_count = options&.[](:partitions_count)
18
+ @partition_columns = options&.[](:partition_columns)
19
+ end
20
+
21
+ def double(*args, **options)
22
+ args.each { |name| column(name, :double, options) }
23
+ end
24
+
25
+ def float(*args, **options)
26
+ args.each { |name| column(name, :float, options) }
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/integer'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ module Type
9
+ # :nodoc:
10
+ class BigInt < ::ActiveModel::Type::Integer
11
+ def type
12
+ :bigint
13
+ end
14
+
15
+ def limit
16
+ 8
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/boolean'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ module Type
9
+ class Boolean < ::ActiveModel::Type::Boolean
10
+
11
+ def type
12
+ :boolean
13
+ end
14
+
15
+ def serialize(value)
16
+ ActiveModel::Type::Boolean.new.cast(value)
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/string'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ module Type
9
+ class Char < ::ActiveModel::Type::String
10
+ def type
11
+ :char
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/helpers/time_value'
4
+ require 'active_record/connection_adapters/kudu/type/time'
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters
8
+ module Kudu
9
+ module Type
10
+ include ::ActiveModel::Type::Helpers::TimeValue
11
+
12
+ # :nodoc:
13
+ class DateTime < ::ActiveRecord::ConnectionAdapters::Kudu::Type::Time
14
+ def type
15
+ :datetime
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/float'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ module Type
9
+ class Double < ::ActiveModel::Type::Float
10
+ def type
11
+ :double
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/type/float'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module Kudu
8
+ module Type
9
+ # :nodoc:
10
+ class Float < ::ActiveModel::Type::Float
11
+ def type
12
+ :float
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end