@@ -7,55 +7,110 @@ module DatabaseStatements
7
7
READ_QUERY = ActiveRecord ::ConnectionAdapters ::AbstractAdapter . build_read_query_regexp ( :begin , :commit , :dbcc , :explain , :save , :select , :set , :rollback , :waitfor , :use ) # :nodoc:
8
8
private_constant :READ_QUERY
9
9
10
- def write_query? ( sql ) # :nodoc:
11
- !READ_QUERY . match? ( sql )
12
- rescue ArgumentError # Invalid encoding
13
- !READ_QUERY . match? ( sql . b )
14
- end
10
+ # TODO: replace `internal_exec_query` by `perform_query`.
15
11
16
- def raw_execute ( sql , name , async : false , allow_retry : false , materialize_transactions : true )
17
- log ( sql , name , async : async ) do |notification_payload |
18
- with_raw_connection ( allow_retry : allow_retry , materialize_transactions : materialize_transactions ) do |conn |
19
- result = if id_insert_table_name = query_requires_identity_insert? ( sql )
20
- with_identity_insert_enabled ( id_insert_table_name , conn ) { internal_raw_execute ( sql , conn , perform_do : true ) }
21
- else
22
- internal_raw_execute ( sql , conn , perform_do : true )
23
- end
24
- verified!
25
- notification_payload [ :row_count ] = result
26
- result
27
- end
28
- end
29
- end
12
+ def perform_query ( raw_connection , sql , binds , type_casted_binds , prepare :, notification_payload :, batch :)
13
+ unless binds . nil? || binds . empty?
14
+ types , params = sp_executesql_types_and_parameters ( binds )
30
15
31
- def internal_exec_query ( sql , name = "SQL" , binds = [ ] , prepare : false , async : false , allow_retry : false )
32
- sql = transform_query ( sql )
16
+ # TODO: `name` parameter does not exist.
17
+ sql = sp_executesql_sql ( sql , types , params )
18
+ end
33
19
34
- check_if_write_query ( sql )
35
- mark_transaction_written_if_write ( sql )
36
20
37
- unless without_prepared_statement? ( binds )
38
- types , params = sp_executesql_types_and_parameters ( binds )
39
- sql = sp_executesql_sql ( sql , types , params , name )
21
+ result = if id_insert_table_name = query_requires_identity_insert? ( sql )
22
+ with_identity_insert_enabled ( id_insert_table_name , raw_connection ) do
23
+ internal_exec_sql_query ( sql , raw_connection )
24
+ end
25
+ else
26
+ internal_exec_sql_query ( sql , raw_connection )
27
+ end
28
+
29
+ verified!
30
+ notification_payload [ :row_count ] = result . count
31
+ result
32
+ end
33
+
34
+ #
35
+ # def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false)
36
+ # sql = transform_query(sql)
37
+ #
38
+ # check_if_write_query(sql)
39
+ # mark_transaction_written_if_write(sql)
40
+ #
41
+ # unless without_prepared_statement?(binds)
42
+ # types, params = sp_executesql_types_and_parameters(binds)
43
+ # sql = sp_executesql_sql(sql, types, params, name)
44
+ # end
45
+ #
46
+ # log(sql, name, binds, async: async) do |notification_payload|
47
+ # with_raw_connection do |conn|
48
+ # result = if id_insert_table_name = query_requires_identity_insert?(sql)
49
+ # with_identity_insert_enabled(id_insert_table_name, conn) do
50
+ # internal_exec_sql_query(sql, conn)
51
+ # end
52
+ # else
53
+ # internal_exec_sql_query(sql, conn)
54
+ # end
55
+ #
56
+ # verified!
57
+ # notification_payload[:row_count] = result.count
58
+ # result
59
+ # end
60
+ # end
61
+ # end
62
+
63
+
64
+ # Receive a native adapter result object and returns an ActiveRecord::Result object.
65
+ def cast_result ( raw_result )
66
+ if raw_result . columns . empty?
67
+ ActiveRecord ::Result . empty
68
+ else
69
+ ActiveRecord ::Result . new ( raw_result . columns , raw_result . rows )
40
70
end
41
71
42
- log ( sql , name , binds , async : async ) do |notification_payload |
43
- with_raw_connection do |conn |
44
- result = if id_insert_table_name = query_requires_identity_insert? ( sql )
45
- with_identity_insert_enabled ( id_insert_table_name , conn ) do
46
- internal_exec_sql_query ( sql , conn )
47
- end
48
- else
49
- internal_exec_sql_query ( sql , conn )
50
- end
72
+ # rescue => e
73
+ # binding.pry
74
+ end
51
75
52
- verified!
53
- notification_payload [ :row_count ] = result . count
54
- result
55
- end
76
+ def affected_rows ( raw_result )
77
+
78
+ if raw_result . count == 1 && raw_result . first . key? ( 'AffectedRows' )
79
+ raw_result . first [ 'AffectedRows' ]
80
+ else
81
+ raw_result . count
56
82
end
83
+
84
+ rescue => e
85
+ binding . pry
57
86
end
58
87
88
+
89
+
90
+ def write_query? ( sql ) # :nodoc:
91
+ !READ_QUERY . match? ( sql )
92
+ rescue ArgumentError # Invalid encoding
93
+ !READ_QUERY . match? ( sql . b )
94
+ end
95
+
96
+ # TODO: This method implemented in Rails.
97
+ # def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
98
+ # log(sql, name, async: async) do |notification_payload|
99
+ # with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
100
+ # result = if id_insert_table_name = query_requires_identity_insert?(sql)
101
+ # with_identity_insert_enabled(id_insert_table_name, conn) { internal_raw_execute(sql, conn, perform_do: true) }
102
+ # else
103
+ # internal_raw_execute(sql, conn, perform_do: true)
104
+ # end
105
+ # verified!
106
+ # notification_payload[:row_count] = result
107
+ # result
108
+ # end
109
+ # end
110
+ # end
111
+
112
+
113
+
59
114
def internal_exec_sql_query ( sql , conn )
60
115
handle = internal_raw_execute ( sql , conn )
61
116
handle_to_names_and_values ( handle , ar_result : true )
@@ -65,12 +120,12 @@ def internal_exec_sql_query(sql, conn)
65
120
66
121
def exec_delete ( sql , name , binds )
67
122
sql = sql . dup << "; SELECT @@ROWCOUNT AS AffectedRows"
68
- super ( sql , name , binds ) . rows . first . first
123
+ super ( sql , name , binds )
69
124
end
70
125
71
126
def exec_update ( sql , name , binds )
72
127
sql = sql . dup << "; SELECT @@ROWCOUNT AS AffectedRows"
73
- super ( sql , name , binds ) . rows . first . first
128
+ super ( sql , name , binds )
74
129
end
75
130
76
131
def begin_db_transaction
@@ -366,18 +421,19 @@ def basic_attribute_type?(type)
366
421
type . is_a? ( NilClass )
367
422
end
368
423
369
- def sp_executesql_sql ( sql , types , params , name )
370
- if name == "EXPLAIN"
371
- params . each . with_index do |param , index |
372
- substitute_at_finder = /(@#{ index } )(?=(?:[^']|'[^']*')*$)/ # Finds unquoted @n values.
373
- sql = sql . sub substitute_at_finder , param . to_s
374
- end
375
- else
424
+ # TODO: `name` was removed from the method signature.
425
+ def sp_executesql_sql ( sql , types , params )
426
+ # if name == "EXPLAIN"
427
+ # params.each.with_index do |param, index|
428
+ # substitute_at_finder = /(@#{index})(?=(?:[^']|'[^']*')*$)/ # Finds unquoted @n values.
429
+ # sql = sql.sub substitute_at_finder, param.to_s
430
+ # end
431
+ # else
376
432
types = quote ( types . join ( ", " ) )
377
433
params = params . map . with_index { |p , i | "@#{ i } = #{ p } " } . join ( ", " ) # Only p is needed, but with @i helps explain regexp.
378
434
sql = "EXEC sp_executesql #{ quote ( sql ) } "
379
435
sql += ", #{ types } , #{ params } " unless params . empty?
380
- end
436
+ # end
381
437
sql . freeze
382
438
end
383
439
@@ -455,10 +511,10 @@ def finish_statement_handle(handle)
455
511
# TinyTDS returns false instead of raising an exception if connection fails.
456
512
# Getting around this by raising an exception ourselves while PR
457
513
# https://github.com/rails-sqlserver/tiny_tds/pull/469 is not released.
458
- def internal_raw_execute ( sql , conn , perform_do : false )
459
- result = conn . execute ( sql ) . tap do | _result |
460
- raise TinyTds :: Error , "failed to execute statement" if _result . is_a? ( FalseClass )
461
- end
514
+ # TODO: Check if ` perform_do` is needed.
515
+ def internal_raw_execute ( sql , raw_connection , perform_do : false )
516
+ result = raw_connection . execute ( sql )
517
+ raise TinyTds :: Error , "failed to execute statement" if result . is_a? ( FalseClass )
462
518
463
519
perform_do ? result . do : result
464
520
end
0 commit comments