ruby-plsql 0.5.3 → 0.8.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 (57) hide show
  1. checksums.yaml +5 -5
  2. data/.github/stale.yml +37 -0
  3. data/.github/workflows/rubocop.yml +37 -0
  4. data/.github/workflows/test.yml +69 -0
  5. data/.rubocop.yml +147 -0
  6. data/.travis.yml +88 -0
  7. data/.travis/oracle/download.sh +15 -0
  8. data/.travis/oracle/install.sh +32 -0
  9. data/.travis/setup_accounts.sh +9 -0
  10. data/Gemfile +17 -9
  11. data/History.txt +76 -0
  12. data/README.md +29 -6
  13. data/Rakefile +31 -26
  14. data/VERSION +1 -1
  15. data/Vagrantfile +4 -4
  16. data/ci/network/admin/tnsnames.ora +7 -0
  17. data/ci/setup_accounts.sh +9 -0
  18. data/gemfiles/Gemfile.activerecord-5.0 +21 -0
  19. data/gemfiles/Gemfile.activerecord-5.1 +21 -0
  20. data/gemfiles/Gemfile.activerecord-5.2 +21 -0
  21. data/gemfiles/Gemfile.activerecord-6.0 +21 -0
  22. data/gemfiles/Gemfile.activerecord-6.1 +21 -0
  23. data/gemfiles/Gemfile.activerecord-main +21 -0
  24. data/lib/plsql/connection.rb +19 -22
  25. data/lib/plsql/helpers.rb +1 -3
  26. data/lib/plsql/jdbc_connection.rb +70 -68
  27. data/lib/plsql/oci8_patches.rb +2 -2
  28. data/lib/plsql/oci_connection.rb +62 -77
  29. data/lib/plsql/package.rb +61 -46
  30. data/lib/plsql/procedure.rb +358 -78
  31. data/lib/plsql/procedure_call.rb +508 -463
  32. data/lib/plsql/schema.rb +96 -101
  33. data/lib/plsql/sequence.rb +10 -13
  34. data/lib/plsql/sql_statements.rb +9 -11
  35. data/lib/plsql/table.rb +60 -63
  36. data/lib/plsql/type.rb +71 -76
  37. data/lib/plsql/variable.rb +90 -94
  38. data/lib/plsql/version.rb +1 -1
  39. data/lib/plsql/view.rb +16 -19
  40. data/ruby-plsql.gemspec +55 -35
  41. data/spec/plsql/connection_spec.rb +72 -66
  42. data/spec/plsql/package_spec.rb +63 -14
  43. data/spec/plsql/procedure_spec.rb +603 -261
  44. data/spec/plsql/schema_spec.rb +47 -23
  45. data/spec/plsql/sequence_spec.rb +2 -2
  46. data/spec/plsql/sql_statements_spec.rb +6 -6
  47. data/spec/plsql/table_spec.rb +84 -79
  48. data/spec/plsql/type_spec.rb +24 -30
  49. data/spec/plsql/variable_spec.rb +80 -88
  50. data/spec/plsql/version_spec.rb +4 -4
  51. data/spec/plsql/view_spec.rb +42 -42
  52. data/spec/spec_helper.rb +38 -35
  53. data/spec/support/create_arunit_user.sql +2 -0
  54. data/spec/support/custom_config.rb.sample +14 -0
  55. data/spec/support/test_db.rb +12 -13
  56. data/spec/support/unlock_and_setup_hr_user.sql +2 -0
  57. metadata +111 -34
data/lib/plsql/schema.rb CHANGED
@@ -13,13 +13,13 @@ module PLSQL
13
13
  @@schemas[connection_alias] = self.new
14
14
  end
15
15
  end
16
-
17
16
  end
18
17
 
19
18
  def initialize(raw_conn = nil, schema = nil, original_schema = nil) #:nodoc:
20
19
  self.connection = raw_conn
21
20
  @schema_name = schema ? schema.to_s.upcase : nil
22
21
  @original_schema = original_schema
22
+ @dbms_output_stream = nil
23
23
  end
24
24
 
25
25
  # Returns connection wrapper object (this is not raw OCI8 or JDBC connection!)
@@ -35,7 +35,7 @@ module PLSQL
35
35
  end
