@@ -17,17 +17,11 @@ package spannerdriver
1717import (
1818 "context"
1919 "database/sql/driver"
20- "fmt"
21- "regexp"
22- "strconv"
23- "strings"
2420 "time"
2521
2622 "cloud.google.com/go/spanner"
2723 "cloud.google.com/go/spanner/apiv1/spannerpb"
2824 "google.golang.org/api/iterator"
29- "google.golang.org/grpc/codes"
30- "google.golang.org/grpc/status"
3125)
3226
3327// statementExecutor is an empty struct that is used to hold the execution methods
@@ -48,30 +42,6 @@ import (
4842type statementExecutor struct {
4943}
5044
51- func (s * statementExecutor ) ShowRetryAbortsInternally (_ context.Context , c * conn , _ string , opts * ExecOptions , _ []driver.NamedValue ) (driver.Rows , error ) {
52- it , err := createBooleanIterator ("RetryAbortsInternally" , c .RetryAbortsInternally ())
53- if err != nil {
54- return nil , err
55- }
56- return createRows (it , opts ), nil
57- }
58-
59- func (s * statementExecutor ) ShowAutocommitDmlMode (_ context.Context , c * conn , _ string , opts * ExecOptions , _ []driver.NamedValue ) (driver.Rows , error ) {
60- it , err := createStringIterator ("AutocommitDMLMode" , c .AutocommitDMLMode ().String ())
61- if err != nil {
62- return nil , err
63- }
64- return createRows (it , opts ), nil
65- }
66-
67- func (s * statementExecutor ) ShowReadOnlyStaleness (_ context.Context , c * conn , _ string , opts * ExecOptions , _ []driver.NamedValue ) (driver.Rows , error ) {
68- it , err := createStringIterator ("ReadOnlyStaleness" , c .ReadOnlyStaleness ().String ())
69- if err != nil {
70- return nil , err
71- }
72- return createRows (it , opts ), nil
73- }
74-
7545func (s * statementExecutor ) StartBatchDdl (_ context.Context , c * conn , _ string , _ * ExecOptions , _ []driver.NamedValue ) (driver.Result , error ) {
7646 return c .startBatchDDL ()
7747}
@@ -88,128 +58,6 @@ func (s *statementExecutor) AbortBatch(_ context.Context, c *conn, _ string, _ *
8858 return c .abortBatch ()
8959}
9060
91- func (s * statementExecutor ) SetRetryAbortsInternally (_ context.Context , c * conn , params string , _ * ExecOptions , _ []driver.NamedValue ) (driver.Result , error ) {
92- if params == "" {
93- return nil , spanner .ToSpannerError (status .Error (codes .InvalidArgument , "no value given for RetryAbortsInternally" ))
94- }
95- retry , err := strconv .ParseBool (params )
96- if err != nil {
97- return nil , spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "invalid boolean value: %s" , params ))
98- }
99- return c .setRetryAbortsInternally (retry )
100- }
101-
102- func (s * statementExecutor ) SetAutocommitDmlMode (_ context.Context , c * conn , params string , _ * ExecOptions , _ []driver.NamedValue ) (driver.Result , error ) {
103- if params == "" {
104- return nil , spanner .ToSpannerError (status .Error (codes .InvalidArgument , "no value given for AutocommitDMLMode" ))
105- }
106- var mode AutocommitDMLMode
107- switch strings .ToUpper (params ) {
108- case fmt .Sprintf ("'%s'" , strings .ToUpper (Transactional .String ())):
109- mode = Transactional
110- case fmt .Sprintf ("'%s'" , strings .ToUpper (PartitionedNonAtomic .String ())):
111- mode = PartitionedNonAtomic
112- default :
113- return nil , spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "invalid AutocommitDMLMode value: %s" , params ))
114- }
115- return c .setAutocommitDMLMode (mode )
116- }
117-
118- var strongRegexp = regexp .MustCompile ("(?i)'STRONG'" )
119- var exactStalenessRegexp = regexp .MustCompile (`(?i)'(?P<type>EXACT_STALENESS)[\t ]+(?P<duration>(\d{1,19})(s|ms|us|ns))'` )
120- var maxStalenessRegexp = regexp .MustCompile (`(?i)'(?P<type>MAX_STALENESS)[\t ]+(?P<duration>(\d{1,19})(s|ms|us|ns))'` )
121- var readTimestampRegexp = regexp .MustCompile (`(?i)'(?P<type>READ_TIMESTAMP)[\t ]+(?P<timestamp>(\d{4})-(\d{2})-(\d{2})([Tt](\d{2}):(\d{2}):(\d{2})(\.\d{1,9})?)([Zz]|([+-])(\d{2}):(\d{2})))'` )
122- var minReadTimestampRegexp = regexp .MustCompile (`(?i)'(?P<type>MIN_READ_TIMESTAMP)[\t ]+(?P<timestamp>(\d{4})-(\d{2})-(\d{2})([Tt](\d{2}):(\d{2}):(\d{2})(\.\d{1,9})?)([Zz]|([+-])(\d{2}):(\d{2})))'` )
123-
124- func (s * statementExecutor ) SetReadOnlyStaleness (_ context.Context , c * conn , params string , _ * ExecOptions , _ []driver.NamedValue ) (driver.Result , error ) {
125- if params == "" {
126- return nil , spanner .ToSpannerError (status .Error (codes .InvalidArgument , "no value given for ReadOnlyStaleness" ))
127- }
128- invalidErr := spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "invalid ReadOnlyStaleness value: %s" , params ))
129-
130- var staleness spanner.TimestampBound
131-
132- if strongRegexp .MatchString (params ) {
133- staleness = spanner .StrongRead ()
134- } else if exactStalenessRegexp .MatchString (params ) {
135- d , err := parseDuration (exactStalenessRegexp , "staleness" , params )
136- if err != nil {
137- return nil , err
138- }
139- staleness = spanner .ExactStaleness (d )
140- } else if maxStalenessRegexp .MatchString (params ) {
141- d , err := parseDuration (maxStalenessRegexp , "staleness" , params )
142- if err != nil {
143- return nil , err
144- }
145- staleness = spanner .MaxStaleness (d )
146- } else if readTimestampRegexp .MatchString (params ) {
147- t , err := parseTimestamp (readTimestampRegexp , params )
148- if err != nil {
149- return nil , err
150- }
151- staleness = spanner .ReadTimestamp (t )
152- } else if minReadTimestampRegexp .MatchString (params ) {
153- t , err := parseTimestamp (minReadTimestampRegexp , params )
154- if err != nil {
155- return nil , err
156- }
157- staleness = spanner .MinReadTimestamp (t )
158- } else {
159- return nil , invalidErr
160- }
161- return c .setReadOnlyStaleness (staleness )
162- }
163-
164- func parseDuration (re * regexp.Regexp , name , params string ) (time.Duration , error ) {
165- matches := matchesToMap (re , params )
166- if matches ["duration" ] == "" && matches ["number" ] == "" && matches ["null" ] == "" {
167- return 0 , spanner .ToSpannerError (status .Error (codes .InvalidArgument , fmt .Sprintf ("No duration found in %s string: %v" , name , params )))
168- }
169- if matches ["duration" ] != "" {
170- d , err := time .ParseDuration (matches ["duration" ])
171- if err != nil {
172- return 0 , spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "Invalid duration: %s" , matches ["duration" ]))
173- }
174- return d , nil
175- } else if matches ["number" ] != "" {
176- d , err := strconv .Atoi (matches ["number" ])
177- if err != nil {
178- return 0 , spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "Invalid duration: %s" , matches ["number" ]))
179- }
180- return time .Millisecond * time .Duration (d ), nil
181- } else if matches ["null" ] != "" {
182- return time .Duration (0 ), nil
183- }
184- return time .Duration (0 ), spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "Unrecognized duration: %s" , params ))
185- }
186-
187- func parseTimestamp (re * regexp.Regexp , params string ) (time.Time , error ) {
188- matches := matchesToMap (re , params )
189- if matches ["timestamp" ] == "" {
190- return time.Time {}, spanner .ToSpannerError (status .Error (codes .InvalidArgument , "No timestamp found in staleness string" ))
191- }
192- t , err := time .Parse (time .RFC3339Nano , matches ["timestamp" ])
193- if err != nil {
194- return time.Time {}, spanner .ToSpannerError (status .Errorf (codes .InvalidArgument , "Invalid timestamp: %s" , matches ["timestamp" ]))
195- }
196- return t , nil
197- }
198-
199- func matchesToMap (re * regexp.Regexp , s string ) map [string ]string {
200- matches := make (map [string ]string )
201- match := re .FindStringSubmatch (s )
202- if match == nil {
203- return matches
204- }
205- for i , name := range re .SubexpNames () {
206- if i != 0 && name != "" {
207- matches [name ] = match [i ]
208- }
209- }
210- return matches
211- }
212-
21361func createEmptyIterator () * clientSideIterator {
21462 return & clientSideIterator {
21563 metadata : & spannerpb.ResultSetMetadata {
0 commit comments