Skip to content

Commit afec09e

Browse files
committed
fix prepared statements for sybase < 15.7
1 parent dc44d45 commit afec09e

File tree

4 files changed

+47
-56
lines changed

4 files changed

+47
-56
lines changed

README.md

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use the regular database/sql APIs:
3838
)
3939

4040
func main() {
41-
cnxStr := "tds://my_user:my_password@dbhost.com:5000/pubs?charset=utf8
41+
cnxStr := "tds://my_user:my_password@dbhost.com:5000/pubs?charset=utf8"
4242
db, err := sql.Open("tds", connStr)
4343
if err != nil {
4444
log.Fatal(err)
@@ -73,7 +73,7 @@ It is suggested to raise it to avoid truncation.
7373

7474
Less frequently used ones:
7575

76-
* ssl - Whether or not to use SSL. THe default is not to use ssl.
76+
* ssl - Whether or not to use SSL. The default is not to use ssl.
7777
Set to "on" if the server is setup to use ssl.
7878
* encryptPassword - Can be "yes" to require password encryption,
7979
"no" to disable it, and "try" to try encrytping password an falling back
@@ -147,7 +147,7 @@ You must cast your database/sql connection as sql.Conn to use this extension.
147147
The following demonstrates how to handle showplan and print messages:
148148

149149

150-
conn = goConn.(*tds.Conn)
150+
conn := goConn.(*tds.Conn)
151151

152152
// print showplan messages and all
153153
conn.SetErrorhandler(func(m tds.SybError) bool {
@@ -167,6 +167,11 @@ The following demonstrates how to handle showplan and print messages:
167167
return m.Severity > 10
168168
})
169169

170+
### Limitations
171+
As of now the driver does not support bulk insert and named parameters.
172+
Password encryption only works for Sybase ASE > 15.0.1, the old cypher is
173+
not known.
174+
170175
### Testing
171176
You can use stmt_test.go and session_test.go for sample usage, as follows:
172177

@@ -208,7 +213,6 @@ There are differences, however a lot of it is relevant.
208213
* [func (s Conn) Rollback() error](#Conn.Rollback)
209214
* [func (s Conn) SelectValue(ctx context.Context, query string) (value interface{}, err error)](#Conn.SelectValue)
210215
* [func (c *Conn) SetErrorhandler(fn func(s SybError) bool)](#Conn.SetErrorhandler)
211-
* [type Errorhandler](#Errorhandler)
212216
* [type Num](#Num)
213217
* [func (n Num) Rat() big.Rat](#Num.Rat)
214218
* [func (n *Num) Scan(src interface{}) error](#Num.Scan)
@@ -250,6 +254,7 @@ There are differences, however a lot of it is relevant.
250254
[changetype_string.go](/changetype_string.go) [columnflag_string.go](/columnflag_string.go) [datatype_string.go](/datatype_string.go) [doc.go](/doc.go) [driver.go](/driver.go) [messages.go](/messages.go) [num.go](/num.go) [result.go](/result.go) [rows.go](/rows.go) [session.go](/session.go) [stmt.go](/stmt.go) [tabular_messages.go](/tabular_messages.go) [token_string.go](/token_string.go) [types.go](/types.go)
251255

252256

257+
253258
## <a name="pkg-variables">Variables</a>
254259
``` go
255260
var ErrBadType = errors.New("invalid type given")
@@ -286,7 +291,7 @@ ErrUnsupportedPassWordEncrytion is caused by an unsupported password encrytion s
286291

287292

288293

289-
## <a name="Conn">type</a> [Conn](/driver.go?s=979:1009#L45)
294+
## <a name="Conn">type</a> [Conn](/driver.go?s=896:926#L40)
290295
``` go
291296
type Conn struct {
292297
// contains filtered or unexported fields
@@ -301,7 +306,7 @@ Conn encapsulates a tds session and satisties driver.Connc
301306

302307

303308

304-
### <a name="NewConn">func</a> [NewConn](/driver.go?s=3259:3298#L137)
309+
### <a name="NewConn">func</a> [NewConn](/driver.go?s=3176:3215#L132)
305310
``` go
306311
func NewConn(dsn string) (*Conn, error)
307312
```
@@ -311,14 +316,14 @@ NewConn returns a TDS session
311316

312317

313318

314-
### <a name="Conn.Begin">func</a> (Conn) [Begin](/session.go?s=8440:8484#L316)
319+
### <a name="Conn.Begin">func</a> (Conn) [Begin](/session.go?s=8339:8383#L316)
315320
``` go
316321
func (s Conn) Begin() (driver.Tx, error)
317322
```
318323

319324

320325

321-
### <a name="Conn.BeginTx">func</a> (Conn) [BeginTx](/session.go?s=9292:9380#L335)
326+
### <a name="Conn.BeginTx">func</a> (Conn) [BeginTx](/session.go?s=9191:9279#L335)
322327
``` go
323328
func (s Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)
324329
```
@@ -327,7 +332,7 @@ BeginTx implements driver.ConnBeginTx interface
327332

328333

329334

330-
### <a name="Conn.Close">func</a> (Conn) [Close](/session.go?s=8114:8145#L302)
335+
### <a name="Conn.Close">func</a> (Conn) [Close](/session.go?s=8013:8044#L302)
331336
``` go
332337
func (s Conn) Close() error
333338
```
@@ -337,14 +342,14 @@ by sending logout message and closing tcp connection.
337342

338343

339344

340-
### <a name="Conn.Commit">func</a> (Conn) [Commit](/session.go?s=10422:10454#L369)
345+
### <a name="Conn.Commit">func</a> (Conn) [Commit](/session.go?s=10321:10353#L369)
341346
``` go
342347
func (s Conn) Commit() error
343348
```
344349

345350

346351

347-
### <a name="Conn.Exec">func</a> (Conn) [Exec](/session.go?s=12274:12354#L435)
352+
### <a name="Conn.Exec">func</a> (Conn) [Exec](/session.go?s=12173:12253#L435)
348353
``` go
349354
func (s Conn) Exec(query string, args []driver.Value) (driver.Result, error)
350355
```
@@ -354,7 +359,7 @@ The aim is to use language queries when no parameters are given
354359

355360

356361

357-
### <a name="Conn.ExecContext">func</a> (Conn) [ExecContext](/session.go?s=12490:12609#L444)
362+
### <a name="Conn.ExecContext">func</a> (Conn) [ExecContext](/session.go?s=12389:12508#L444)
358363
``` go
359364
func (s Conn) ExecContext(ctx context.Context, query string,
360365
namedArgs []driver.NamedValue) (driver.Result, error)
@@ -364,7 +369,7 @@ Implement the "ExecerContext" interface
364369

365370

366371

367-
### <a name="Conn.GetEnv">func</a> (Conn) [GetEnv](/driver.go?s=3976:4016#L169)
372+
### <a name="Conn.GetEnv">func</a> (Conn) [GetEnv](/driver.go?s=3850:3890#L161)
368373
``` go
369374
func (c Conn) GetEnv() map[string]string
370375
```
@@ -379,7 +384,7 @@ The following keys are garanteed to be present:
379384

380385

381386

382-
### <a name="Conn.Ping">func</a> (Conn) [Ping](/session.go?s=10919:10968#L382)
387+
### <a name="Conn.Ping">func</a> (Conn) [Ping](/session.go?s=10818:10867#L382)
383388
``` go
384389
func (s Conn) Ping(ctx context.Context) error
385390
```
@@ -388,7 +393,7 @@ Ping implements driver.Pinger interface
388393

389394

390395

391-
### <a name="Conn.Prepare">func</a> (Conn) [Prepare](/session.go?s=13078:13138#L469)
396+
### <a name="Conn.Prepare">func</a> (Conn) [Prepare](/session.go?s=12977:13037#L469)
392397
``` go
393398
func (s Conn) Prepare(query string) (driver.Stmt, error)
394399
```
@@ -397,7 +402,7 @@ Prepare prepares a statement and returns it
397402

398403

399404

400-
### <a name="Conn.PrepareContext">func</a> (Conn) [PrepareContext](/session.go?s=13271:13359#L477)
405+
### <a name="Conn.PrepareContext">func</a> (Conn) [PrepareContext](/session.go?s=13170:13258#L477)
401406
``` go
402407
func (s Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)
403408
```
@@ -406,7 +411,7 @@ Prepare prepares a statement and returns it
406411

407412

408413

409-
### <a name="Conn.Query">func</a> (Conn) [Query](/session.go?s=11348:11427#L402)
414+
### <a name="Conn.Query">func</a> (Conn) [Query](/session.go?s=11247:11326#L402)
410415
``` go
411416
func (s Conn) Query(query string, args []driver.Value) (driver.Rows, error)
412417
```
@@ -416,7 +421,7 @@ The aim is to use language queries when no parameters are given
416421

417422

418423

419-
### <a name="Conn.QueryContext">func</a> (Conn) [QueryContext](/session.go?s=11564:11682#L410)
424+
### <a name="Conn.QueryContext">func</a> (Conn) [QueryContext](/session.go?s=11463:11581#L410)
420425
``` go
421426
func (s Conn) QueryContext(ctx context.Context, query string,
422427
namedArgs []driver.NamedValue) (driver.Rows, error)
@@ -426,14 +431,14 @@ Implement the "QueryerContext" interface
426431

427432

428433

429-
### <a name="Conn.Rollback">func</a> (Conn) [Rollback](/session.go?s=10646:10680#L375)
434+
### <a name="Conn.Rollback">func</a> (Conn) [Rollback](/session.go?s=10545:10579#L375)
430435
``` go
431436
func (s Conn) Rollback() error
432437
```
433438

434439

435440

436-
### <a name="Conn.SelectValue">func</a> (Conn) [SelectValue](/session.go?s=13490:13585#L485)
441+
### <a name="Conn.SelectValue">func</a> (Conn) [SelectValue](/session.go?s=13389:13484#L485)
437442
``` go
438443
func (s Conn) SelectValue(ctx context.Context, query string) (value interface{}, err error)
439444
```
@@ -442,7 +447,7 @@ Reads exactly one value from an sql query
442447

443448

444449

445-
### <a name="Conn.SetErrorhandler">func</a> (\*Conn) [SetErrorhandler](/driver.go?s=3747:3803#L160)
450+
### <a name="Conn.SetErrorhandler">func</a> (\*Conn) [SetErrorhandler](/driver.go?s=3621:3677#L152)
446451
``` go
447452
func (c *Conn) SetErrorhandler(fn func(s SybError) bool)
448453
```
@@ -453,21 +458,6 @@ indicating if this message is indeed a critical error.
453458

454459

455460

456-
## <a name="Errorhandler">type</a> [Errorhandler](/driver.go?s=842:915#L40)
457-
``` go
458-
type Errorhandler interface {
459-
SetErrorHandler(func(m sqlMessage) bool)
460-
}
461-
```
462-
463-
464-
465-
466-
467-
468-
469-
470-
471461
## <a name="Num">type</a> [Num](/num.go?s=758:844#L32)
472462
``` go
473463
type Num struct {
@@ -772,13 +762,7 @@ Stmt is a prepared statement implementing the driver.Stmt interface
772762

773763

774764

775-
776-
777-
778-
779-
780-
781-
### <a name="Stmt.Close">func</a> (\*Stmt) [Close](/stmt.go?s=5611:5640#L207)
765+
### <a name="Stmt.Close">func</a> (\*Stmt) [Close](/stmt.go?s=5633:5662#L207)
782766
``` go
783767
func (st *Stmt) Close() error
784768
```
@@ -787,7 +771,7 @@ Close drops the prepared statement from the database
787771

788772

789773

790-
### <a name="Stmt.ColumnConverter">func</a> (Stmt) [ColumnConverter](/stmt.go?s=6184:6245#L226)
774+
### <a name="Stmt.ColumnConverter">func</a> (Stmt) [ColumnConverter](/stmt.go?s=6206:6267#L226)
791775
``` go
792776
func (st Stmt) ColumnConverter(idx int) driver.ValueConverter
793777
```
@@ -797,7 +781,7 @@ precision, scale and then convert to a valid sql.Driver value.
797781

798782

799783

800-
### <a name="Stmt.Exec">func</a> (\*Stmt) [Exec](/stmt.go?s=3256:3328#L131)
784+
### <a name="Stmt.Exec">func</a> (\*Stmt) [Exec](/stmt.go?s=3278:3350#L131)
801785
``` go
802786
func (st *Stmt) Exec(args []driver.Value) (res driver.Result, err error)
803787
```
@@ -807,7 +791,7 @@ Implements the database/sql/Stmt interface
807791

808792

809793

810-
### <a name="Stmt.ExecContext">func</a> (\*Stmt) [ExecContext](/stmt.go?s=3819:3929#L150)
794+
### <a name="Stmt.ExecContext">func</a> (\*Stmt) [ExecContext](/stmt.go?s=3841:3951#L150)
811795
``` go
812796
func (st *Stmt) ExecContext(ctx context.Context, namedArgs []driver.NamedValue) (res driver.Result, err error)
813797
```
@@ -817,7 +801,7 @@ Implements the database/sql/Stmt interface
817801

818802

819803

820-
### <a name="Stmt.NumInput">func</a> (Stmt) [NumInput](/stmt.go?s=5492:5521#L202)
804+
### <a name="Stmt.NumInput">func</a> (Stmt) [NumInput](/stmt.go?s=5514:5543#L202)
821805
``` go
822806
func (st Stmt) NumInput() int
823807
```
@@ -826,7 +810,7 @@ NumInput returns the number of expected parameters
826810

827811

828812

829-
### <a name="Stmt.Query">func</a> (\*Stmt) [Query](/stmt.go?s=4554:4617#L175)
813+
### <a name="Stmt.Query">func</a> (\*Stmt) [Query](/stmt.go?s=4576:4639#L175)
830814
``` go
831815
func (st *Stmt) Query(args []driver.Value) (driver.Rows, error)
832816
```
@@ -835,7 +819,7 @@ Query executes a prepared statement and returns rows.
835819

836820

837821

838-
### <a name="Stmt.QueryContext">func</a> (\*Stmt) [QueryContext](/stmt.go?s=4960:5061#L186)
822+
### <a name="Stmt.QueryContext">func</a> (\*Stmt) [QueryContext](/stmt.go?s=4982:5083#L186)
839823
``` go
840824
func (st *Stmt) QueryContext(ctx context.Context, namedArgs []driver.NamedValue) (driver.Rows, error)
841825
```
@@ -879,3 +863,10 @@ implement the error interface
879863

880864

881865

866+
867+
868+
869+
870+
871+
- - -
872+
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)

doc.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use the regular database/sql APIs:
3232
)
3333
3434
func main() {
35-
cnxStr := "tds://my_user:my_password@dbhost.com:5000/pubs?charset=utf8
35+
cnxStr := "tds://my_user:my_password@dbhost.com:5000/pubs?charset=utf8"
3636
db, err := sql.Open("tds", connStr)
3737
if err != nil {
3838
log.Fatal(err)
@@ -68,7 +68,7 @@ It is suggested to raise it to avoid truncation.
6868
6969
Less frequently used ones:
7070
71-
* ssl - Whether or not to use SSL. THe default is not to use ssl.
71+
* ssl - Whether or not to use SSL. The default is not to use ssl.
7272
Set to "on" if the server is setup to use ssl.
7373
* encryptPassword - Can be "yes" to require password encryption,
7474
"no" to disable it, and "try" to try encrytping password an falling back
@@ -143,7 +143,7 @@ You must cast your database/sql connection as sql.Conn to use this extension.
143143
144144
The following demonstrates how to handle showplan and print messages:
145145
146-
conn = goConn.(*tds.Conn)
146+
conn := goConn.(*tds.Conn)
147147
148148
// print showplan messages and all
149149
conn.SetErrorhandler(func(m tds.SybError) bool {

session.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,13 @@ loginResponse:
212212
try = 1
213213
block, _ := pem.Decode(p.data[1].([]byte))
214214
if block == nil {
215-
return fmt.Errorf("tds: login failed. Cannot parse server's public key PEM: %s", err)
215+
return ErrUnsupportedPassWordEncrytion
216216
}
217217

218218
var pk rsa.PublicKey
219219
_, err := asn1.Unmarshal(block.Bytes, &pk)
220220
if err != nil {
221-
return fmt.Errorf("tds: login failed. Cannot parse server's public key using ans1: %s", err)
221+
return ErrUnsupportedPassWordEncrytion
222222
}
223223

224224
// nonce introduces randomness to avoid replay attacks

stmt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func newStmt(ctx context.Context, s *session, query string) (*Stmt, error) {
4343
return st, driver.ErrBadConn
4444
}
4545

46-
params := &columns{msg: newMsg(ParamFmt)}
47-
wideParams := &columns{msg: newMsg(ParamFmt2), flags: wide}
46+
params := &columns{msg: newMsg(ParamFmt), flags: param}
47+
wideParams := &columns{msg: newMsg(ParamFmt2), flags: wide | param}
4848
st.row = &row{msg: newMsg(Param)}
4949

5050
// get a statement number

0 commit comments

Comments
 (0)