36
36
 
37
37
  # Set connection to OCI8 or JDBC connection:
38
- #
38
+ #
39
39
  # plsql.connection = OCI8.new(database_user, database_password, database_name)
40
40
  #
41
41
  # or
@@ -90,7 +90,7 @@ module PLSQL
90
90
  # Current Oracle schema name
91
91
  def schema_name
92
92
  return nil unless connection
93
- @schema_name ||= select_first("SELECT SYS_CONTEXT('userenv','session_user') FROM dual")[0]
93
+ @schema_name ||= select_first("SELECT SYS_CONTEXT('userenv','current_schema') FROM dual")[0]
94
94
  end
95
95
 
96
96
  # Default timezone to which database values will be converted - :utc or :local
@@ -131,9 +131,9 @@ module PLSQL
131
131
  end
132
132
 
133
133
  # Seet DBMS_OUTPUT buffer size (default is 20_000). Example:
134
- #
134
+ #
135
135
  # plsql.dbms_output_buffer_size = 100_000
136
- #
136
+ #
137
137
  def dbms_output_buffer_size=(value)
138
138
  @dbms_output_buffer_size = value
139
139
  end
@@ -142,9 +142,9 @@ module PLSQL
142
142
  DBMS_OUTPUT_MAX_LINES = 2147483647
143
143
 
144
144
  # Specify IO stream where to log DBMS_OUTPUT from PL/SQL procedures. Example:
145
- #
145
+ #
146
146
  # plsql.dbms_output_stream = STDOUT
147
- #
147
+ #
148
148
  def dbms_output_stream=(stream)
149
149
  @dbms_output_stream = stream
150
150
  if @dbms_output_stream.nil? && @connection
@@ -163,118 +163,113 @@ module PLSQL
163
163
 
164
164
  private
165
165
 
166
- def reset_instance_variables
167
- if @connection
168
- @schema_objects = {}
169
- else
170
- @schema_objects = nil
166
+ def reset_instance_variables
167
+ if @connection
168
+ @schema_objects = {}
169
+ else
170
+ @schema_objects = nil
171
+ end
172
+ @schema_name = nil
173
+ @default_timezone = nil
171
174
  end
172
- @schema_name = nil
173
- @default_timezone = nil
174
- end
175
175
 
176
- def method_missing(method, *args, &block)
177
- raise ArgumentError, "No database connection" unless connection
178
- # search in database if not in cache at first
179
- object = (@schema_objects[method] ||= find_database_object(method) || find_other_schema(method) ||
180
- find_public_synonym(method) || find_standard_procedure(method))
176
+ def method_missing(method, *args, &block)
177
+ raise ArgumentError, "No database connection" unless connection
178
+ # search in database if not in cache at first
179
+ object = (@schema_objects[method] ||= find_database_object(method) || find_other_schema(method) ||
180
+ find_public_synonym(method) || find_standard_procedure(method))
181
181
 
182
- raise ArgumentError, "No database object '#{method.to_s.upcase}' found" unless object
182
+ raise ArgumentError, "No database object '#{method.to_s.upcase}' found" unless object
183
183
 
184
- if object.is_a?(Procedure)
185
- object.exec(*args, &block)
186
- elsif object.is_a?(Type) && !args.empty?
187
- object.new(*args, &block)
188
- else
189
- object
184
+ if object.is_a?(Procedure)
185
+ object.exec(*args, &block)
186
+ elsif object.is_a?(Type) && !args.empty?
187
+ object.new(*args, &block)
188
+ else
189
+ object
190
+ end
190
191
  end
191
- end
192
192
 
