@@ -7,8 +7,9 @@ export type RawValue = Value | Sql;
77 * A SQL instance can be nested within each other to build SQL strings.
88 */
99export class Sql {
10- private rawStrings : Array < string > ;
11- private rawValues : Array < RawValue > ;
10+ values : Value [ ] ;
11+ strings : string [ ] ;
12+
1213 constructor (
1314 rawStrings : ReadonlyArray < string > ,
1415 rawValues : ReadonlyArray < RawValue >
@@ -25,65 +26,47 @@ export class Sql {
2526 ) ;
2627 }
2728
28- this . rawStrings = [ ] ;
29- this . rawValues = [ ] ;
29+ let valuesLength = rawValues . length ;
30+ let stringsLength = rawStrings . length ;
3031
31- if ( rawValues . length === 0 ) {
32- this . rawStrings = rawStrings . slice ( 0 ) ;
33- return ;
32+ for ( const child of rawValues ) {
33+ if ( child instanceof Sql ) {
34+ valuesLength += child . values . length - 1 ;
35+ stringsLength += child . strings . length - 2 ;
36+ }
3437 }
3538
36- this . rawStrings . length = rawStrings . length ;
37-
38- if ( rawValues . length ) {
39- this . rawValues . length = rawValues . length ;
39+ this . values = new Array ( valuesLength ) ;
40+ this . strings = new Array ( stringsLength ) ;
4041
41- for ( let child of rawValues ) {
42- if ( child instanceof Sql ) {
43- this . rawStrings . length += child . strings . length ;
44- this . rawValues . length += child . values . length - 1 ;
45- }
46- }
47- }
48- this . rawStrings [ 0 ] = rawStrings [ 0 ] ;
42+ this . strings [ 0 ] = rawStrings [ 0 ] ;
4943
50- let i = 1 ;
51- let strIn = 1 ;
52- for ( ; i < rawStrings . length ; ++ i ) {
53- const rawString = rawStrings [ i ] ;
54- const child = rawValues [ i - 1 ] ;
44+ // Iterate over raw values, strings, and children. The value is always
45+ // positioned between two strings, e.g. `index + 1`.
46+ let index = 1 ;
47+ let position = 0 ;
48+ while ( index < rawStrings . length ) {
49+ const child = rawValues [ index - 1 ] ;
50+ const rawString = rawStrings [ index ++ ] ;
5551
56- // check for type
52+ // Check for nested `sql` queries.
5753 if ( child instanceof Sql ) {
58- const len = child . values . length ;
59- // concat beginning
60- this . rawStrings [ strIn - 1 ] += child . strings [ 0 ] ;
61-
62- for ( let d = 0 ; d < len ; ++ d ) {
63- this . rawStrings [ strIn ] = child . strings [ d + 1 ] ;
64- this . rawValues [ strIn - 1 ] = child . values [ d ] ;
65- strIn ++ ;
54+ // Append child prefix text to current string.
55+ this . strings [ position ] += child . strings [ 0 ] ;
56+
57+ let childIndex = 0 ;
58+ while ( childIndex < child . values . length ) {
59+ this . values [ position ++ ] = child . values [ childIndex ++ ] ;
60+ this . strings [ position ] = child . strings [ childIndex ] ;
6661 }
6762
68- // set current
69- this . rawStrings [ strIn - 1 ] += rawString ;
63+ // Append raw string to current string.
64+ this . strings [ position ] += rawString ;
7065 } else {
71- this . rawStrings [ strIn ] = rawString ;
72- this . rawValues [ strIn - 1 ] = child ;
73- ++ strIn ;
66+ this . values [ position ++ ] = child ;
67+ this . strings [ position ] = rawString ;
7468 }
7569 }
76-
77- this . rawStrings . length = strIn ;
78- this . rawValues . length = strIn - 1 ;
79- }
80-
81- get values ( ) : Value [ ] {
82- return this . rawValues ;
83- }
84-
85- get strings ( ) : string [ ] {
86- return this . rawStrings ;
8770 }
8871
8972 get text ( ) {
@@ -106,9 +89,8 @@ export class Sql {
10689}
10790
10891// Work around MySQL enumerable keys in issue #2.
109- Object . defineProperty ( Sql . prototype , "text" , { enumerable : true } ) ;
110- Object . defineProperty ( Sql . prototype , "values" , { enumerable : true } ) ;
11192Object . defineProperty ( Sql . prototype , "sql" , { enumerable : true } ) ;
93+ Object . defineProperty ( Sql . prototype , "text" , { enumerable : true } ) ;
11294
11395/**
11496 * Create a SQL query for a list of values.
0 commit comments