@@ -37,11 +37,20 @@ type SQCloudConfig struct {
3737 Username string
3838 Password string
3939 Database string
40- Timeout time.Duration
41- CompressMode string
42- Secure bool
43- TlsInsecureSkipVerify bool
44- Pem string
40+ PasswordHashed bool // Password is hashed
41+ Timeout time.Duration // Optional query timeout passed directly to TLS socket
42+ CompressMode string // eg: LZ4
43+ Compression bool // Enable compression
44+ Zerotext bool // Tell the server to zero-terminate strings
45+ Memory bool // Database will be created in memory
46+ Create bool // Create the database if it doesn't exist?
47+ Secure bool // Connect using plain TCP port, without TLS encryption, NOT RECOMMENDED (insecure)
48+ NonLinearizable bool // Request for immediate responses from the server node without waiting for linerizability guarantees
49+ TlsInsecureSkipVerify bool // Accept invalid TLS certificates (no_verify_certificate)
50+ Pem string // TODO: ?
51+ RootCertificate string
52+ ClientCertificate string
53+ ClientCertificateKey string
4554 ApiKey string
4655 NoBlob bool // flag to tell the server to not send BLOB columns
4756 MaxData int // value to tell the server to not send columns with more than max_data bytes
@@ -69,6 +78,9 @@ type SQCloud struct {
6978 ErrorMessage string
7079}
7180
81+ const CompressModeNo = "NO"
82+ const CompressModeLZ4 = "LZ4"
83+
7284const SQLiteCloudCA = "SQLiteCloudCA"
7385
7486func New (config SQCloudConfig ) * SQCloud {
@@ -104,15 +116,23 @@ func ParseConnectionString(ConnectionString string) (config *SQCloudConfig, err
104116 config .Password , _ = u .User .Password ()
105117 config .Database = strings .TrimPrefix (u .Path , "/" )
106118 config .Timeout = 0
107- config .CompressMode = "NO"
119+ config .Compression = false
120+ config .CompressMode = CompressModeNo
121+ config .Zerotext = false
122+ config .Memory = false
123+ config .Create = false
108124 config .Secure = true
125+ config .NonLinearizable = false
109126 config .TlsInsecureSkipVerify = false
110127 config .Pem = ""
111- config .ApiKey = ""
128+ config .RootCertificate = ""
129+ config .ClientCertificate = ""
130+ config .ClientCertificateKey = ""
112131 config .NoBlob = false
113132 config .MaxData = 0
114133 config .MaxRows = 0
115134 config .MaxRowset = 0
135+ config .ApiKey = ""
116136
117137 sPort := strings .TrimSpace (u .Port ())
118138 if len (sPort ) > 0 {
@@ -133,8 +153,50 @@ func ParseConnectionString(ConnectionString string) (config *SQCloudConfig, err
133153
134154 case "compress" :
135155 config .CompressMode = strings .ToUpper (lastLiteral )
156+ if config .CompressMode == CompressModeLZ4 {
157+ config .Compression = true
158+ }
159+ case "compression" :
160+ if b , err := parseBool (lastLiteral , config .Compression ); err == nil && b {
161+ config .Compression = true
162+ config .CompressMode = CompressModeLZ4
163+ }
164+ case "zerotext" :
165+ if b , err := parseBool (lastLiteral , config .Zerotext ); err == nil {
166+ config .Zerotext = b
167+ }
168+ case "memory" :
169+ if b , err := parseBool (lastLiteral , config .Memory ); err == nil {
170+ config .Memory = b
171+ }
172+ case "create" :
173+ if b , err := parseBool (lastLiteral , config .Create ); err == nil {
174+ config .Create = b
175+ }
176+ case "secure" :
177+ if b , err := parseBool (lastLiteral , config .Secure ); err == nil {
178+ config .Secure = b
179+ }
180+ case "insecure" :
181+ if b , err := parseBool (lastLiteral , config .Secure ); err == nil {
182+ config .Secure = ! b
183+ }
184+ case "non_linearizable" , "nonlinearizable" :
185+ if b , err := parseBool (lastLiteral , config .NonLinearizable ); err == nil {
186+ config .NonLinearizable = b
187+ }
188+ case "no_verify_certificate" :
189+ if b , err := parseBool (lastLiteral , config .TlsInsecureSkipVerify ); err == nil {
190+ config .TlsInsecureSkipVerify = b
191+ }
136192 case "tls" :
137193 config .Secure , config .TlsInsecureSkipVerify , config .Pem = ParseTlsString (lastLiteral )
194+ case "root_certificate" :
195+ config .RootCertificate = lastLiteral
196+ case "client_certificate" :
197+ config .ClientCertificate = lastLiteral
198+ case "client_certificate_key" :
199+ config .ClientCertificateKey = lastLiteral
138200 case "apikey" :
139201 config .ApiKey = lastLiteral
140202 case "noblob" :
@@ -210,8 +272,8 @@ func (this *SQCloud) CheckConnectionParameter() error {
210272 return errors .New (fmt .Sprintf ("Invalid Timeout (%s)" , this .Timeout .String ()))
211273 }
212274
213- switch strings . ToUpper ( this .CompressMode ) {
214- case "NO" , "LZ4" :
275+ switch this .CompressMode {
276+ case CompressModeNo , CompressModeLZ4 :
215277 default :
216278 return errors .New (fmt .Sprintf ("Invalid compression method (%s)" , this .CompressMode ))
217279 }
@@ -340,45 +402,7 @@ func (this *SQCloud) reconnect() error {
340402 }
341403 }
342404
343- commands := ""
344- args := []interface {}{}
345-
346- if strings .TrimSpace (this .Username ) != "" {
347- c , a := authCommand (this .Username , this .Password )
348- commands += c
349- args = append (args , a ... )
350-
351- } else if strings .TrimSpace (this .ApiKey ) != "" {
352- c , a := authWithKeyCommand (this .ApiKey )
353- commands += c
354- args = append (args , a ... )
355- }
356-
357- if strings .TrimSpace (this .Database ) != "" {
358- c , a := useDatabaseCommand (this .Database )
359- commands += c
360- args = append (args , a ... )
361- }
362-
363- if this .NoBlob {
364- commands += noblobCommand (this .NoBlob )
365- }
366-
367- if this .MaxData > 0 {
368- commands += maxdataCommand (this .MaxData )
369- }
370-
371- if this .MaxRows > 0 {
372- commands += maxrowsCommand (this .MaxRows )
373- }
374-
375- if this .MaxRowset > 0 {
376- commands += maxrowsetCommand (this .MaxRowset )
377- }
378-
379- if this .CompressMode != "NO" {
380- commands += compressCommand (this .CompressMode )
381- }
405+ commands , args := connectionCommands (this .SQCloudConfig )
382406
383407 if commands != "" {
384408 if len (args ) > 0 {
@@ -421,6 +445,53 @@ func (this *SQCloud) Close() error {
421445 return nil
422446}
423447
448+ func connectionCommands (config SQCloudConfig ) (string , []interface {}) {
449+ buffer := ""
450+ args := []interface {}{}
451+
452+ // it must be executed before authentication command
453+ if config .NonLinearizable {
454+ buffer += nonlinearizableCommand (config .NonLinearizable )
455+ }
456+
457+ if config .ApiKey != "" {
458+ c , a := authWithKeyCommand (config .ApiKey )
459+ buffer += c
460+ args = append (args , a ... )
461+ }
462+
463+ if config .Username != "" && config .Password != "" {
464+ c , a := authCommand (config .Username , config .Password , config .PasswordHashed )
465+ buffer += c
466+ args = append (args , a ... )
467+ }
468+
469+ if config .Database != "" {
470+ create := config .Create && ! config .Memory
471+ c , a := useDatabaseCommand (config .Database , create )
472+ buffer += c
473+ args = append (args , a ... )
474+ }
475+
476+ buffer += compressCommand (config .CompressMode )
477+
478+ if config .Zerotext {
479+ buffer += zerotextCommand (config .Zerotext )
480+ }
481+
482+ if config .NoBlob {
483+ buffer += noblobCommand (config .NoBlob )
484+ }
485+
486+ buffer += maxdataCommand (config .MaxData )
487+
488+ buffer += maxrowsCommand (config .MaxRows )
489+
490+ buffer += maxrowsetCommand (config .MaxRowset )
491+
492+ return buffer , args
493+ }
494+
424495func noblobCommand (NoBlob bool ) string {
425496 if NoBlob {
426497 return "SET CLIENT KEY NOBLOB TO 1;"
@@ -443,15 +514,31 @@ func maxrowsetCommand(v int) string {
443514
444515func compressCommand (CompressMode string ) string {
445516 switch compression := strings .ToUpper (CompressMode ); {
446- case compression == "NO" :
517+ case compression == CompressModeNo :
447518 return "SET CLIENT KEY COMPRESSION TO 0;"
448- case compression == "LZ4" :
519+ case compression == CompressModeLZ4 :
449520 return "SET CLIENT KEY COMPRESSION TO 1;"
450521 default :
451522 return ""
452523 }
453524}
454525
526+ func nonlinearizableCommand (NonLinearizable bool ) string {
527+ if NonLinearizable {
528+ return "SET CLIENT KEY NONLINEARIZABLE TO 1;"
529+ } else {
530+ return "SET CLIENT KEY NONLINEARIZABLE TO 0;"
531+ }
532+ }
533+
534+ func zerotextCommand (Zerotext bool ) string {
535+ if Zerotext {
536+ return "SET CLIENT KEY ZEROTEXT TO 1;"
537+ } else {
538+ return "SET CLIENT KEY ZEROTEXT TO 0;"
539+ }
540+ }
541+
455542// Compress enabled or disables data compression for this connection.
456543// If enabled, the data is compressed with the LZ4 compression algorithm, otherwise no compression is applied the data.
457544func (this * SQCloud ) Compress (CompressMode string ) error {
0 commit comments