193
- def find_database_object(name, override_schema_name = nil)
194
- object_schema_name = override_schema_name || schema_name
195
- object_name = name.to_s.upcase
196
- if row = select_first(
197
- "SELECT o.object_type, o.object_id, o.status,
198
- (CASE WHEN o.object_type = 'PACKAGE'
199
- THEN (SELECT ob.status FROM all_objects ob
200
- WHERE ob.owner = o.owner AND ob.object_name = o.object_name AND ob.object_type = 'PACKAGE BODY')
201
- ELSE NULL END) body_status
193
+ def find_database_object(name, override_schema_name = nil)
194
+ object_schema_name = override_schema_name || schema_name
195
+ object_name = name.to_s.upcase
196
+ if row = select_first(
197
+ "SELECT o.object_type, o.object_id
202
198
  FROM all_objects o
203
199
  WHERE owner = :owner AND object_name = :object_name
204
200
  AND object_type IN ('PROCEDURE','FUNCTION','PACKAGE','TABLE','VIEW','SEQUENCE','TYPE','SYNONYM')",
205
- object_schema_name, object_name)
206
- object_type, object_id, status, body_status = row
207
- raise ArgumentError, "Database object '#{object_schema_name}.#{object_name}' is not in valid status\n#{
208
- _errors(object_schema_name, object_name, object_type)}" if status == 'INVALID'
209
- raise ArgumentError, "Package '#{object_schema_name}.#{object_name}' body is not in valid status\n#{
210
- _errors(object_schema_name, object_name, 'PACKAGE BODY')}" if body_status == 'INVALID'
211
- case object_type
212
- when 'PROCEDURE', 'FUNCTION'
213
- if (connection.database_version <=> [11, 1, 0, 0]) >= 0
214
- row = select_first(
215
- "SELECT p.object_id FROM all_procedures p
216
- WHERE p.owner = :owner
217
- AND p.object_name = :object_name
218
- AND p.object_type = :object_type",
219
- object_schema_name, object_name, object_type)
220
- object_id = row[0]
201
+ object_schema_name, object_name)
202
+ object_type, object_id = row
203
+ case object_type
204
+ when "PROCEDURE", "FUNCTION"
205
+ if (connection.database_version <=> [11, 1, 0, 0]) >= 0
206
+ if row = select_first(
207
+ "SELECT p.object_id FROM all_procedures p
208
+ WHERE p.owner = :owner
209
+ AND p.object_name = :object_name
210
+ AND p.object_type = :object_type",
211
+ object_schema_name, object_name, object_type)
212
+ object_id = row[0]
213
+ else
214
+ raise ArgumentError, "Database object '#{object_schema_name}.#{object_name}' is not in valid status\n#{
215
+ _errors(object_schema_name, object_name, object_type)}"
216
+ end
217
+ end
218
+ Procedure.new(self, name, nil, override_schema_name, object_id)
219
+ when "PACKAGE"
220
+ Package.new(self, name, override_schema_name)
221
+ when "TABLE"
222
+ Table.new(self, name, override_schema_name)
223
+ when "VIEW"
224
+ View.new(self, name, override_schema_name)
225
+ when "SEQUENCE"
226
+ Sequence.new(self, name, override_schema_name)
227
+ when "TYPE"
228
+ Type.new(self, name, override_schema_name)
229
+ when "SYNONYM"
230
+ target_schema_name, target_object_name = @connection.describe_synonym(object_schema_name, object_name)
231
+ find_database_object(target_object_name, target_schema_name)
221
232
  end
222
- Procedure.new(self, name, nil, override_schema_name, object_id)
223
- when 'PACKAGE'
224
- Package.new(self, name, override_schema_name)
225
- when 'TABLE'
226
- Table.new(self, name, override_schema_name)
227
- when 'VIEW'
228
- View.new(self, name, override_schema_name)
229
- when 'SEQUENCE'
230
- Sequence.new(self, name, override_schema_name)
231
- when 'TYPE'
232
- Type.new(self, name, override_schema_name)
233
- when 'SYNONYM'
234
- target_schema_name, target_object_name = @connection.describe_synonym(object_schema_name, object_name)
235
- find_database_object(target_object_name, target_schema_name)
236
233
  end
237
234
  end
238
- end
239
235
 
