...

Source file src/cloud.google.com/go/cloudsqlconn/sqlserver/mssql/mssql.go

Documentation: cloud.google.com/go/cloudsqlconn/sqlserver/mssql

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package mssql provides a Cloud SQL SQL Server driver that works with the
    16  // database/sql package.
    17  package mssql
    18  
    19  import (
    20  	"context"
    21  	"database/sql"
    22  	"database/sql/driver"
    23  	"net"
    24  
    25  	"cloud.google.com/go/cloudsqlconn"
    26  	mssqldb "github.com/microsoft/go-mssqldb"
    27  	"github.com/microsoft/go-mssqldb/msdsn"
    28  )
    29  
    30  // RegisterDriver registers a SQL Server driver that uses the
    31  // cloudsqlconn.Dialer configured with the provided options. The choice of name
    32  // is entirely up to the caller and may be used to distinguish between multiple
    33  // registrations of differently configured Dialers.
    34  func RegisterDriver(name string, opts ...cloudsqlconn.Option) (func() error, error) {
    35  	d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
    36  	if err != nil {
    37  		return func() error { return nil }, err
    38  	}
    39  	sql.Register(name, &sqlserverDriver{
    40  		d: d,
    41  	})
    42  	return func() error { return d.Close() }, nil
    43  }
    44  
    45  type csqlDialer struct {
    46  	driver.Conn
    47  
    48  	d        *cloudsqlconn.Dialer
    49  	connName string
    50  }
    51  
    52  // DialContext adheres to the mssql.Dialer interface.
    53  func (c *csqlDialer) DialContext(ctx context.Context, _, _ string) (net.Conn, error) {
    54  	return c.d.Dial(ctx, c.connName)
    55  }
    56  
    57  // Close ensures the cloudsqlconn.Dialer is closed before the conncetion is
    58  // closed.
    59  func (c *csqlDialer) Close() error {
    60  	c.d.Close()
    61  	return c.Conn.Close()
    62  }
    63  
    64  type sqlserverDriver struct {
    65  	d *cloudsqlconn.Dialer
    66  }
    67  
    68  // Open accepts a URL, ADO, or ODBC style connection string and returns a
    69  // connection to the database using cloudsqlconn.Dialer. The Cloud SQL instance
    70  // connection name should be specified in a "cloudsql" parameter. For example:
    71  //
    72  // "sqlserver://user:password@localhost?database=mydb&cloudsql=my-proj:us-central1:my-inst"
    73  //
    74  // For details, see
    75  // https://github.com/microsoft/go-mssqldb#the-connection-string-can-be-specified-in-one-of-three-formats
    76  func (s *sqlserverDriver) Open(name string) (driver.Conn, error) {
    77  	res, err := msdsn.Parse(name)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	c, err := mssqldb.NewConnector(name)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	connName := res.Parameters["cloudsql"]
    86  	c.Dialer = &csqlDialer{
    87  		d:        s.d,
    88  		connName: connName,
    89  	}
    90  	return c.Connect(context.Background())
    91  }
    92  

View as plain text