ruby-plsql 0.5.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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