240
- def _errors(object_schema_name, object_name, object_type)
241
- result = ""
242
- previous_line = 0
243
- select_all(
244
- "SELECT e.line, e.position, e.text error_text, s.text source_text
245
- FROM all_errors e, all_source s
246
- WHERE e.owner = :owner AND e.name = :name AND e.type = :type
247
- AND s.owner = e.owner AND s.name = e.name AND s.type = e.type AND s.line = e.line
248
- ORDER BY e.sequence",
249
- object_schema_name, object_name, object_type
250
- ).each do |line, position, error_text, source_text|
251
- result << "Error on line #{'%4d' % line}: #{source_text}" if line > previous_line
252
- result << " position #{'%4d' % position}: #{error_text}\n"
253
- previous_line = line
236
+ def _errors(object_schema_name, object_name, object_type)
237
+ result = ""
238
+ previous_line = 0
239
+ select_all(
240
+ "SELECT e.line, e.position, e.text error_text, s.text source_text
241
+ FROM all_errors e, all_source s
242
+ WHERE e.owner = :owner AND e.name = :name AND e.type = :type
243
+ AND s.owner = e.owner AND s.name = e.name AND s.type = e.type AND s.line = e.line
244
+ ORDER BY e.sequence",
245
+ object_schema_name, object_name, object_type
246
+ ).each do |line, position, error_text, source_text|
247
+ result << "Error on line #{'%4d' % line}: #{source_text}" if line > previous_line
248
+ result << " position #{'%4d' % position}: #{error_text}\n"
249
+ previous_line = line
250
+ end
251
+ result unless result.empty?
254
252
  end
255
- result unless result.empty?
256
- end
257
253
 
258
- def find_other_schema(name)
259
- return nil if @original_schema
260
- if select_first("SELECT username FROM all_users WHERE username = :username", name.to_s.upcase)
261
- Schema.new(connection, name, self)
262
- else
263
- nil
254
+ def find_other_schema(name)
255
+ return nil if @original_schema
256
+ if select_first("SELECT username FROM all_users WHERE username = :username", name.to_s.upcase)
257
+ Schema.new(connection, name, self)
258
+ else
259
+ nil
260
+ end
264
261
  end
265
- end
266
-
267
- def find_standard_procedure(name)
268
- return nil if @original_schema
269
- Procedure.find(self, name, 'STANDARD', 'SYS')
270
- end
271
262
 
272
- def find_public_synonym(name)
273
- return nil if @original_schema
274
- target_schema_name, target_object_name = @connection.describe_synonym('PUBLIC', name)
275
- find_database_object(target_object_name, target_schema_name) if target_schema_name
276
- end
263
+ def find_standard_procedure(name)
264
+ return nil if @original_schema
265
+ Procedure.find(self, name, "STANDARD", "SYS")
266
+ end
277
267
 
268
+ def find_public_synonym(name)
269
+ return nil if @original_schema
270
+ target_schema_name, target_object_name = @connection.describe_synonym("PUBLIC", name)
271
+ find_database_object(target_object_name, target_schema_name) if target_schema_name
272
+ end
278
273
  end
279
274
  end
280
275
 
@@ -1,22 +1,21 @@
1
1
  module PLSQL
2
-
3
2
  module SequenceClassMethods #:nodoc:
4
3
  def find(schema, sequence)
5
4
  if schema.select_first(
6
- "SELECT sequence_name FROM all_sequences
7
- WHERE sequence_owner = :owner
8
- AND sequence_name = :sequence_name",
5
+ "SELECT sequence_name FROM all_sequences
6
+ WHERE sequence_owner = :owner
7
+ AND sequence_name = :sequence_name",
9
8
  schema.schema_name, sequence.to_s.upcase)
10
9
  new(schema, sequence)
11
10
  # search for synonym
12
11
  elsif (row = schema.select_first(
13
- "SELECT t.sequence_owner, t.sequence_name
14
- FROM all_synonyms s, all_sequences t
15
- WHERE s.owner IN (:owner, 'PUBLIC')
16
- AND s.synonym_name = :synonym_name
17
- AND t.sequence_owner = s.table_owner
18
- AND t.sequence_name = s.table_name
19
- ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0)",
12
+ "SELECT t.sequence_owner, t.sequence_name
13
+ FROM all_synonyms s, all_sequences t
14
+ WHERE s.owner IN (:owner, 'PUBLIC')
15
+ AND s.synonym_name = :synonym_name
16
+ AND t.sequence_owner = s.table_owner
17
+ AND t.sequence_name = s.table_name
18
+ ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0)",
20
19
  schema.schema_name, sequence.to_s.upcase))
21
20
  new(schema, row[1], row[0])
22
21
  else
@@ -43,7 +42,5 @@ module PLSQL
43
42
  def currval
