activerecord-advantage-adapter 0.1.7 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1bdc562c7440301244b1a6a48e97f9d5859bcfb10ff1ad1fdfef14c0bfbc47e
4
- data.tar.gz: 843fcbe3aa8c55be30d7d07315980871e190340ed35938f1ca8e7feddf72f57a
3
+ metadata.gz: 7288057984945ea0eff65cbaa632431020c0740b4ba6db36b6bdf72b797621f2
4
+ data.tar.gz: 48dfd45511b91853dd448e8acab83f8912c7abd048f684673489607210057fa2
5
5
  SHA512:
6
- metadata.gz: 130731dda15fddc1d5f990b5fa8930e810f0c242893049beff250fee337530228c2dc893087fed2a0241183e6323317d99befdd44deb668197519a518e8047c5
7
- data.tar.gz: 2336ed9446e64f67465074831efab9df081eb208056915d4b27780a90714f84c7690095b7856d25d237092e7fa03d4a74898f73326c35c2ea06558920fbc6c46
6
+ metadata.gz: 26ef46605ebc9155616ec9cab5739725be9c393d649ef97321aa59595b8b336db7b4f0557576987c1e3904726e69c52980d66b77b182852d2b0439a2f2149a98
7
+ data.tar.gz: 9ba384335aa4ec03501bf8cc6f7583d1a50c68c4214d415709bb6b2930338571b0271dd26f289f4e1a0779ac98b4ca52b303091815c871d65e7a1355b8a2e131
@@ -1,7 +1,7 @@
1
1
  lib = File.expand_path("../lib", __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
- pkg_version = "0.1.7"
4
+ pkg_version = "1.0.0"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'activerecord-advantage-adapter'
@@ -39,10 +39,12 @@ Gem::Specification.new do |spec|
39
39
  'activerecord-advantage-adapter.gemspec']
40
40
  spec.require_paths = ['lib']
41
41
 
42
+ spec.required_ruby_version = '>= 2.7'
43
+
42
44
  spec.add_development_dependency 'bundler', '~> 2.2.10'
43
45
  spec.add_development_dependency 'rake', '~> 12.3.3'
44
46
  spec.add_development_dependency 'rspec', '~> 3.0'
45
47
 
48
+ spec.add_runtime_dependency 'activerecord', '>= 7.0'
46
49
  spec.add_runtime_dependency 'advantage', '~> 0.1', '>= 0.1.2'
47
- # spec.add_runtime_dependency 'activerecord', '>= 3.2.0'
48
50
  end
@@ -36,28 +36,19 @@ class ADS
36
36
  end
37
37
  end
38
38
 
39
+ if ActiveRecord::ConnectionAdapters.respond_to?(:register)
40
+ ActiveRecord::ConnectionAdapters.register(
41
+ "advantage",
42
+ "ActiveRecord::ConnectionAdapters::AdvantageAdapter",
43
+ "active_record/connection_adapters/advantage_adapter"
44
+ )
45
+ end
46
+
39
47
  module ActiveRecord
40
48
  class Base
41
- DEFAULT_CONFIG = { :username => "adssys", :password => nil }
42
- # Main connection function to Advantage
43
- # Connection Adapter takes four parameters:
44
- # * :database (required, no default). Corresponds to "Data Source=" in connection string
45
- # * :username (optional, default to 'adssys'). Correspons to "User ID=" in connection string
46
- # * :password (optional, deafult to '')
47
- # * :options (optional, defaults to ''). Corresponds to any additional options in connection string
48
-
49
49
  def self.advantage_connection(config)
50
- config = DEFAULT_CONFIG.merge(config)
51
-
52
- raise ArgumentError, "No data source was given. Please add a :database option." unless config.has_key?(:database)
53
-
54
- connection_string = "data source=#{config[:database]};User ID=#{config[:username]};"
55
- connection_string += "Password=#{config[:password]};" unless config[:password].nil?
56
- connection_string += "#{config[:options]};" unless config[:options].nil?
57
- connection_string += "DateFormat=YYYY-MM-DD;"
58
-
50
+ connection_string = ConnectionAdapters::AdvantageAdapter.build_connection_string(config)
59
51
  db = ADS.instance.api.ads_new_connection()
