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.
- checksums.yaml +5 -5
- data/.github/stale.yml +37 -0
- data/.github/workflows/rubocop.yml +37 -0
- data/.github/workflows/test.yml +69 -0
- data/.rubocop.yml +147 -0
- data/.travis.yml +88 -0
- data/.travis/oracle/download.sh +15 -0
- data/.travis/oracle/install.sh +32 -0
- data/.travis/setup_accounts.sh +9 -0
- data/Gemfile +17 -9
- data/History.txt +76 -0
- data/README.md +29 -6
- data/Rakefile +31 -26
- data/VERSION +1 -1
- data/Vagrantfile +4 -4
- data/ci/network/admin/tnsnames.ora +7 -0
- data/ci/setup_accounts.sh +9 -0
- data/gemfiles/Gemfile.activerecord-5.0 +21 -0
- data/gemfiles/Gemfile.activerecord-5.1 +21 -0
- data/gemfiles/Gemfile.activerecord-5.2 +21 -0
- data/gemfiles/Gemfile.activerecord-6.0 +21 -0
- data/gemfiles/Gemfile.activerecord-6.1 +21 -0
- data/gemfiles/Gemfile.activerecord-main +21 -0
- data/lib/plsql/connection.rb +19 -22
- data/lib/plsql/helpers.rb +1 -3
- data/lib/plsql/jdbc_connection.rb +70 -68
- data/lib/plsql/oci8_patches.rb +2 -2
- data/lib/plsql/oci_connection.rb +62 -77
- data/lib/plsql/package.rb +61 -46
- data/lib/plsql/procedure.rb +358 -78
- data/lib/plsql/procedure_call.rb +508 -463
- data/lib/plsql/schema.rb +96 -101
- data/lib/plsql/sequence.rb +10 -13
- data/lib/plsql/sql_statements.rb +9 -11
- data/lib/plsql/table.rb +60 -63
- data/lib/plsql/type.rb +71 -76
- data/lib/plsql/variable.rb +90 -94
- data/lib/plsql/version.rb +1 -1
- data/lib/plsql/view.rb +16 -19
- data/ruby-plsql.gemspec +55 -35
- data/spec/plsql/connection_spec.rb +72 -66
- data/spec/plsql/package_spec.rb +63 -14
- data/spec/plsql/procedure_spec.rb +603 -261
- data/spec/plsql/schema_spec.rb +47 -23
- data/spec/plsql/sequence_spec.rb +2 -2
- data/spec/plsql/sql_statements_spec.rb +6 -6
- data/spec/plsql/table_spec.rb +84 -79
- data/spec/plsql/type_spec.rb +24 -30
- data/spec/plsql/variable_spec.rb +80 -88
- data/spec/plsql/version_spec.rb +4 -4
- data/spec/plsql/view_spec.rb +42 -42
- data/spec/spec_helper.rb +38 -35
- data/spec/support/create_arunit_user.sql +2 -0
- data/spec/support/custom_config.rb.sample +14 -0
- data/spec/support/test_db.rb +12 -13
- data/spec/support/unlock_and_setup_hr_user.sql +2 -0
- 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','
|
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
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
182
|
+
raise ArgumentError, "No database object '#{method.to_s.upcase}' found" unless object
|
183
183
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
"SELECT o.object_type, o.object_id
|
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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
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
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
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
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
|
data/lib/plsql/sequence.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
data/lib/plsql/sql_statements.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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,
|
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
|
-
:
|
67
|
-
:
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
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=
|
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(
|
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=
|
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=
|
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=
|
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=
|
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(
|
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
|