44
43
  @schema.select_one "SELECT \"#{@schema_name}\".\"#{@sequence_name}\".CURRVAL FROM dual"
45
44
  end
46
-
47
45
  end
48
-
49
46
  end
@@ -16,7 +16,7 @@ module PLSQL
16
16
  end
17
17
 
18
18
  # Select :first or :all values. Examples:
19
- #
19
+ #
20
20
  # plsql.select :first, "SELECT * FROM employees WHERE employee_id = :1", 1
21
21
  # plsql.select :all, "SELECT * FROM employees ORDER BY employee_id"
22
22
  def select(*args)
@@ -43,9 +43,9 @@ module PLSQL
43
43
 
44
44
  # Execute COMMIT in current database session.
45
45
  # Use beforehand
46
- #
46
+ #
47
47
  # plsql.connection.autocommit = false
48
- #
48
+ #
49
49
  # to turn off automatic commits after each statement.
50
50
  def commit
51
51
  @connection.commit
@@ -53,9 +53,9 @@ module PLSQL
53
53
 
54
54
  # Execute ROLLBACK in current database session.
55
55
  # Use beforehand
56
- #
56
+ #
57
57
  # plsql.connection.autocommit = false
58
- #
58
+ #
59
59
  # to turn off automatic commits after each statement.
60
60
  def rollback
61
61
  @connection.rollback
@@ -64,9 +64,9 @@ module PLSQL
64
64
  # Create SAVEPOINT with specified name. Later use +rollback_to+ method to roll changes back
65
65
  # to specified savepoint.
66
66
  # Use beforehand
67
- #
67
+ #
68
68
  # plsql.connection.autocommit = false
69
- #
69
+ #
70
70
  # to turn off automatic commits after each statement.
71
71
  def savepoint(name)
72
72
  execute "SAVEPOINT #{name}"
@@ -74,14 +74,12 @@ module PLSQL
74
74
 
75
75
  # Roll back changes to specified savepoint (that was created using +savepoint+ method)
76
76
  # Use beforehand
77
- #
77
+ #
78
78
  # plsql.connection.autocommit = false
79
- #
79
+ #
80
80
  # to turn off automatic commits after each statement.
81
81
  def rollback_to(name)
82
82
  execute "ROLLBACK TO #{name}"
83
83
  end
84
-
85
84
  end
86
85
  end
87
-
data/lib/plsql/table.rb CHANGED
@@ -1,28 +1,27 @@
1
1
  module PLSQL
2
-
3
2
  module TableClassMethods #:nodoc:
4
3
  def find(schema, table)
5
4
  if schema.select_first(
6
- "SELECT table_name FROM all_tables
7
- WHERE owner = :owner
8
- AND table_name = :table_name",
5
+ "SELECT table_name FROM all_tables
6
+ WHERE owner = :owner
7
+ AND table_name = :table_name",
9
8
  schema.schema_name, table.to_s.upcase)
10
9
  new(schema, table)
11
10
  # search for synonym
12
11
  elsif (row = schema.select_first(
13
- "SELECT t.owner, t.table_name
14
- FROM all_synonyms s, all_tables t
15
- WHERE s.owner = :owner
16
- AND s.synonym_name = :synonym_name
17
- AND t.owner = s.table_owner
18
- AND t.table_name = s.table_name
19
- UNION ALL
20
- SELECT t.owner, t.table_name
21
- FROM all_synonyms s, all_tables t
22
- WHERE s.owner = 'PUBLIC'
23
- AND s.synonym_name = :synonym_name
24
- AND t.owner = s.table_owner
25
- AND t.table_name = s.table_name",
12
+ "SELECT t.owner, t.table_name
13
+ FROM all_synonyms s, all_tables t
14
+ WHERE s.owner = :owner
15
+ AND s.synonym_name = :synonym_name
16
+ AND t.owner = s.table_owner
17
+ AND t.table_name = s.table_name
18
+ UNION ALL
19
+ SELECT t.owner, t.table_name
20
+ FROM all_synonyms s, all_tables t
21
+ WHERE s.owner = 'PUBLIC'
22
+ AND s.synonym_name = :synonym_name
23
+ AND t.owner = s.table_owner
24
+ AND t.table_name = s.table_name",
26
25
  schema.schema_name, table.to_s.upcase, table.to_s.upcase))