60
-
61
52
  ConnectionAdapters::AdvantageAdapter.new(db, logger, connection_string)
62
53
  end
63
54
  end
@@ -115,12 +106,32 @@ module ActiveRecord
115
106
  end
116
107
 
117
108
  class AdvantageAdapter < AbstractAdapter
118
- def initialize(connection, logger, connection_string = "") #:nodoc:
119
- super(connection, logger)
109
+ DEFAULT_CONFIG = { username: "adssys", password: nil }
110
+
111
+ def self.build_connection_string(config)
112
+ config = DEFAULT_CONFIG.merge(config.symbolize_keys)
113
+ cs = "data source=#{config[:database]};User ID=#{config[:username]};"
114
+ cs += "Password=#{config[:password]};" unless config[:password].nil?
115
+ cs += "#{config[:options]};" unless config[:options].nil?
116
+ cs += "DateFormat=YYYY-MM-DD;"
117
+ cs
118
+ end
119
+
120
+ def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_string = "") #:nodoc:
121
+ if config_or_deprecated_connection.is_a?(Hash)
122
+ super(config_or_deprecated_connection)
123
+ config = config_or_deprecated_connection.symbolize_keys
124
+ raise ArgumentError, "No data source was given. Please add a :database option." unless config.key?(:database)
125
+ @connection_string = self.class.build_connection_string(config)
126
+ @connection = ADS.instance.api.ads_new_connection()
127
+ else
128
+ super(config_or_deprecated_connection, deprecated_logger)
129
+ @connection = config_or_deprecated_connection
130
+ @connection_string = deprecated_connection_string
131
+ end
120
132
  @prepared_statements = false
121
133
  @auto_commit = true
122
134
  @affected_rows = 0
123
- @connection_string = connection_string
124
135
  @visitor = Arel::Visitors::Advantage.new self
125
136
  connect!
126
137
  end
@@ -148,9 +159,12 @@ module ActiveRecord
148
159
  super
149
160
  end
150
161
 
151
- def reconnect! #:nodoc:
152
- disconnect!
153
- connect!
162
+ def reconnect!(restore_transactions: false) #:nodoc:
163
+ super
164
+ end
165
+
166
+ def write_query?(sql) #:nodoc:
167
+ false
154
168
  end
155
169
 
156
170
  def supports_count_distinct? #:nodoc:
@@ -186,11 +200,26 @@ module ActiveRecord
186
200
  }
187
201
  end
188
202
 
189
- # Applies quotations around column names in generated queries
203
+ # AR 7.2 routes instance quote_column_name/quote_table_name through
204
+ # self.class.* (ClassMethods). Define both instance and class forms so
205
+ # the delegation chain never hits AbstractAdapter::ClassMethods which
206
+ # raises NotImplementedError.
207
+ def self.quote_column_name(name)
208
+ %("#{name}")
209
+ end
210
+
211
+ def self.quote_table_name(name)
212
+ %("#{name}")
213
+ end
214
+
190
215
  def quote_column_name(name) #:nodoc:
191
216
  %("#{name}")
192
217
  end
193
218
 
219
+ def quote_table_name(name) #:nodoc:
220
+ %("#{name}")
221
+ end
222
+
194
223
  def quoted_true #:nodoc:
195
224
  '1'
196
225
  end
@@ -200,24 +229,25 @@ module ActiveRecord
200
229
  end
201
230
 
202
231
  # Translate the exception if possible
203
- def translate_exception(exception, message) #:nodoc:
232
+ # Accept both AR < 7.2 positional (message) and AR >= 7.2 keyword args
233
+ def translate_exception(exception, *positional, message: nil, sql: nil, binds: nil, **) #:nodoc:
234
+ message = message || positional.first
204
235
  return super unless exception.respond_to?(:errno)
205
236
 
206
237
  case exception.errno
207
238
  when 2121
208
239
  if exception.sql !~ /^SELECT/i
209
- raise ActiveRecord::ActiveRecordError.new(message)
240
+ ActiveRecord::ActiveRecordError.new(message)
210
241
  else
