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 }