diff --git a/mssqlconn/config.go b/mssqlconn/config.go new file mode 100644 index 0000000..c5df5ef --- /dev/null +++ b/mssqlconn/config.go @@ -0,0 +1,23 @@ +package mssqlconn + +import ( + "fmt" + "regexp" +) + +const ( + Driver = "sqlserver" + + argFmt = "@p%d" +) + +// TODO allow spaces and other characters and escaping with backticks +var columnNameRegex = regexp.MustCompile(`^[0-9a-zA-Z$_]{1,64}$`) + +// https://learn.microsoft.com/en-us/sql/odbc/microsoft/column-name-limitations +func validateColumnName(name string) error { + if !columnNameRegex.MatchString(name) { + return fmt.Errorf("invalid Microsoft SQL Server column name: %q", name) + } + return nil +} diff --git a/mssqlconn/connection.go b/mssqlconn/connection.go new file mode 100644 index 0000000..e60cc74 --- /dev/null +++ b/mssqlconn/connection.go @@ -0,0 +1,33 @@ +package mssqlconn + +import ( + "context" + "database/sql" + "fmt" + + _ "github.com/microsoft/go-mssqldb" + + "github.com/domonda/go-sqldb" + "github.com/domonda/go-sqldb/impl" +) + +func New(ctx context.Context, config *sqldb.Config) (sqldb.Connection, error) { + if config.Driver != Driver { + return nil, fmt.Errorf(`invalid driver %q, expected %q`, config.Driver, Driver) + } + config.DefaultIsolationLevel = sql.LevelReadCommitted // Microsoft SQL Server default + + db, err := config.Connect(ctx) + if err != nil { + return nil, err + } + return impl.Connection(ctx, db, config, validateColumnName, argFmt), nil +} + +func MustNew(ctx context.Context, config *sqldb.Config) sqldb.Connection { + conn, err := New(ctx, config) + if err != nil { + panic(err) + } + return conn +} diff --git a/mssqlconn/go.mod b/mssqlconn/go.mod new file mode 100644 index 0000000..e9b7bca --- /dev/null +++ b/mssqlconn/go.mod @@ -0,0 +1,19 @@ +module github.com/domonda/go-sqldb/mssqlconn + +go 1.22.0 + +replace github.com/domonda/go-sqldb => ../ + +require ( + github.com/domonda/go-sqldb v0.0.0-20240122205319-56db59ae89d2 + github.com/microsoft/go-mssqldb v1.7.0 +) + +require ( + github.com/domonda/go-types v0.0.0-20240301143218-7f4371e713b4 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/lib/pq v1.10.9 // indirect + golang.org/x/crypto v0.20.0 // indirect + golang.org/x/text v0.14.0 // indirect +)