@@ -8,58 +8,79 @@ module DatabaseStatements
88 #
99 # see: abstract/database_statements.rb
1010
11- # Executes a SQL statement
12- def execute ( sql , name = nil , async : false , allow_retry : false )
13- sql = preprocess_query ( sql )
11+ READ_QUERY = ActiveRecord ::ConnectionAdapters ::AbstractAdapter . build_read_query_regexp (
12+ :close , :declare , :fetch , :move , :set , :show
13+ ) # :nodoc:
14+ private_constant :READ_QUERY
15+
16+ def write_query? ( sql ) # :nodoc:
17+ !READ_QUERY . match? ( sql )
18+ rescue ArgumentError # Invalid encoding
19+ !READ_QUERY . match? ( sql . b )
20+ end
1421
15- log ( sql , name , async : async ) { _connection . exec ( sql , allow_retry : allow_retry ) }
22+ # Executes a SQL statement
23+ def execute ( ...)
24+ super
1625 end
1726
18- def exec_query ( sql , name = "SQL" , binds = [ ] , prepare : false , async : false , allow_retry : false )
27+ # Low level execution of a SQL statement on the connection returning adapter specific result object.
28+ def raw_execute ( sql , name = "SQL" , binds = [ ] , prepare : false , async : false , allow_retry : false , materialize_transactions : false )
1929 sql = preprocess_query ( sql )
2030
2131 type_casted_binds = type_casted_binds ( binds )
32+ with_raw_connection ( allow_retry : allow_retry , materialize_transactions : materialize_transactions ) do |conn |
33+ log ( sql , name , binds , type_casted_binds , async : async ) do
34+ cursor = nil
35+ cached = false
36+ with_retry do
37+ if binds . nil? || binds . empty?
38+ cursor = conn . prepare ( sql )
39+ else
40+ unless @statements . key? sql
41+ @statements [ sql ] = conn . prepare ( sql )
42+ end
2243
23- log ( sql , name , binds , type_casted_binds , async : async ) do
24- cursor = nil
25- cached = false
26- with_retry do
27- if without_prepared_statement? ( binds )
28- cursor = _connection . prepare ( sql )
29- else
30- unless @statements . key? sql
31- @statements [ sql ] = _connection . prepare ( sql )
32- end
33-
34- cursor = @statements [ sql ]
35-
36- cursor . bind_params ( type_casted_binds )
44+ cursor = @statements [ sql ]
45+ cursor . bind_params ( type_casted_binds )
3746
38- cached = true
47+ cached = true
48+ end
49+ cursor . exec
3950 end
4051
41- cursor . exec
42- end
43-
44- if ( name == "EXPLAIN" ) && sql . start_with? ( "EXPLAIN" )
45- res = true
46- else
4752 columns = cursor . get_col_names . map do |col_name |
4853 oracle_downcase ( col_name )
4954 end
55+
5056 rows = [ ]
51- fetch_options = { get_lob_value : ( name != "Writable Large Object" ) }
52- while row = cursor . fetch ( fetch_options )
53- rows << row
57+ if sql =~ /\A \s *SELECT/i # This seems a naive way to detect queries that will have row results.
58+ fetch_options = { get_lob_value : ( name != "Writable Large Object" ) }
59+ while row = cursor . fetch ( fetch_options )
60+ rows << row
61+ end
5462 end
55- res = build_result ( columns : columns , rows : rows )
63+
64+ affected_rows_count = cursor . row_count
65+
66+ cursor . close unless cached
67+
68+ { columns : columns , rows : rows , affected_rows_count : affected_rows_count }
5669 end
70+ end
71+ end
5772
58- cursor . close unless cached
59- res
73+ def cast_result ( result )
74+ if result . nil?
75+ ActiveRecord ::Result . empty
76+ else
77+ ActiveRecord ::Result . new ( result [ :columns ] , result [ :rows ] )
6078 end
6179 end
62- alias_method :internal_exec_query , :exec_query
80+
81+ def affected_rows ( result )
82+ result [ :affected_rows_count ]
83+ end
6384
6485 def supports_explain?
6586 true
@@ -106,7 +127,7 @@ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, retu
106127 cursor = nil
107128 returning_id_col = returning_id_index = nil
108129 with_retry do
109- if without_prepared_statement? ( binds )
130+ if binds . nil? || binds . empty?
110131 cursor = _connection . prepare ( sql )
111132 else
112133 unless @statements . key? ( sql )
@@ -146,7 +167,7 @@ def exec_update(sql, name = nil, binds = [])
146167 log ( sql , name , binds , type_casted_binds ) do
147168 with_retry do
148169 cached = false
149- if without_prepared_statement? ( binds )
170+ if binds . nil? || binds . empty?
150171 cursor = _connection . prepare ( sql )
151172 else
152173 if @statements . key? ( sql )
@@ -289,6 +310,15 @@ def with_retry
289310 raise
290311 end
291312 end
313+
314+ def handle_warnings ( sql )
315+ @notice_receiver_sql_warnings . each do |warning |
316+ next if warning_ignored? ( warning )
317+
318+ warning . sql = sql
319+ ActiveRecord . db_warnings_action . call ( warning )
320+ end
321+ end
292322 end
293323 end
294324 end
0 commit comments