27
26
  new(schema, row[1], row[0])
28
27
  else
@@ -58,34 +57,34 @@ module PLSQL
58
57
  ) do |r|
59
58
  column_name, position,
60
59
  data_type, data_length, data_precision, data_scale, char_used,
61
- data_type_owner, data_type_mod, typecode, nullable, data_default = r
60
+ data_type_owner, _, typecode, nullable, data_default = r
62
61
  # remove scale (n) from data_type (returned for TIMESTAMPs and INTERVALs)
63
- data_type.sub!(/\(\d+\)/,'')
62
+ data_type.sub!(/\(\d+\)/, "")
64
63
  # store column metadata
65
64
  @columns[column_name.downcase.to_sym] = {
66
- :position => position && position.to_i,
67
- :data_type => data_type_owner && (typecode == 'COLLECTION' ? 'TABLE' : 'OBJECT' ) || data_type,
68
- :data_length => data_type_owner ? nil : data_length && data_length.to_i,
69
- :data_precision => data_precision && data_precision.to_i,
70
- :data_scale => data_scale && data_scale.to_i,
71
- :char_used => char_used,
72
- :type_owner => data_type_owner,
73
- :type_name => data_type_owner && data_type,
74
- :sql_type_name => data_type_owner && "#{data_type_owner}.#{data_type}",
75
- :nullable => nullable == 'Y', # store as true or false
76
- :data_default => data_default && data_default.strip # remove leading and trailing whitespace
65
+ position: position && position.to_i,
66
+ data_type: data_type_owner && (typecode == "COLLECTION" ? "TABLE" : "OBJECT") || data_type,
67
+ data_length: data_type_owner ? nil : data_length && data_length.to_i,
68
+ data_precision: data_precision && data_precision.to_i,
69
+ data_scale: data_scale && data_scale.to_i,
70
+ char_used: char_used,
71
+ type_owner: data_type_owner,
72
+ type_name: data_type_owner && data_type,
73
+ sql_type_name: data_type_owner && "#{data_type_owner}.#{data_type}",
74
+ nullable: nullable == "Y", # store as true or false
75
+ data_default: data_default && data_default.strip # remove leading and trailing whitespace
77
76
  }
78
77
  end
79
78
  end
80
79
 
81
80
  # list of table column names
82
81
  def column_names
83
- @column_names ||= @columns.keys.sort_by{|k| columns[k][:position]}
82
+ @column_names ||= @columns.keys.sort_by { |k| columns[k][:position] }
84
83
  end
85
84
 
86
85
  # General select method with :first, :all or :count as first parameter.
87
86
  # It is recommended to use #first, #all or #count method instead of this one.
88
- def select(first_or_all, sql_params='', *bindvars)
87
+ def select(first_or_all, sql_params = "", *bindvars)
89
88
  case first_or_all
90
89
  when :first, :all
91
90
  select_sql = "SELECT * "
@@ -102,7 +101,7 @@ module PLSQL
102
101
  raise ArgumentError, "Cannot specify bind variables when passing WHERE conditions as Hash" unless bindvars.empty?
103
102
  where_sqls = []
104
103
  order_by_sql = nil
105
- sql_params.each do |k,v|
104
+ sql_params.each do |k, v|
106
105
  if k == :order_by
107
106
  order_by_sql = " ORDER BY #{v} "
108
107
  elsif v.nil? || v == :is_null
@@ -114,7 +113,7 @@ module PLSQL
114
113
  bindvars << v
115
114
  end
116
115
  end
117
- select_sql << "WHERE " << where_sqls.join(' AND ') unless where_sqls.empty?
116
+ select_sql << "WHERE " << where_sqls.join(" AND ") unless where_sqls.empty?
118
117
  select_sql << order_by_sql if order_by_sql
119
118
  else
120
119
  raise ArgumentError, "Only String or Hash can be provided as SQL condition argument"
@@ -131,48 +130,49 @@ module PLSQL
131
130
  # plsql.employees.all
132
131
  # plsql.employees.all(:order_by => :employee_id)