211
242
  super
212
243
  end
213
244
  when 7076
214
- raise InvalidForeignKey.new(message, exception)
245
+ InvalidForeignKey.new(message, exception)
215
246
  when 7057
216
- raise RecordNotUnique.new(message, exception)
247
+ RecordNotUnique.new(message, exception)
217
248
  else
218
249
  super
219
250
  end
220
- super
221
251
  end
222
252
 
223
253
  # The database update function.
@@ -274,8 +304,13 @@ module ActiveRecord
274
304
  end
275
305
 
276
306
  # Returns a query as an array of arrays
277
- def select_rows(sql, name = nil)
278
- exec_query(sql, name).rows
307
+ def select_rows(arel, name = nil, binds = [], **kwargs)
308
+ exec_query(arel, name, binds).rows
309
+ end
310
+
311
+ def internal_exec_query(sql, name = "SQL", binds = [], **_kwargs) #:nodoc:
312
+ cols, record = execute(sql, name)
313
+ ActiveRecord::Result.new(cols, record)
279
314
  end
280
315
 
281
316
  # Begin a transaction
@@ -301,17 +336,21 @@ module ActiveRecord
301
336
  end
302
337
 
303
338
  # Advantage does not support sizing of integers based on the sytax INTEGER(size).
304
- def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
339
+ # Accept both AR < 7.2 positional (limit, precision, scale) and AR >= 7.2 keyword args
340
+ def type_to_sql(type, *positional, limit: nil, precision: nil, scale: nil, **) #:nodoc:
341
+ limit = limit || positional[0]
342
+ precision = precision || positional[1]
343
+ scale = scale || positional[2]
305
344
  if native_database_types[type]
306
345
  if type == :integer
307
346
  'integer'
308
347
  elsif type == :string && !limit.nil?
309
348
  "varchar (#{limit})"
310
349
  else
311
- super(type, limit, precision, scale)
350
+ super
312
351
  end
313
352
  else
314
- super(type, limit, precision, scale)
353
+ super
315
354
  end
316
355
  end
317
356
 
@@ -326,6 +365,14 @@ module ActiveRecord
326
365
  select(sql, name).map { |row| strip_or_self(row['TABLE_NAME']) }
327
366
  end
328
367
 
368
+ if Rails::VERSION::MAJOR == 5
369
+ # this really needs fixing, in the case where a database contains views, but that requires
370
+ # a "data dictionary", and I'm testing against a collection of "database tables"
371
+ def views(_name = nil)
372
+ []
373
+ end
374
+ end
375
+
329
376
  # Return a list of columns
330
377
  def columns(table_name, _name = nil) #:nodoc:
331
378
  table_structure(table_name).map do |field|
@@ -426,7 +473,7 @@ SQL
426
473
 
427
474
  # Alter a column
428
475
  def change_column(table_name, column_name, type, options = {}) #:nodoc:
429
- add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, type_options[:limit], type_options[:precision], type_options[:scale])}"
476
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, limit: type_options[:limit], precision: type_options[:precision], scale: type_options[:scale])}"
430
477
  add_column_options!(add_column_sql, options)
431
478
  execute(add_column_sql)
432
479
  end
@@ -442,7 +489,7 @@ SQL
442
489
 
443
490
  # Rename a column
444
491
  def rename_column(table_name, column_name, new_column_name) #:nodoc:
445
- execute "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{type_to_sql(type, type_options[:limit], type_options[:precision], type_options[:scale])}"
492
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{type_to_sql(type, limit: type_options[:limit], precision: type_options[:precision], scale: type_options[:scale])}"
446
493
  end
447
494
 
448
495
  # Drop a column from a table
@@ -503,17 +550,49 @@ SQL
503
550
  options.include?(:default) && !(options[:null] == false && options[:default].nil?)
504
551
  end
505
552
 
553
+
506
554
  private
507
555
 
