@@ -2,98 +2,121 @@ component output=false extends="wheels.Global"{
22
33 public struct function $executeQuery (
44 required struct queryAttributes ,
5- required array sql ,
5+ required array sql ,
66 required boolean parameterize ,
77 required numeric limit ,
88 required numeric offset ,
99 required string comment ,
1010 required string debugName ,
1111 required string primaryKey
1212 ) {
13- // Since we allow the developer to pass in the name to use for the query variable we need to avoid name clashing.
14- // We do this by putting all our own variables inside a $wheels struct.
15- local .$wheels = {};
16- local .$wheels .rv = {};
17-
18- if (structKeyExists (arguments .queryAttributes , " DATASOURCE" ) && len (arguments .queryAttributes .DATASOURCE )){
19- local .info = $dbinfo (
20- type = " version" ,
21- datasource = arguments .queryAttributes .DATASOURCE );
22- } else {
23- local .info = $dbinfo (
24- type = " version" ,
13+ // local variables
14+ local .wheels = { rv : {} };
15+ local .newLine = chr (13 ) & chr (10 );
16+ local .args = arguments ;
17+ local .sqlArray = args .sql ;
18+ local .sqlLen = arrayLen (sqlArray );
19+
20+ // Detect datasource info once
21+ local .ds = args .queryAttributes ;
22+ local .dsInfo = ( structKeyExists (ds , " DATASOURCE" ) && len (ds .DATASOURCE ) )
23+ ? $dbinfo (type = " version" , datasource = ds .DATASOURCE )
24+ : $dbinfo (
25+ type = " version" ,
2526 datasource = application .wheels .dataSourceName ,
26- username = application .wheels .dataSourceUserName ,
27- password = application .wheels .dataSourcePassword
27+ username = application .wheels .dataSourceUserName ,
28+ password = application .wheels .dataSourcePassword
2829 );
29- }
30- cfquery (attributeCollection = arguments .queryAttributes ){
31- local .$wheels .pos = 0 ;
32-
33- for (local .$wheels .i in arguments .sql ) {
34- local .$wheels .pos + = 1 ;
35- if (isStruct (local .$wheels .i )) {
36- local .$wheels .queryParamAttributes = $queryParams (local .$wheels .i );
37- if (! isBinary (local .$wheels .i .value ) && local .$wheels .i .value == " null" && local .$wheels .pos > 1 &&
38- (right (arguments .sql [local .$wheels .pos - 1 ], 2 ) == " IS" || right (arguments .sql [local .$wheels .pos - 1 ], 6 ) == " IS NOT" )) {
39- writeOutput (" NULL" );
40- } else if (structKeyExists (local .$wheels .queryParamAttributes , " list" )) {
41- if (arguments .parameterize ) {
42- writeOutput (" (" );
43- cfqueryParam (attributeCollection = local .$wheels .queryParamAttributes );
44- writeOutput (" )" );
45- } else {
46- writeOutput (" (" & preserveSingleQuotes (local .$wheels .i .value ) & " )" );
47- }
48- } else {
49- if (arguments .parameterize ) {
50- cfqueryParam (attributeCollection = local .$wheels .queryParamAttributes );
51- } else {
52- writeOutput ($quoteValue (str = local .$wheels .i .value , sqlType = local .$wheels .i .type ));
53- }
54- }
55- } else {
56- local .$wheels .i = replace (preserveSingleQuotes (local .$wheels .i ), " [[comma]]" , " ," , " all" );
57- writeOutput (preserveSingleQuotes (local .$wheels .i ));
58- }
59- writeOutput (chr (13 ) & chr (10 ));
60- }
61-
62- if (arguments .limit ){
63- if (FindNoCase (" Oracle" , local .info .database_productname )){
64- if (arguments .offset ){
65- writeOutput (" OFFSET " & arguments .offset & " ROWS" & chr (13 ) & chr (10 ) & " FETCH NEXT " & arguments .limit & " ROWS ONLY" );
66- } else {
67- writeOutput (" FETCH FIRST " & arguments .limit & " ROWS ONLY" );
30+
31+ // Build query
32+ cfquery (attributeCollection = args .queryAttributes ) {
33+ local .pos = 1 ;
34+ local .prev = " " ;
35+
36+ for (; pos <= sqlLen ; pos ++ ) {
37+ local .part = sqlArray [pos ];
38+
39+ if (isStruct (part )) {
40+ local .qp = $queryParams (part );
41+
42+ // Handle NULL for "IS NULL" or "IS NOT NULL"
43+ if (
44+ ! isBinary (part .value ) &&
45+ part .value == " null" &&
46+ pos > 1 &&
47+ ( right (prev , 2 ) == " IS" || right (prev , 6 ) == " IS NOT" )
48+ ) {
49+ writeOutput (" NULL" );
50+ }
51+ // Handle parameter lists "(?,?,?)"
52+ else if (structKeyExists (qp , " list" )) {
53+ writeOutput (" (" );
54+ if (args .parameterize ) {
55+ cfqueryParam (attributeCollection = qp );
56+ } else {
57+ writeOutput (" (" & preserveSingleQuotes (part .value ) & " )" );
58+ }
59+ writeOutput (" )" );
60+ }
61+ // Normal parameter
62+ else {
63+ if (args .parameterize ) {
64+ cfqueryParam (attributeCollection = qp );
65+ } else {
66+ writeOutput ($quoteValue (str = part .value , sqlType = part .type ));
67+ }
68+ }
69+ }
70+ else {
71+ // regular SQL string part
72+ part = replace (preserveSingleQuotes (part ), " [[comma]]" , " ," , " all" );
73+ writeOutput (preserveSingleQuotes (part ));
74+ }
75+
76+ writeOutput (newLine );
77+ prev = part ;
6878 }
69- } else {
70- writeOutput (" LIMIT " & arguments .limit );
71- if (arguments .offset ) {
72- writeOutput (chr (13 ) & chr (10 ) & " OFFSET " & arguments .offset );
79+
80+ // LIMIT / OFFSET logic
81+ if (args .limit ) {
82+ if (findNoCase (" Oracle" , dsInfo .database_productname )) {
83+ if (args .offset ) {
84+ writeOutput (" OFFSET " & args .offset & " ROWS" & newLine & " FETCH NEXT " & args .limit & " ROWS ONLY" );
85+ } else {
86+ writeOutput (" FETCH FIRST " & args .limit & " ROWS ONLY" );
87+ }
88+ } else {
89+ writeOutput (" LIMIT " & args .limit );
90+ if (args .offset ) {
91+ writeOutput (newLine & " OFFSET " & args .offset );
92+ }
93+ }
7394 }
95+
96+ // Comment block
97+ if (len (args .comment )) {
98+ writeOutput (args .comment );
99+ }
100+ }
101+
102+ // Retrieve debug query if needed
103+ if (structKeyExists (local , args .debugName )) {
104+ wheels .rv .query = local [args .debugName ];
74105 }
75- }
76-
77- if (len (arguments .comment )) {
78- writeOutput (arguments .comment );
79- }
80- }
81-
82- if (StructKeyExists (local , arguments .debugName )){
83- local .$wheels .rv .query = local [arguments .debugName ];
84- }
85- // Get / set the primary key name / value when Lucee / ACF cannot retrieve it for us.
86- local .$wheels .id = $identitySelect (
87- primaryKey = arguments .primaryKey ,
88- queryAttributes = arguments .queryAttributes ,
89- result = local .$wheels .result
106+
107+ // Manual identity retrieval for Lucee / ACF
108+ wheels .id = $identitySelect (
109+ primaryKey = args .primaryKey ,
110+ queryAttributes = args .queryAttributes ,
111+ result = wheels .result
90112 );
91- if (StructKeyExists (local .$wheels , " id" ) && IsStruct (local .$wheels .id ) && ! StructIsEmpty (local .$wheels .id )) {
92- StructAppend (local .$wheels .result , local .$wheels .id );
113+
114+ if (structKeyExists (wheels ," id" ) && isStruct (wheels .id ) && ! structIsEmpty (wheels .id )) {
115+ structAppend (wheels .result , wheels .id );
93116 }
94117
95- local .$ wheels .rv .result = local .$ wheels .result ;
96- return local .$ wheels .rv ;
118+ wheels .rv .result = wheels .result ;
119+ return wheels .rv ;
97120 }
98121
99122 /**
@@ -126,7 +149,7 @@ component output=false extends="wheels.Global"{
126149 required struct result ,
127150 required string primaryKey
128151 ) {
129- var query = {};
152+ local . query = {};
130153 local .sql = Trim (arguments .result .sql );
131154 if (Left (local .sql , 11 ) == " INSERT INTO" && ! StructKeyExists (arguments .result , $generatedKey ())) {
132155 local .startPar = Find (" (" , local .sql ) + 1 ;
@@ -507,7 +530,7 @@ component output=false extends="wheels.Global"{
507530 local .queryAttributes .dataSource = arguments .dataSource ;
508531 local .queryAttributes .username = variables .username ;
509532 local .queryAttributes .password = variables .password ;
510- local .queryAttributes .result = " local.$ wheels.result" ;
533+ local .queryAttributes .result = " local.wheels.result" ;
511534 local .queryAttributes .name = " local." & arguments .$debugName ;
512535 if (StructKeyExists (local .queryAttributes , " username" ) && ! Len (local .queryAttributes .username )) {
513536 StructDelete (local .queryAttributes , " username" );
0 commit comments