133
132
  # plsql.employees.all("WHERE employee_id > :employee_id", 5)
134
- #
135
- def all(sql='', *bindvars)
133
+ #
134
+ def all(sql = "", *bindvars)
136
135
  select(:all, sql, *bindvars)
137
136
  end
138
137
 
139
138
  # Select first table record using optional conditions. Examples:
140
- #
139
+ #
141
140
  # plsql.employees.first
142
141
  # plsql.employees.first(:employee_id => 1)
143
142
  # plsql.employees.first("WHERE employee_id = 1")
144
143
  # plsql.employees.first("WHERE employee_id = :employee_id", 1)
145
- #
146
- def first(sql='', *bindvars)
144
+ #
145
+ def first(sql = "", *bindvars)
147
146
  select(:first, sql, *bindvars)
148
147
  end
149
148
 
150
149
  # Count table records using optional conditions. Examples:
151
- #
150
+ #
152
151
  # plsql.employees.count
153
152
  # plsql.employees.count("WHERE employee_id > :employee_id", 5)
154
- #
155
- def count(sql='', *bindvars)
153
+ #
154
+ def count(sql = "", *bindvars)
156
155
  select(:count, sql, *bindvars)
157
156
  end
158
157
 
159
158
  # Insert record or records in table. Examples:
160
- #
159
+ #
161
160
  # employee = { :employee_id => 1, :first_name => 'First', :last_name => 'Last', :hire_date => Time.local(2000,01,31) }
162
161
  # plsql.employees.insert employee
163
162
  # # => INSERT INTO employees VALUES (1, 'First', 'Last', ...)
164
- #
163
+ #
165
164
  # employees = [employee1, employee2, ... ] # array of many Hashes
166
165
  # plsql.employees.insert employees
167
166
  #
168
167
  def insert(record)
169
168
  # if Array of records is passed then insert each individually
170
169
  if record.is_a?(Array)
171
- record.each {|r| insert(r)}
170
+ record.each { |r| insert(r) }
172
171
  return nil
173
172
  end
174
173
 
175
174
  table_proc = TableProcedure.new(@schema, self, :insert)
175
+ record = record.map { |k, v| [k.downcase.to_sym, v] }.to_h
176
176
  table_proc.add_insert_arguments(record)
177
177
 
178
178
  call = ProcedureCall.new(table_proc, table_proc.argument_values)
@@ -180,15 +180,15 @@ module PLSQL
180
180
  end
181
181
 
182
182
  # Insert record or records in table using array of values. Examples:
183
- #
183
+ #
184
184
  # # with values for all columns
185
185
  # plsql.employees.insert_values [1, 'First', 'Last', Time.local(2000,01,31)]
186
186
  # # => INSERT INTO employees VALUES (1, 'First', 'Last', ...)
187
- #
187
+ #
188
188
  # # with values for specified columns
189
189
  # plsql.employees.insert_values [:employee_id, :first_name, :last_name], [1, 'First', 'Last']
190
190
  # # => INSERT INTO employees (employee_id, first_name, last_name) VALUES (1, 'First', 'Last')
191
- #
191
+ #
192
192
  # # with values for many records
193
193
  # plsql.employees.insert_values [:employee_id, :first_name, :last_name], [1, 'First', 'Last'], [2, 'Second', 'Last']
194
194
  # # => INSERT INTO employees (employee_id, first_name, last_name) VALUES (1, 'First', 'Last')
@@ -197,7 +197,7 @@ module PLSQL
197
197
  def insert_values(*args)
198
198
  raise ArgumentError, "no arguments given" unless args.first
199
199
  # if first argument is array of symbols then use it as list of fields
200
- if args.first.all?{|a| a.instance_of?(Symbol)}
200
+ if args.first.all? { |a| a.instance_of?(Symbol) }
201
201
  fields = args.shift
202
202
  # otherwise use all columns as list of fields
203
203
  else
@@ -211,14 +211,14 @@ module PLSQL
211
211
  end
212
212
 
213
213
  # Update table records using optional conditions. Example:
214
- #
214
+ #
215
215
  # plsql.employees.update(:first_name => 'Second', :where => {:employee_id => 1})
216
216
  # # => UPDATE employees SET first_name = 'Second' WHERE employee_id = 1