556
+ def type_map
557
+ @type_map ||= Type::TypeMap.new.tap { |m| initialize_type_map(m) }
558
+ end
559
+
560
+ # copied from "connection_adapters/abstract_adapter.rb"
561
+ def register_class(mapping, key, klass)
562
+ mapping.register_type(key) do |*args|
563
+ klass.new
564
+ end
565
+ end
566
+
508
567
  # Used in the lookup_cast_type procedure
509
- def initialize_type_map(m = type_map)
510
- super
568
+ def initialize_type_map(m)
569
+ register_class m, %r(boolean)i, Type::Boolean
570
+ register_class m, %r(char)i, Type::String
571
+ register_class m, %r(binary)i, Type::Binary
572
+ register_class m, %r(text)i, Type::Text
573
+ register_class m, %r(date)i, Type::Date
574
+ register_class m, %r(time)i, Type::Time
575
+ register_class m, %r(datetime)i, Type::DateTime
576
+ register_class m, %r(float)i, Type::Float
577
+ register_class m, %r(int)i, Type::Integer
578
+ register_class m, %r(decimal)i, Type::Decimal
579
+
580
+ m.alias_type %r(logical)i, "boolean"
581
+ m.alias_type %r(numeric)i, "decimal"
582
+ m.alias_type %r(string)i, "char"
511
583
  m.alias_type %r(memo)i, "char"
584
+ m.alias_type %r(image)i, "binary"
585
+ m.alias_type %r(varchar)i, "char"
586
+ m.alias_type %r(timestamp)i, "datetime"
587
+ m.alias_type %r(number)i, "decimal"
588
+ m.alias_type %r(money)i, "decimal"
589
+ m.alias_type %r(double)i, "float"
590
+
512
591
  m.alias_type %r(long binary)i, "binary"
513
592
  m.alias_type %r(integer)i, "int"
514
593
  m.alias_type %r(short)i, "int"
515
594
  m.alias_type %r(autoinc)i, "int"
516
- m.alias_type %r(logical)i, "boolean"
595
+ m.alias_type %r(raw)i, "binary"
517
596
  end
518
597
 
519
598
  # Connect
@@ -523,6 +602,14 @@ SQL
523
602
  error = ADS.instance.api.ads_error(@connection)
524
603
  raise ActiveRecord::ActiveRecordError.new("#{error}: Cannot Establish Connection")
525
604
  end
605
+ @raw_connection = @connection
606
+ end
607
+
608
+ # AR 7.2 requires private #reconnect; called by the public reconnect!
609
+ def reconnect #:nodoc:
610
+ ADS.instance.api.ads_disconnect(@connection)
611
+ @connection = ADS.instance.api.ads_new_connection()
612
+ connect!
526
613
  end
527
614
 
528
615
  # The database execution function
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-advantage-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edgar Sherman
8
8
  - Jon Adams
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2023-05-31 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
@@ -53,6 +52,20 @@ dependencies:
53
52
  - - "~>"
54
53
  - !ruby/object:Gem::Version
55
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '7.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '7.0'
56
69
  - !ruby/object:Gem::Dependency
57
70
  name: advantage
58
71
  requirement: !ruby/object:Gem::Requirement
@@ -95,7 +108,6 @@ metadata:
95
108
  homepage_uri: http://devzone.advantagedatabase.com
96
109
  source_code_uri: https://github.com/t12nslookup/activerecord-advantage-adapter/
97
110
  changelog_uri: https://github.com/t12nslookup/activerecord-advantage-adapter/blob/main/CHANGELOG.md
98
- post_install_message:
99
111
  rdoc_options: []
100
112
  require_paths:
101
113
  - lib
@@ -103,15 +115,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
115
  requirements:
104
116
  - - ">="
105
117
  - !ruby/object:Gem::Version
106
- version: '0'
118
+ version: '2.7'
107
119
  required_rubygems_version: !ruby/object:Gem::Requirement
108
120
  requirements:
109
121
  - - ">="
110
122
  - !ruby/object:Gem::Version
111
123
  version: '0'
112
124
  requirements: []
113
- rubygems_version: 3.1.6
114
- signing_key:
125
+ rubygems_version: 3.6.9
115
126
  specification_version: 4
116
127
  summary: ActiveRecord driver for Advantage
117
128
  test_files: []