From de3c1fd2f33d941a446880cee9b3c341f0c81c89 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Thu, 10 Mar 2022 19:04:02 +1100 Subject: [PATCH] embedded-excised --- .vscode/launch.json | 16 +++--- docs/developer_guide.md | 6 ++- examples/README.md | 15 ++++++ go.mod | 6 +-- go.sum | 20 ++++++++ internal/stackql/cmd/registry.go | 44 ++++++++++------ internal/stackql/cmd/root.go | 26 +++++----- internal/stackql/planbuilder/plan_builder.go | 50 +++++++++++++++++++ .../planbuilder/primitive_generator.go | 8 +++ .../stackql/planbuilder/statement_analyzer.go | 7 +++ internal/stackql/util/plan_utility.go | 15 ++++++ test/functional/stackql_from_cmd_line.robot | 12 ----- 12 files changed, 174 insertions(+), 51 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index b407fa35..9c4ea120 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,11 +16,11 @@ ] }, { - "name": "Launch exec \"show services from google where name = 'abusiveexperiencereport';\" -- prebuilt with cmake", + "name": "Debug exec \"show services from google where name = 'abusiveexperiencereport';\" -- prebuilt with cmake", "type": "go", "request": "launch", - "mode": "exec", - "program": "${workspaceFolder}/build/stackql", + "mode": "debug", + "program": "${workspaceFolder}/stackql", "args": [ "exec", "show services from google where name = 'abusiveexperiencereport';" @@ -38,18 +38,18 @@ ], }, { - "name": "Launch exec \"DESCRIBE compute.instances;\" -- prebuilt with cmake", + "name": "Debug \"DESCRIBE google.compute.instances;\" -- prebuilt with cmake", "type": "go", "request": "launch", - "mode": "exec", - "program": "${workspaceFolder}/build/stackql", + "mode": "debug", + "program": "${workspaceFolder}/stackql", "args": [ "exec", - "DESCRIBE compute.instances;", // "--offline" + "DESCRIBE google.compute.instances;", // "--offline" ], }, { - "name": "Launch exec \"DESCRIBE compute.disks;\" -- prebuilt with cmake", + "name": "Launch exec \"DESCRIBE google.compute.disks;\" -- prebuilt with cmake", "type": "go", "request": "launch", "mode": "exec", diff --git a/docs/developer_guide.md b/docs/developer_guide.md index dbd73bf0..50a3d42a 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -19,14 +19,16 @@ The following are potentially multi threaded: ## Rebuilding Parser +First, go to the root of the vitess repository. + ```bash -make -C vitess.io/vitess/go/vt/sqlparser +make -C go/vt/sqlparser ``` If you need to add new AST node types, make sure to add them to [go/vt/sqlparser/ast.go](https://github.com/stackql/vitess/blob/feature/stackql-develop/go/vt/sqlparser/ast.go) and then regenerate the file [go/vt/sqlparser/rewriter.go](https://github.com/stackql/vitess/blob/feature/stackql-develop/go/vt/sqlparser/rewriter.go) as follows: ``` -cd vitess.io/vitess/go/vt/sqlparser +cd go/vt/sqlparser go run ./visitorgen/main -input=ast.go -output=rewriter.go ``` diff --git a/examples/README.md b/examples/README.md index 6992f5b8..7c5e54a9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,4 +1,15 @@ +## BYO Registry + + +```bash + +PROVIDER_REGISTRY_ROOT_DIR="$(pwd)/../examples/registry" + +REG_STR='{ "url": "useEmbedded": false }' + +``` + ## BYO Registry @@ -9,7 +20,11 @@ PROVIDER_REGISTRY_ROOT_DIR="$(pwd)/../examples/registry" REG_STR='{ "url": "file://'${PROVIDER_REGISTRY_ROOT_DIR}'", "localDocRoot": "'${PROVIDER_REGISTRY_ROOT_DIR}'", "useEmbedded": false, "verifyConfig": {"nopVerify": true } }' +``` +## Interacting with the registry + +```bash ## All auth required ahead of time at this stage, even for no auth providers AUTH_STR='{ "publicapis": { "type": "null_auth" } }' diff --git a/go.mod b/go.mod index d76d0993..e966d781 100644 --- a/go.mod +++ b/go.mod @@ -13,18 +13,18 @@ require ( github.com/spf13/cobra v1.3.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.1 - github.com/stackql/go-openapistackql v0.0.4-alpha55 + github.com/stackql/go-openapistackql v0.0.5-alpha05 github.com/stackql/go-sqlite3 v0.0.1-stackqlalpha golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gopkg.in/yaml.v2 v2.4.0 readline v0.0.0-00010101000000-000000000000 - vitess.io/vitess v0.0.9-alpha7 + vitess.io/vitess v0.0.10-alpha5 ) replace readline => github.com/stackql/readline v0.0.0-20210418072316-6e4ad520d2b4 replace github.com/fatih/color => github.com/stackql/color v1.10.1-0.20210418074258-4aa529ee76ed -replace vitess.io/vitess => github.com/stackql/vitess v0.0.9-alpha7 +replace vitess.io/vitess => github.com/stackql/vitess v0.0.10-alpha5 diff --git a/go.sum b/go.sum index be1adc93..95c9cbe6 100644 --- a/go.sum +++ b/go.sum @@ -613,6 +613,16 @@ github.com/stackql/go-openapistackql v0.0.4-alpha54 h1:oPSnENVuyl3xSP4ZLfT1PwruS github.com/stackql/go-openapistackql v0.0.4-alpha54/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= github.com/stackql/go-openapistackql v0.0.4-alpha55 h1:lZUEkI/yLtaFY1YaDK4OeFFGUFFtCVHdpBaTYCcvOsc= github.com/stackql/go-openapistackql v0.0.4-alpha55/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= +github.com/stackql/go-openapistackql v0.0.5-alpha01 h1:loKAhonxaSFaxsTx0s8FkbJypiSPibFbI8zYh43U0SY= +github.com/stackql/go-openapistackql v0.0.5-alpha01/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= +github.com/stackql/go-openapistackql v0.0.5-alpha02 h1:9TxR+0Z5RK6cWg9HsLgP5EDOhtXNPg9wX8aAq+IFVd0= +github.com/stackql/go-openapistackql v0.0.5-alpha02/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= +github.com/stackql/go-openapistackql v0.0.5-alpha03 h1:0EW+Qb+3oI2Z8fVzdjjVtk7u1ajtt31P8vY/pdAMmzY= +github.com/stackql/go-openapistackql v0.0.5-alpha03/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= +github.com/stackql/go-openapistackql v0.0.5-alpha04 h1:y9O/Bqi04jQnrtgst4KX8sNY2Jw8WP3VYXxJBkkn99E= +github.com/stackql/go-openapistackql v0.0.5-alpha04/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= +github.com/stackql/go-openapistackql v0.0.5-alpha05 h1:bJ82UH0p7dlx+UvUKBpCkeozG5LrAqu8AQaDsU9MnnI= +github.com/stackql/go-openapistackql v0.0.5-alpha05/go.mod h1:DSVjQrASsDMSP+9r+iE3rKFWJ+4XDkIRF8pjUjsaNC4= github.com/stackql/go-spew v1.1.3-alpha24 h1:yNmgWU+OKU8SvlQ0umiQWWgWS6C5U1GuRMlYfQgbmJA= github.com/stackql/go-spew v1.1.3-alpha24/go.mod h1:o2MPqg2ee1PN4SxAh9zQSJJmKKFJjpro9pejdK7dXWk= github.com/stackql/go-sqlite3 v0.0.1-stackqlalpha h1:Ze9rqvLF76IuI42KqffAmBBQcIgInQrGJQkmTcoVRTI= @@ -624,6 +634,16 @@ github.com/stackql/stackql-provider-registry v0.0.1-alpha903 h1:S0W2zFWXxiBYiXxG github.com/stackql/stackql-provider-registry v0.0.1-alpha903/go.mod h1:D0WFWa7HOXS+PQAmvN0Nm1E6dMdUkUFtAzRH8cXxg88= github.com/stackql/vitess v0.0.9-alpha7 h1:CBCPeyH0yzz2cgswVjWYDqdZi6mE6kZZQ268kWopFwQ= github.com/stackql/vitess v0.0.9-alpha7/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= +github.com/stackql/vitess v0.0.10-alpha1 h1:oYn54nh8QJt9OsvUb044wT+cKrCL9MK4ElD5H1wimj4= +github.com/stackql/vitess v0.0.10-alpha1/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= +github.com/stackql/vitess v0.0.10-alpha2 h1:Aa6lKhnScQFxRvZCI0wmhroxFZh8mFRoHFtFPwUfaao= +github.com/stackql/vitess v0.0.10-alpha2/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= +github.com/stackql/vitess v0.0.10-alpha3 h1:eI9VMiaPBAelmAv7xVVuWuxiaFlpsJ4DL+nMFvDrNaE= +github.com/stackql/vitess v0.0.10-alpha3/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= +github.com/stackql/vitess v0.0.10-alpha4 h1:YrgtRqFYAPxut/lb9q9x/5Jw8pyyV5ON46dR2GzxQL0= +github.com/stackql/vitess v0.0.10-alpha4/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= +github.com/stackql/vitess v0.0.10-alpha5 h1:AEVzt8eCJY8rVqVruft2N/nXGw8EmE3AJ+cBvLq4Uuc= +github.com/stackql/vitess v0.0.10-alpha5/go.mod h1:4M5NhkFYCF10+U3LS4owUYY2GsUt+7t1kN9Rv5UVc9A= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= diff --git a/internal/stackql/cmd/registry.go b/internal/stackql/cmd/registry.go index d1e595bd..250eb8df 100644 --- a/internal/stackql/cmd/registry.go +++ b/internal/stackql/cmd/registry.go @@ -16,35 +16,42 @@ limitations under the License. package cmd import ( + "bytes" + "fmt" + "io" + "strings" + "github.com/spf13/cobra" - "github.com/stackql/stackql/internal/stackql/handler" + "github.com/stackql/stackql/internal/stackql/entryutil" "github.com/stackql/stackql/internal/stackql/iqlerror" ) -// execCmd represents the exec command +const ( + forbiddenRegistryCharacters string = ` ;\` +) + var registryCmd = &cobra.Command{ Use: "registry", - Short: "Interaction with the provider registry, as configured at initialisation time. Usage: stackql registry {subcommand} [{arg}]", + Short: "Interaction with the stackql provider registry, as configured at initialisation time. Usage: stackql registry {subcommand} [{arg}]", Long: ` Interaction with the provider registry, as configured at initialisation time. Usage: stackql registry {subcommand} Currently supported subcommands: - pull {provider} {version} - + - list `, Run: func(cmd *cobra.Command, args []string) { + + var rdr io.Reader + usagemsg := cmd.Long + "\n\n" + cmd.UsageString() if len(args) < 1 { iqlerror.PrintErrorAndExitOneWithMessage(usagemsg) } - reg, err := handler.GetRegistry(runtimeCtx) - if err != nil { - iqlerror.PrintErrorAndExitOneWithMessage(err.Error()) - } if len(args) == 0 { iqlerror.PrintErrorAndExitOneWithMessage(usagemsg) } - subCommand := args[0] + subCommand := strings.ToLower(args[0]) switch subCommand { case "pull": if len(args) != 3 { @@ -52,12 +59,21 @@ var registryCmd = &cobra.Command{ } providerName := args[1] providerVersion := args[2] - err := reg.PullAndPersistProviderArchive(providerName, providerVersion) - if err != nil { - iqlerror.PrintErrorAndExitOneWithMessage(err.Error()) + + if strings.ContainsAny(providerName, forbiddenRegistryCharacters) || strings.ContainsAny(providerVersion, forbiddenRegistryCharacters) { + iqlerror.PrintErrorAndExitOneWithMessage("forbidden characters detected") } - return + rdr = bytes.NewReader([]byte(fmt.Sprintf("registry pull %s %s;", providerName, providerVersion))) + case "list": + rdr = bytes.NewReader([]byte("registry list;")) } - iqlerror.PrintErrorAndExitOneWithMessage(usagemsg) + + sqlEngine, err := entryutil.BuildSQLEngine(runtimeCtx) + iqlerror.PrintErrorAndExitOneIfError(err) + handlerCtx, err := entryutil.BuildHandlerContext(runtimeCtx, rdr, queryCache, sqlEngine) + iqlerror.PrintErrorAndExitOneIfError(err) + iqlerror.PrintErrorAndExitOneIfNil(&handlerCtx, "Handler context error") + RunCommand(&handlerCtx, nil, nil) + }, } diff --git a/internal/stackql/cmd/root.go b/internal/stackql/cmd/root.go index 643746ba..b6ed557f 100644 --- a/internal/stackql/cmd/root.go +++ b/internal/stackql/cmd/root.go @@ -62,16 +62,18 @@ var ( var rootCmd = &cobra.Command{ Use: "stackql", Version: SemVersion, - Short: "Cloud infrastructure coding using SQL", + Short: "Cloud asset management and automation using SQL", Long: ` - _ __ _ ___ ___ __ __ _ - | | \| | __| _ \/ \ /__\| | - | | | ' | _|| v / /\ | \/ | |_ - |_|_|\__|_| |_|_\_||_|\_V_\___| - -Cloud infrastructure coding using SQL. For example: - -SELECT * FROM google.compute.instances;`, + __ __ __ + _____/ /_____ ______/ /______ _/ / + / ___/ __/ __ / ___/ //_/ __ / / + (__ ) /_/ /_/ / /__/ ,< / /_/ / / +/____/\__/\__,_/\___/_/|_|\__, /_/ + /_/ +Cloud asset management and automation using SQL. For example: + +SELECT name, status FROM google.compute.instances +WHERE project = 'my-project' AND zone = 'us-west1-b';`, Run: func(cmd *cobra.Command, args []string) { // in the root command is executed with no arguments, print the help message usagemsg := cmd.Long + "\n\n" + cmd.UsageString() @@ -98,18 +100,18 @@ func init() { rootCmd.PersistentFlags().IntVar(&runtimeCtx.APIRequestTimeout, dto.APIRequestTimeoutKey, 45, "API request timeout in seconds, 0 for no timeout.") rootCmd.PersistentFlags().StringVar(&runtimeCtx.ColorScheme, dto.ColorSchemeKey, config.GetDefaultColorScheme(), fmt.Sprintf("Color scheme, must be one of {'%s', '%s', '%s'}", dto.DarkColorScheme, dto.LightColorScheme, dto.NullColorScheme)) rootCmd.PersistentFlags().StringVar(&runtimeCtx.CABundle, dto.CABundleKey, "", fmt.Sprintf("Path to CA bundle, if not specified then system defaults used.")) - rootCmd.PersistentFlags().BoolVar(&runtimeCtx.AllowInsecure, dto.AllowInsecureKey, false, "allow insecure cert trust (not recommended)") + rootCmd.PersistentFlags().BoolVar(&runtimeCtx.AllowInsecure, dto.AllowInsecureKey, false, "Allow trust of insecure certificates (not recommended)") rootCmd.PersistentFlags().StringVar(&runtimeCtx.ConfigFilePath, dto.ConfigFilePathKey, config.GetDefaultConfigFilePath(), fmt.Sprintf("Config file full path; defaults to current dir")) rootCmd.PersistentFlags().StringVar(&runtimeCtx.ApplicationFilesRootPath, dto.ApplicationFilesRootPathKey, config.GetDefaultApplicationFilesRoot(), fmt.Sprintf("Application config and cache root path")) rootCmd.PersistentFlags().Uint32Var(&runtimeCtx.ApplicationFilesRootPathMode, dto.ApplicationFilesRootPathModeKey, config.GetDefaultProviderCacheDirFileMode(), fmt.Sprintf("Application config and cache file mode")) rootCmd.PersistentFlags().StringVar(&runtimeCtx.ViperCfgFileName, dto.ViperCfgFileNameKey, config.GetDefaultViperConfigFileName(), fmt.Sprintf("Config filename")) rootCmd.PersistentFlags().StringVar(&runtimeCtx.AuthRaw, dto.AuthCtxKey, "", `auth contexts keyvals in json form, eg: '{ "google": { "credentialsfilepath": "/path/to/google/sevice/account/key.json", "type": "service_account" }, "okta": { "credentialsenvvar": "OKTA_SECRET_KEY", "type": "api_key" } }'`) - rootCmd.PersistentFlags().StringVar(&runtimeCtx.RegistryRaw, dto.RegistryRawKey, fmt.Sprintf(`{ "useEmbedded": true, "url": "%s", "localDocRoot": "%s" }`, defaultRegistryUrlString, runtimeCtx.ApplicationFilesRootPath), fmt.Sprintf(`openapi registry context keyvals in json form, eg: '{ "url": "%s" }'.`, defaultRegistryUrlString)) + rootCmd.PersistentFlags().StringVar(&runtimeCtx.RegistryRaw, dto.RegistryRawKey, fmt.Sprintf(`{ "url": "%s", "localDocRoot": "%s" }`, defaultRegistryUrlString, path.Join(runtimeCtx.ApplicationFilesRootPath)), fmt.Sprintf(`openapi registry context keyvals in json form, eg: '{ "url": "%s" }'.`, defaultRegistryUrlString)) rootCmd.PersistentFlags().StringVar(&runtimeCtx.DbEngine, dto.DbEngineKey, config.GetDefaultDbEngine(), fmt.Sprintf("DB engine id")) rootCmd.PersistentFlags().StringVar(&runtimeCtx.DbFilePath, dto.DbFilePathKey, config.GetDefaultDbFilePath(), fmt.Sprintf("DB persistence filename")) rootCmd.PersistentFlags().IntVar(&runtimeCtx.DbGenerationId, dto.DbGenerationIdKey, txncounter.GetNextGenerationId(), fmt.Sprintf("DB generation id")) rootCmd.PersistentFlags().BoolVar(&runtimeCtx.HTTPLogEnabled, dto.HTTPLogEnabledKey, false, "Display http request info in terminal") - rootCmd.PersistentFlags().IntVar(&runtimeCtx.HTTPMaxResults, dto.HTTPMaxResultsKey, -1, "max results per http request, any number <=0 results in no limitation") + rootCmd.PersistentFlags().IntVar(&runtimeCtx.HTTPMaxResults, dto.HTTPMaxResultsKey, -1, "Max results per http request, any number <=0 results in no limitation") rootCmd.PersistentFlags().IntVar(&runtimeCtx.HTTPProxyPort, dto.HTTPProxyPortKey, -1, "http proxy port, any number <=0 will result in the default port for a given scheme (eg: http -> 80)") rootCmd.PersistentFlags().StringVar(&runtimeCtx.HTTPProxyHost, dto.HTTPProxyHostKey, "", "http proxy host, empty means no proxy") rootCmd.PersistentFlags().StringVar(&runtimeCtx.HTTPProxyScheme, dto.HTTPProxySchemeKey, "http", "http proxy scheme, eg 'http'") diff --git a/internal/stackql/planbuilder/plan_builder.go b/internal/stackql/planbuilder/plan_builder.go index 45a86a92..60ed588a 100644 --- a/internal/stackql/planbuilder/plan_builder.go +++ b/internal/stackql/planbuilder/plan_builder.go @@ -2,6 +2,7 @@ package planbuilder import ( "fmt" + "strconv" "strings" "github.com/stackql/stackql/internal/stackql/astvisit" @@ -66,6 +67,8 @@ func (pgb *planGraphBuilder) createInstructionFor(handlerCtx *handler.HandlerCon return pgb.handleInsert(handlerCtx, stmt) case *sqlparser.OtherRead, *sqlparser.OtherAdmin: return iqlerror.GetStatementNotSupportedError("OTHER") + case *sqlparser.Registry: + return pgb.handleRegistry(handlerCtx, stmt) case *sqlparser.Rollback: return iqlerror.GetStatementNotSupportedError("TRANSACTION: ROLLBACK") case *sqlparser.Savepoint: @@ -258,6 +261,53 @@ func (pgb *planGraphBuilder) handleDelete(handlerCtx *handler.HandlerContext, no return nil } +func (pgb *planGraphBuilder) handleRegistry(handlerCtx *handler.HandlerContext, node *sqlparser.Registry) error { + primitiveGenerator := newRootPrimitiveGenerator(node, handlerCtx, pgb.planGraph) + err := primitiveGenerator.analyzeRegistry(handlerCtx, node) + if err != nil { + return err + } + reg, err := handler.GetRegistry(handlerCtx.RuntimeContext) + if err != nil { + return err + } + pr := primitivebuilder.NewLocalPrimitive( + func(pc primitive.IPrimitiveCtx) dto.ExecutorOutput { + switch at := strings.ToLower(node.ActionType); at { + case "pull": + err := reg.PullAndPersistProviderArchive(node.ProviderId, node.ProviderVersion) + if err != nil { + return dto.NewErroneousExecutorOutput(err) + } + return util.PrepareResultSet(dto.NewPrepareResultSetPlusRawDTO(nil, nil, nil, nil, nil, &dto.BackendMessages{WorkingMessages: []string{fmt.Sprintf("%s provider, version '%s' successfully installed", node.ProviderId, node.ProviderVersion)}}, nil)) + case "list": + provz, err := reg.ListAllAvailableProviders() + if err != nil { + return dto.NewErroneousExecutorOutput(err) + } + colz := []string{"provider", "version"} + keys := make(map[string]map[string]interface{}) + i := 0 + for k, v := range provz { + for _, ver := range v.Versions { + keys[strconv.Itoa(i)] = map[string]interface{}{ + "provider": k, + "version": ver, + } + i++ + } + } + return util.PrepareResultSet(dto.NewPrepareResultSetPlusRawDTO(nil, keys, colz, nil, nil, nil, nil)) + default: + return dto.NewErroneousExecutorOutput(fmt.Errorf("registry action '%s' no supported", at)) + } + }, + ) + pgb.planGraph.CreatePrimitiveNode(pr) + + return nil +} + func (pgb *planGraphBuilder) handleInsert(handlerCtx *handler.HandlerContext, node *sqlparser.Insert) error { if !handlerCtx.RuntimeContext.TestWithoutApiCalls { primitiveGenerator := newRootPrimitiveGenerator(node, handlerCtx, pgb.planGraph) diff --git a/internal/stackql/planbuilder/primitive_generator.go b/internal/stackql/planbuilder/primitive_generator.go index a6f7c367..9cc5d01a 100644 --- a/internal/stackql/planbuilder/primitive_generator.go +++ b/internal/stackql/planbuilder/primitive_generator.go @@ -343,6 +343,14 @@ func (pb *primitiveGenerator) showInstructionExecutor(node *sqlparser.Show, hand keys = methodKeys case "PROVIDERS": keys = handlerCtx.GetSupportedProviders(extended) + rv := util.PrepareResultSet(dto.NewPrepareResultSetDTO(nil, keys, columnOrder, nil, err, nil)) + if len(keys) == 0 { + rv = util.EmptyProtectResultSet( + rv, + []string{"name"}, + ) + } + return rv case "RESOURCES": svcName := node.OnTable.Name.GetRawVal() if svcName == "" { diff --git a/internal/stackql/planbuilder/statement_analyzer.go b/internal/stackql/planbuilder/statement_analyzer.go index adf0fd4c..d0b0bf07 100644 --- a/internal/stackql/planbuilder/statement_analyzer.go +++ b/internal/stackql/planbuilder/statement_analyzer.go @@ -58,6 +58,8 @@ func (p *primitiveGenerator) analyzeStatement(handlerCtx *handler.HandlerContext return p.analyzeInsert(handlerCtx, stmt) case *sqlparser.OtherRead, *sqlparser.OtherAdmin: return iqlerror.GetStatementNotSupportedError("OTHER") + case *sqlparser.Registry: + return p.analyzeRegistry(handlerCtx, stmt) case *sqlparser.Rollback: return iqlerror.GetStatementNotSupportedError("TRANSACTION: ROLLBACK") case *sqlparser.Savepoint: @@ -1257,6 +1259,11 @@ func (p *primitiveGenerator) analyzeSleep(handlerCtx *handler.HandlerContext, no return err } +func (p *primitiveGenerator) analyzeRegistry(handlerCtx *handler.HandlerContext, node *sqlparser.Registry) error { + var err error + return err +} + func (p *primitiveGenerator) analyzeShow(handlerCtx *handler.HandlerContext, node *sqlparser.Show) error { var err error p.parseComments(node.Comments) diff --git a/internal/stackql/util/plan_utility.go b/internal/stackql/util/plan_utility.go index 6b9ec56f..4960c361 100644 --- a/internal/stackql/util/plan_utility.go +++ b/internal/stackql/util/plan_utility.go @@ -290,6 +290,21 @@ func PrepareResultSet(payload dto.PrepareResultSetDTO) dto.ExecutorOutput { ) } +func EmptyProtectResultSet(rv dto.ExecutorOutput, columns []string) dto.ExecutorOutput { + if len(rv.GetRawResult()) == 0 { + resVal := &sqltypes.Result{ + Fields: make([]*querypb.Field, len(columns)), + } + for f := range resVal.Fields { + resVal.Fields[f] = &querypb.Field{ + Name: columns[f], + } + } + rv.GetSQLResult = func() *sqltypes.Result { return resVal } + } + return rv +} + func DescribeRowSort(rows map[string]map[string]interface{}) []string { return describeRowSortArr } diff --git a/test/functional/stackql_from_cmd_line.robot b/test/functional/stackql_from_cmd_line.robot index 7bb37cf4..600ade18 100644 --- a/test/functional/stackql_from_cmd_line.robot +++ b/test/functional/stackql_from_cmd_line.robot @@ -11,15 +11,12 @@ Positive Control Get Providers Should StackQL Exec Contain ${SHOW_PROVIDERS_STR} okta - Should StackQL Embedded Exec Contain ${SHOW_PROVIDERS_STR} okta Get Okta Services Should StackQL Exec Contain ${SHOW_OKTA_SERVICES_FILTERED_STR} Application${SPACE}API - Should StackQL Embedded Exec Contain ${SHOW_OKTA_SERVICES_FILTERED_STR} Application${SPACE}API Get Okta Application Resources Should StackQL Exec Contain ${SHOW_OKTA_APPLICATION_RESOURCES_FILTERED_STR} grants groups - Should StackQL Embedded Exec Contain ${SHOW_OKTA_APPLICATION_RESOURCES_FILTERED_STR} grants groups *** Keywords *** Run StackQL Exec Command @@ -54,18 +51,9 @@ Should StackQL Exec Equal ${result} = Run StackQL Exec Command ${_EXEC_CMD_STR} @{varargs} Should Be Equal ${result.stdout} ${_EXEC_CMD_EXPECTED_OUTPUT} -Should StackQL Embedded Exec Equal - [Arguments] ${_EXEC_CMD_STR} ${_EXEC_CMD_EXPECTED_OUTPUT} @{varargs} - ${result} = Run StackQL Embedded Exec Command ${_EXEC_CMD_STR} @{varargs} - Should Be Equal ${result.stdout} ${_EXEC_CMD_EXPECTED_OUTPUT} - Should StackQL Exec Contain [Arguments] ${_EXEC_CMD_STR} ${_EXEC_CMD_EXPECTED_OUTPUT} @{varargs} ${result} = Run StackQL Exec Command ${_EXEC_CMD_STR} Should contain ${result.stdout} ${_EXEC_CMD_EXPECTED_OUTPUT} @{varargs} -Should StackQL Embedded Exec Contain - [Arguments] ${_EXEC_CMD_STR} ${_EXEC_CMD_EXPECTED_OUTPUT} @{varargs} - ${result} = Run StackQL Embedded Exec Command ${_EXEC_CMD_STR} - Should contain ${result.stdout} ${_EXEC_CMD_EXPECTED_OUTPUT} @{varargs}