217
217
  #
218
218
  def update(params)
219
219
  raise ArgumentError, "Only Hash parameter can be passed to table update method" unless params.is_a?(Hash)
220
220
  where = params.delete(:where)
221
-
221
+
222
222
  table_proc = TableProcedure.new(@schema, self, :update)
223
223
  table_proc.add_set_arguments(params)
224
224
  table_proc.add_where_arguments(where) if where
@@ -227,11 +227,11 @@ module PLSQL
227
227
  end
228
228
 
229
229
  # Delete table records using optional conditions. Example:
230
- #
230
+ #
231
231
  # plsql.employees.delete(:employee_id => 1)
232
232
  # # => DELETE FROM employees WHERE employee_id = 1
233
- #
234
- def delete(sql_params='', *bindvars)
233
+ #
234
+ def delete(sql_params = "", *bindvars)
235
235
  delete_sql = "DELETE FROM \"#{@schema_name}\".\"#{@table_name}\" "
236
236
  case sql_params
237
237
  when String
@@ -239,11 +239,11 @@ module PLSQL
239
239
  when Hash
240
240
  raise ArgumentError, "Cannot specify bind variables when passing WHERE conditions as Hash" unless bindvars.empty?
241
241
  where_sqls = []
242
- sql_params.each do |k,v|
242
+ sql_params.each do |k, v|
243
243
  where_sqls << "#{k} = :#{k}"
244
244
  bindvars << v
245
245
  end
246
- delete_sql << "WHERE " << where_sqls.join(' AND ') unless where_sqls.empty?
246
+ delete_sql << "WHERE " << where_sqls.join(" AND ") unless where_sqls.empty?
247
247
  else
248
248
  raise ArgumentError, "Only String or Hash can be provided as SQL condition argument"
249
249
  end
@@ -287,7 +287,7 @@ module PLSQL
287
287
  end
288
288
 
289
289
  def add_insert_arguments(params)
290
- params.each do |k,v|
290
+ params.each do |k, v|
291
291
  raise ArgumentError, "Invalid column name #{k.inspect} specified as argument" unless (column_metadata = @table.columns[k])
292
292
  @argument_list[0] << k
293
293
  @arguments[0][k] = column_metadata
@@ -296,7 +296,7 @@ module PLSQL
296
296
  end
297
297
 
298
298
  def add_set_arguments(params)
299
- params.each do |k,v|
299
+ params.each do |k, v|
300
300
  raise ArgumentError, "Invalid column name #{k.inspect} specified as argument" unless (column_metadata = @table.columns[k])
301
301
  @argument_list[0] << k
302
302
  @arguments[0][k] = column_metadata
@@ -308,7 +308,7 @@ module PLSQL
308
308
  def add_where_arguments(params)
309
309
  case params
310
310
  when Hash
311
- params.each do |k,v|
311
+ params.each do |k, v|
312
312
  raise ArgumentError, "Invalid column name #{k.inspect} specified as argument" unless (column_metadata = @table.columns[k])
313
313
  @argument_list[0] << :"w_#{k}"
314
314
  @arguments[0][:"w_#{k}"] = column_metadata
@@ -332,7 +332,7 @@ module PLSQL
332
332
  def call_sql(params_string)
333
333
  case @operation
334
334
  when :insert
335
- "INSERT INTO \"#{@table.schema_name}\".\"#{@table.table_name}\"(#{@argument_list[0].map{|a| a.to_s}.join(', ')}) VALUES (#{params_string});\n"
335
+ "INSERT INTO \"#{@table.schema_name}\".\"#{@table.table_name}\"(#{@argument_list[0].map { |a| a.to_s }.join(', ')}) VALUES (#{params_string});\n"
336
336
  when :update
337
337
  update_sql = "UPDATE \"#{@table.schema_name}\".\"#{@table.table_name}\" SET #{@set_sqls.join(', ')}"
338
338
  update_sql << " WHERE #{@where_sqls.join(' AND ')}" unless @where_sqls.empty?
@@ -340,9 +340,6 @@ module PLSQL
340
340
  update_sql
341
341
  end
342
342
  end
343
-
344
343
  end
345
-
346
344
  end
347
-
348
345
  end