github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/xsql/dsn.go (about)

     1  package xsql
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/ydb-platform/ydb-go-sdk/v3/balancers"
    10  	"github.com/ydb-platform/ydb-go-sdk/v3/config"
    11  	"github.com/ydb-platform/ydb-go-sdk/v3/credentials"
    12  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/bind"
    13  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/dsn"
    14  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
    15  )
    16  
    17  const tablePathPrefixTransformer = "table_path_prefix"
    18  
    19  func Parse(dataSourceName string) (opts []config.Option, connectorOpts []ConnectorOption, _ error) {
    20  	info, err := dsn.Parse(dataSourceName)
    21  	if err != nil {
    22  		return nil, nil, xerrors.WithStackTrace(err)
    23  	}
    24  	opts = append(opts, info.Options...)
    25  	if token := info.Params.Get("token"); token != "" {
    26  		opts = append(opts, config.WithCredentials(credentials.NewAccessTokenCredentials(token)))
    27  	}
    28  	if balancer := info.Params.Get("go_balancer"); balancer != "" {
    29  		opts = append(opts, config.WithBalancer(balancers.FromConfig(balancer)))
    30  	} else if balancer := info.Params.Get("balancer"); balancer != "" {
    31  		opts = append(opts, config.WithBalancer(balancers.FromConfig(balancer)))
    32  	}
    33  	if queryMode := info.Params.Get("go_query_mode"); queryMode != "" {
    34  		mode := QueryModeFromString(queryMode)
    35  		if mode == UnknownQueryMode {
    36  			return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
    37  		}
    38  		connectorOpts = append(connectorOpts, WithDefaultQueryMode(mode))
    39  	} else if queryMode := info.Params.Get("query_mode"); queryMode != "" {
    40  		mode := QueryModeFromString(queryMode)
    41  		if mode == UnknownQueryMode {
    42  			return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
    43  		}
    44  		connectorOpts = append(connectorOpts, WithDefaultQueryMode(mode))
    45  	}
    46  	if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" {
    47  		for _, queryMode := range strings.Split(fakeTx, ",") {
    48  			mode := QueryModeFromString(queryMode)
    49  			if mode == UnknownQueryMode {
    50  				return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
    51  			}
    52  			connectorOpts = append(connectorOpts, WithFakeTx(mode))
    53  		}
    54  	}
    55  	if info.Params.Has("go_query_bind") {
    56  		var binders []ConnectorOption
    57  		queryTransformers := strings.Split(info.Params.Get("go_query_bind"), ",")
    58  		for _, transformer := range queryTransformers {
    59  			switch transformer {
    60  			case "declare":
    61  				binders = append(binders, WithQueryBind(bind.AutoDeclare{}))
    62  			case "positional":
    63  				binders = append(binders, WithQueryBind(bind.PositionalArgs{}))
    64  			case "numeric":
    65  				binders = append(binders, WithQueryBind(bind.NumericArgs{}))
    66  			default:
    67  				if strings.HasPrefix(transformer, tablePathPrefixTransformer) {
    68  					prefix, err := extractTablePathPrefixFromBinderName(transformer)
    69  					if err != nil {
    70  						return nil, nil, xerrors.WithStackTrace(err)
    71  					}
    72  					binders = append(binders, WithTablePathPrefix(prefix))
    73  				} else {
    74  					return nil, nil, xerrors.WithStackTrace(
    75  						fmt.Errorf("unknown query rewriter: %s", transformer),
    76  					)
    77  				}
    78  			}
    79  		}
    80  		connectorOpts = append(connectorOpts, binders...)
    81  	}
    82  
    83  	return opts, connectorOpts, nil
    84  }
    85  
    86  var (
    87  	tablePathPrefixRe       = regexp.MustCompile(tablePathPrefixTransformer + "\\((.*)\\)")
    88  	errWrongTablePathPrefix = errors.New("wrong '" + tablePathPrefixTransformer + "' query transformer")
    89  )
    90  
    91  func extractTablePathPrefixFromBinderName(binderName string) (string, error) {
    92  	ss := tablePathPrefixRe.FindAllStringSubmatch(binderName, -1)
    93  	if len(ss) != 1 || len(ss[0]) != 2 || ss[0][1] == "" {
    94  		return "", xerrors.WithStackTrace(fmt.Errorf("%w: %s", errWrongTablePathPrefix, binderName))
    95  	}
    96  
    97  	return ss[0][1], nil
    98  }