mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-24 03:09:22 -06:00
Many changes
This commit is contained in:
committed by
Nathan Gabrielson
parent
24c6c33bc6
commit
bc75d263c8
@@ -15,9 +15,12 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/dolthub/dolt/go/store/val"
|
||||
"github.com/gocraft/dbr/v2"
|
||||
"github.com/gocraft/dbr/v2/dialect"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -157,7 +160,7 @@ func (cmd SqlCmd) EventType() eventsapi.ClientEventType {
|
||||
// that parameter is not provided there is additional error handling within this command to make sure that this was in
|
||||
// fact run from within a dolt data repository directory.
|
||||
func (cmd SqlCmd) RequiresRepo() bool {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
// Exec executes the command
|
||||
@@ -220,13 +223,13 @@ func (cmd SqlCmd) Exec(ctx context.Context, commandStr string, args []string, dE
|
||||
|
||||
if query, queryOK := apr.GetValue(QueryFlag); queryOK {
|
||||
if apr.Contains(saveFlag) {
|
||||
return execSaveQuery(sqlCtx, dEnv, queryist, apr, query, format, usage)
|
||||
return SaveQuery(sqlCtx, queryist, apr, query, format, usage)
|
||||
}
|
||||
return queryMode(sqlCtx, queryist, apr, query, format, usage)
|
||||
} else if savedQueryName, exOk := apr.GetValue(executeFlag); exOk {
|
||||
return executeSavedQuery(sqlCtx, queryist, dEnv, savedQueryName, format, usage)
|
||||
return executeSavedQuery(sqlCtx, queryist, savedQueryName, format, usage)
|
||||
} else if apr.Contains(listSavedFlag) {
|
||||
return listSavedQueries(sqlCtx, queryist, dEnv, format, usage)
|
||||
return listSavedQueries(sqlCtx, queryist, format, usage)
|
||||
} else {
|
||||
// Run in either batch mode for piped input, or shell mode for interactive
|
||||
isTty := false
|
||||
@@ -336,33 +339,16 @@ func (cmd SqlCmd) handleLegacyArguments(ap *argparser.ArgParser, commandStr stri
|
||||
|
||||
}
|
||||
|
||||
func listSavedQueries(ctx *sql.Context, qryist cli.Queryist, dEnv *env.DoltEnv, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
if !dEnv.Valid() {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.BuildDError("error: --%s must be used in a dolt database directory.", listSavedFlag).Build(), usage)
|
||||
}
|
||||
|
||||
workingRoot, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
|
||||
hasQC, err := workingRoot.HasTable(ctx, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName})
|
||||
|
||||
if err != nil {
|
||||
verr := errhand.BuildDError("error: Failed to read from repository.").AddCause(err).Build()
|
||||
return sqlHandleVErrAndExitCode(qryist, verr, usage)
|
||||
}
|
||||
|
||||
if !hasQC {
|
||||
return 0
|
||||
}
|
||||
|
||||
func listSavedQueries(ctx *sql.Context, qryist cli.Queryist, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
query := "SELECT * FROM " + doltdb.DoltQueryCatalogTableName
|
||||
return sqlHandleVErrAndExitCode(qryist, execSingleQuery(ctx, qryist, query, format), usage)
|
||||
}
|
||||
|
||||
func executeSavedQuery(ctx *sql.Context, qryist cli.Queryist, _ *env.DoltEnv, savedQueryName string, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
searchQuery := fmt.Sprintf("SELECT query FROM dolt_query_catalog where name = '%s'", savedQueryName)
|
||||
func executeSavedQuery(ctx *sql.Context, qryist cli.Queryist, savedQueryName string, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("SELECT query FROM dolt_query_catalog where name = ?")
|
||||
searchQuery, err := dbr.InterpolateForDialect(buffer.String(), []interface{}{savedQueryName}, dialect.MySQL)
|
||||
|
||||
rows, err := GetRowsForSql(qryist, ctx, searchQuery)
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
@@ -371,12 +357,19 @@ func executeSavedQuery(ctx *sql.Context, qryist cli.Queryist, _ *env.DoltEnv, sa
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
|
||||
query, err := rows[0][0].(*val.TextStorage).Unwrap(ctx)
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
var query string
|
||||
if ts, ok := rows[0][0].(*val.TextStorage); ok {
|
||||
query, err = ts.Unwrap(ctx)
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
} else {
|
||||
if s, ok := rows[0][0].(string); ok {
|
||||
query = s
|
||||
}
|
||||
}
|
||||
|
||||
cli.PrintErrf("Executing saved query: '%s': \n%s\n", savedQueryName, query)
|
||||
cli.PrintErrf("Executing saved query '%s': \n%s\n", savedQueryName, query)
|
||||
return sqlHandleVErrAndExitCode(qryist, execSingleQuery(ctx, qryist, query, format), usage)
|
||||
}
|
||||
|
||||
@@ -400,7 +393,7 @@ func queryMode(
|
||||
return 0
|
||||
}
|
||||
|
||||
func execSaveQuery(ctx *sql.Context, _ *env.DoltEnv, qryist cli.Queryist, apr *argparser.ArgParseResults, query string, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
func SaveQuery(ctx *sql.Context, qryist cli.Queryist, apr *argparser.ArgParseResults, query string, format engine.PrintResultFormat, usage cli.UsagePrinter) int {
|
||||
saveName := apr.GetValueOrDefault(saveFlag, "")
|
||||
|
||||
verr := execSingleQuery(ctx, qryist, query, format)
|
||||
@@ -409,17 +402,27 @@ func execSaveQuery(ctx *sql.Context, _ *env.DoltEnv, qryist cli.Queryist, apr *a
|
||||
}
|
||||
|
||||
order := int32(1)
|
||||
var ok bool
|
||||
rows, err := GetRowsForSql(qryist, ctx, "SELECT MAX(display_order) FROM dolt_query_catalog")
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
if len(rows) > 0 && rows[0][0] != nil {
|
||||
order = rows[0][0].(int32) + 1
|
||||
if order, ok = rows[0][0].(int32); !ok {
|
||||
err = fmt.Errorf("could not get display_order from dolt_query_catalog")
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
order++
|
||||
}
|
||||
|
||||
saveMessage := apr.GetValueOrDefault(messageFlag, "")
|
||||
insertQuery := fmt.Sprintf("INSERT INTO dolt_query_catalog VALUES ('%s', %d, '%s', '%s', '%s') "+
|
||||
"ON DUPLICATE KEY UPDATE query = '%s', description = '%s'", saveName, order, saveName, query, saveMessage, query, saveMessage)
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("INSERT INTO dolt_query_catalog VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE query = ?, description = ?")
|
||||
params := []interface{}{saveName, order, saveName, query, saveMessage, query, saveMessage}
|
||||
insertQuery, err := dbr.InterpolateForDialect(buffer.String(), params, dialect.MySQL)
|
||||
if err != nil {
|
||||
return sqlHandleVErrAndExitCode(qryist, errhand.VerboseErrorFromError(err), usage)
|
||||
}
|
||||
|
||||
_, err = GetRowsForSql(qryist, ctx, insertQuery)
|
||||
|
||||
|
||||
@@ -92,13 +92,13 @@ func NewEmptyQueryCatalogTable(_ *sql.Context) sql.Table {
|
||||
return &QueryCatalogTable{}
|
||||
}
|
||||
|
||||
func (qt *QueryCatalogTable) Replacer(ctx *sql.Context) sql.RowReplacer {
|
||||
func (qt *QueryCatalogTable) Replacer(_ *sql.Context) sql.RowReplacer {
|
||||
return newQueryCatalogWriter(qt)
|
||||
}
|
||||
|
||||
// Updater returns a RowUpdater for this table. The RowUpdater will have Update called once for each row to be
|
||||
// updated, followed by a call to Close() when all rows have been processed.
|
||||
func (qt *QueryCatalogTable) Updater(ctx *sql.Context) sql.RowUpdater {
|
||||
func (qt *QueryCatalogTable) Updater(_ *sql.Context) sql.RowUpdater {
|
||||
return newQueryCatalogWriter(qt)
|
||||
}
|
||||
|
||||
@@ -116,12 +116,12 @@ func (qt *QueryCatalogTable) Deleter(*sql.Context) sql.RowDeleter {
|
||||
|
||||
// IndexedAccess implements IndexAddressableTable, but QueryCatalogTables has no indexes.
|
||||
// Thus, this should never be called.
|
||||
func (qt *QueryCatalogTable) IndexedAccess(ctx *sql.Context, lookup sql.IndexLookup) sql.IndexedTable {
|
||||
func (qt *QueryCatalogTable) IndexedAccess(_ *sql.Context, _ sql.IndexLookup) sql.IndexedTable {
|
||||
panic("Unreachable")
|
||||
}
|
||||
|
||||
// GetIndexes implements IndexAddressableTable, but QueryCatalogTables has no indexes.
|
||||
func (qt *QueryCatalogTable) GetIndexes(ctx *sql.Context) ([]sql.Index, error) {
|
||||
func (qt *QueryCatalogTable) GetIndexes(_ *sql.Context) ([]sql.Index, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -284,383 +284,3 @@ func (qw *queryCatalogWriter) Close(ctx *sql.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*var queryCatalogCols = schema.NewColCollection(
|
||||
// QueryCatalogIdCol is the name of the primary key column of the query catalog table
|
||||
schema.NewColumn(doltdb.QueryCatalogIdCol, schema.QueryCatalogIdTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
// QueryCatalogOrderCol is the column containing the order of the queries in the catalog
|
||||
schema.NewColumn(doltdb.QueryCatalogOrderCol, schema.QueryCatalogOrderTag, types.UintKind, false, schema.NotNullConstraint{}),
|
||||
// QueryCatalogNameCol is the name of the column containing the name of a query in the catalog
|
||||
// TODO: parser won't handle a reserved word here, but it should. Only an issue for create table statements.
|
||||
schema.NewColumn(doltdb.QueryCatalogNameCol, schema.QueryCatalogNameTag, types.StringKind, false),
|
||||
// QueryCatalogQueryCol is the name of the column containing the query of a catalog entry
|
||||
schema.NewColumn(doltdb.QueryCatalogQueryCol, schema.QueryCatalogQueryTag, types.StringKind, false),
|
||||
// QueryCatalogDescriptionCol is the name of the column containing the description of a query in the catalog
|
||||
schema.NewColumn(doltdb.QueryCatalogDescriptionCol, schema.QueryCatalogDescriptionTag, types.StringKind, false),
|
||||
)
|
||||
|
||||
var ErrQueryNotFound = errors.NewKind("Query '%s' not found")
|
||||
|
||||
type SavedQuery struct {
|
||||
ID string
|
||||
Name string
|
||||
Query string
|
||||
Description string
|
||||
Order uint64
|
||||
}
|
||||
|
||||
func savedQueryFromKVProlly(id string, value val.Tuple) (SavedQuery, error) {
|
||||
orderVal, ok := catalogVd.GetUint64(0, value)
|
||||
if !ok {
|
||||
orderVal = 0
|
||||
}
|
||||
nameVal, ok := catalogVd.GetString(1, value)
|
||||
if !ok {
|
||||
nameVal = ""
|
||||
}
|
||||
queryVal, ok := catalogVd.GetString(2, value)
|
||||
if !ok {
|
||||
nameVal = ""
|
||||
}
|
||||
descVal, ok := catalogVd.GetString(3, value)
|
||||
if !ok {
|
||||
descVal = ""
|
||||
}
|
||||
|
||||
return SavedQuery{
|
||||
ID: id,
|
||||
Name: nameVal,
|
||||
Query: queryVal,
|
||||
Description: descVal,
|
||||
Order: orderVal,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func savedQueryFromKVNoms(id string, valTuple types.Tuple) (SavedQuery, error) {
|
||||
tv, err := row.ParseTaggedValues(valTuple)
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
|
||||
nameVal := tv.GetWithDefault(schema.QueryCatalogNameTag, types.String(""))
|
||||
queryVal := tv.GetWithDefault(schema.QueryCatalogQueryTag, types.String(""))
|
||||
descVal := tv.GetWithDefault(schema.QueryCatalogDescriptionTag, types.String(""))
|
||||
orderVal := tv.GetWithDefault(schema.QueryCatalogOrderTag, types.Uint(0))
|
||||
|
||||
return SavedQuery{
|
||||
ID: id,
|
||||
Name: string(nameVal.(types.String)),
|
||||
Query: string(queryVal.(types.String)),
|
||||
Description: string(descVal.(types.String)),
|
||||
Order: uint64(orderVal.(types.Uint)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (sq SavedQuery) asRow(nbf *types.NomsBinFormat) (row.Row, error) {
|
||||
taggedVals := make(row.TaggedValues)
|
||||
taggedVals[schema.QueryCatalogIdTag] = types.String(sq.ID)
|
||||
taggedVals[schema.QueryCatalogOrderTag] = types.Uint(sq.Order)
|
||||
taggedVals[schema.QueryCatalogNameTag] = types.String(sq.Name)
|
||||
taggedVals[schema.QueryCatalogQueryTag] = types.String(sq.Query)
|
||||
taggedVals[schema.QueryCatalogDescriptionTag] = types.String(sq.Description)
|
||||
|
||||
return row.New(nbf, DoltQueryCatalogSchema, taggedVals)
|
||||
}
|
||||
|
||||
var DoltQueryCatalogSchema = schema.MustSchemaFromCols(queryCatalogCols)
|
||||
|
||||
// system tables do not contain addressable columns, and do not require nodestore access.
|
||||
var catalogKd = DoltQueryCatalogSchema.GetKeyDescriptor(nil)
|
||||
var catalogVd = DoltQueryCatalogSchema.GetValueDescriptor(nil)
|
||||
|
||||
// Creates the query catalog table if it doesn't exist.
|
||||
func createQueryCatalogIfNotExists(ctx context.Context, root doltdb.RootValue) (doltdb.RootValue, error) {
|
||||
_, ok, err := root.GetTable(ctx, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return doltdb.CreateEmptyTable(ctx, root, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName}, DoltQueryCatalogSchema)
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// NewQueryCatalogEntryWithRandID saves a new entry in the query catalog table and returns the new root value. An ID will be
|
||||
// chosen automatically.
|
||||
func NewQueryCatalogEntryWithRandID(ctx context.Context, root doltdb.RootValue, name, query, description string) (SavedQuery, doltdb.RootValue, error) {
|
||||
uid, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
// Use the last 12 hex digits of the uuid for the ID.
|
||||
uidStr := uid.String()
|
||||
id := uidStr[len(uidStr)-12:]
|
||||
|
||||
return newQueryCatalogEntry(ctx, root, id, name, query, description)
|
||||
}
|
||||
|
||||
// NewQueryCatalogEntryWithNameAsID saves an entry in the query catalog table and returns the new root value. If an
|
||||
// entry with the given name is already present, it will be overwritten.
|
||||
func NewQueryCatalogEntryWithNameAsID(ctx context.Context, root doltdb.RootValue, name, query, description string) (SavedQuery, doltdb.RootValue, error) {
|
||||
return newQueryCatalogEntry(ctx, root, name, name, query, description)
|
||||
}
|
||||
|
||||
func newQueryCatalogEntry(ctx context.Context, root doltdb.RootValue, id, name, query, description string) (SavedQuery, doltdb.RootValue, error) {
|
||||
root, err := createQueryCatalogIfNotExists(ctx, root)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName})
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
var sq SavedQuery
|
||||
var newTable *doltdb.Table
|
||||
if types.IsFormat_DOLT(tbl.Format()) {
|
||||
sq, newTable, err = newQueryCatalogEntryProlly(ctx, tbl, id, name, query, description)
|
||||
} else {
|
||||
sq, newTable, err = newQueryCatalogEntryNoms(ctx, tbl, id, name, query, description)
|
||||
}
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName}, newTable)
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
return sq, root, err
|
||||
}
|
||||
|
||||
func newQueryCatalogEntryNoms(ctx context.Context, tbl *doltdb.Table, id, name, query, description string) (SavedQuery, *doltdb.Table, error) {
|
||||
data, err := tbl.GetNomsRowData(ctx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
order := getMaxQueryOrderNoms(data, ctx) + 1
|
||||
existingSQ, err := retrieveFromQueryCatalogNoms(ctx, tbl, id)
|
||||
|
||||
if err != nil {
|
||||
if !ErrQueryNotFound.Is(err) {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
} else {
|
||||
order = existingSQ.Order
|
||||
}
|
||||
|
||||
sq := SavedQuery{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Query: query,
|
||||
Description: description,
|
||||
Order: order,
|
||||
}
|
||||
|
||||
r, err := sq.asRow(tbl.Format())
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
me := data.Edit()
|
||||
me.Set(r.NomsMapKey(DoltQueryCatalogSchema), r.NomsMapValue(DoltQueryCatalogSchema))
|
||||
|
||||
updatedTable, err := me.Map(ctx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
newTable, err := tbl.UpdateNomsRows(ctx, updatedTable)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
return sq, newTable, nil
|
||||
}
|
||||
|
||||
func newQueryCatalogEntryProlly(ctx context.Context, tbl *doltdb.Table, id, name, query, description string) (SavedQuery, *doltdb.Table, error) {
|
||||
idx, err := tbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
m, err := durable.ProllyMapFromIndex(idx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
existingSQ, err := retrieveFromQueryCatalogProlly(ctx, tbl, id)
|
||||
if err != nil && !ErrQueryNotFound.Is(err) {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
var order uint64
|
||||
if ErrQueryNotFound.Is(err) {
|
||||
order, err = getMaxQueryOrderProlly(ctx, m)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
order++
|
||||
} else {
|
||||
order = existingSQ.Order
|
||||
}
|
||||
|
||||
kb := val.NewTupleBuilder(catalogKd, m.NodeStore())
|
||||
vb := val.NewTupleBuilder(catalogVd, m.NodeStore())
|
||||
kb.PutString(0, id)
|
||||
k, err := kb.Build(m.Pool())
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
vb.PutUint64(0, order)
|
||||
vb.PutString(1, name)
|
||||
vb.PutString(2, query)
|
||||
vb.PutString(3, description)
|
||||
v, err := vb.Build(m.Pool())
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
mut := m.Mutate()
|
||||
err = mut.Put(ctx, k, v)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
m, err = mut.Map(ctx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
idx = durable.IndexFromProllyMap(m)
|
||||
|
||||
tbl, err = tbl.UpdateRows(ctx, idx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, nil, err
|
||||
}
|
||||
|
||||
return SavedQuery{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Query: query,
|
||||
Description: description,
|
||||
Order: order,
|
||||
}, tbl, nil
|
||||
}
|
||||
|
||||
func RetrieveFromQueryCatalog(ctx context.Context, root doltdb.RootValue, id string) (SavedQuery, error) {
|
||||
tbl, ok, err := root.GetTable(ctx, doltdb.TableName{Name: doltdb.DoltQueryCatalogTableName})
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
} else if !ok {
|
||||
return SavedQuery{}, doltdb.ErrTableNotFound
|
||||
}
|
||||
|
||||
if types.IsFormat_DOLT(tbl.Format()) {
|
||||
return retrieveFromQueryCatalogProlly(ctx, tbl, id)
|
||||
}
|
||||
|
||||
return retrieveFromQueryCatalogNoms(ctx, tbl, id)
|
||||
}
|
||||
|
||||
func retrieveFromQueryCatalogProlly(ctx context.Context, tbl *doltdb.Table, id string) (SavedQuery, error) {
|
||||
idx, err := tbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
|
||||
m, err := durable.ProllyMapFromIndex(idx)
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
|
||||
kb := val.NewTupleBuilder(catalogKd, m.NodeStore())
|
||||
kb.PutString(0, id)
|
||||
k, err := kb.Build(m.Pool())
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
var value val.Tuple
|
||||
_ = m.Get(ctx, k, func(_, v val.Tuple) error {
|
||||
value = v
|
||||
return nil
|
||||
})
|
||||
if value == nil {
|
||||
return SavedQuery{}, ErrQueryNotFound.New(id)
|
||||
}
|
||||
|
||||
return savedQueryFromKVProlly(id, value)
|
||||
}
|
||||
|
||||
func retrieveFromQueryCatalogNoms(ctx context.Context, tbl *doltdb.Table, id string) (SavedQuery, error) {
|
||||
m, err := tbl.GetNomsRowData(ctx)
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
|
||||
k, err := types.NewTuple(tbl.Format(), types.Uint(schema.QueryCatalogIdTag), types.String(id))
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
}
|
||||
|
||||
val, ok, err := m.MaybeGet(ctx, k)
|
||||
|
||||
if err != nil {
|
||||
return SavedQuery{}, err
|
||||
} else if !ok {
|
||||
return SavedQuery{}, ErrQueryNotFound.New(id)
|
||||
}
|
||||
|
||||
return savedQueryFromKVNoms(id, val.(types.Tuple))
|
||||
}
|
||||
|
||||
// Returns the largest order entry in the catalog
|
||||
func getMaxQueryOrderNoms(data types.Map, ctx context.Context) uint64 {
|
||||
maxOrder := uint64(0)
|
||||
data.IterAll(ctx, func(key, value types.Value) error {
|
||||
r, _ := row.FromNoms(DoltQueryCatalogSchema, key.(types.Tuple), value.(types.Tuple))
|
||||
orderVal, ok := r.GetColVal(schema.QueryCatalogOrderTag)
|
||||
if ok {
|
||||
order := uint64(orderVal.(types.Uint))
|
||||
if order > maxOrder {
|
||||
maxOrder = order
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return maxOrder
|
||||
}
|
||||
|
||||
func getMaxQueryOrderProlly(ctx context.Context, data prolly.Map) (uint64, error) {
|
||||
itr, err := data.IterAll(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
maxOrder := uint64(0)
|
||||
for {
|
||||
_, v, err := itr.Next(ctx)
|
||||
if err != nil && err != io.EOF {
|
||||
return 0, err
|
||||
}
|
||||
if err == io.EOF {
|
||||
return maxOrder, nil
|
||||
}
|
||||
order, ok := catalogVd.GetUint64(0, v)
|
||||
if ok {
|
||||
if order > maxOrder {
|
||||
maxOrder = order
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -60,32 +60,28 @@ teardown() {
|
||||
[[ "$output" =~ "my message" ]] || false
|
||||
}
|
||||
|
||||
@test "query-catalog: empty directory" {
|
||||
mkdir empty && cd empty
|
||||
|
||||
run dolt sql -q "show databases" --save name
|
||||
[ "$status" -ne 0 ]
|
||||
[[ ! "$output" =~ panic ]] || false
|
||||
[[ "$output" =~ "The current directory is not a valid dolt repository." ]] || false
|
||||
|
||||
run dolt sql --list-saved
|
||||
[ "$status" -ne 0 ]
|
||||
[[ ! "$output" =~ panic ]] || false
|
||||
[[ "$output" =~ "The current directory is not a valid dolt repository." ]] || false
|
||||
|
||||
run dolt sql --execute name
|
||||
[ "$status" -ne 0 ]
|
||||
[[ ! "$output" =~ panic ]] || false
|
||||
[[ "$output" =~ "The current directory is not a valid dolt repository." ]] || false
|
||||
}
|
||||
|
||||
@test "query-catalog: executed saved" {
|
||||
@test "can list saved queries" {
|
||||
Q1="select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1"
|
||||
Q2="select pk from one_pk order by pk"
|
||||
dolt sql -q "$Q1" -s name1
|
||||
dolt sql -q "$Q2" -s name2
|
||||
|
||||
# save Q1 and verify output
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
id,display_order,name,query,description
|
||||
name1,1,name1,"select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1",""
|
||||
name2,2,name2,select pk from one_pk order by pk,""
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql --list-saved -r csv
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
}
|
||||
|
||||
@test "can execute saved queries" {
|
||||
Q1="select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1"
|
||||
dolt sql -q "$Q1" -s name1
|
||||
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
pk,pk1,pk2
|
||||
0,0,0
|
||||
@@ -95,67 +91,38 @@ pk,pk1,pk2
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql -r csv -x name1
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
|
||||
# save Q2 and verify output
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
pk
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql -r csv -x name2
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
|
||||
# execute list-saved and verify output. I have no idea why the
|
||||
# query on the second line isn't quoted, assuming it's a bash
|
||||
# interpretation thing. Has quotes when run by hand.
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
id,display_order,name,query,description
|
||||
name1,1,name1,"select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1",""
|
||||
name2,2,name2,select pk from one_pk order by pk,""
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql --list-saved -r csv
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
|
||||
# update an existing query, and verify query catalog is updated
|
||||
Q1_UPDATED="select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 and pk < 3 order by 1 desc"
|
||||
dolt sql -q "$Q1_UPDATED" -s name1
|
||||
|
||||
# execute list-saved and verify output
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
id,display_order,name,query,description
|
||||
name1,1,name1,"select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 and pk < 3 order by 1 desc",""
|
||||
name2,2,name2,select pk from one_pk order by pk,""
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql --list-saved -r csv
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
pk,pk1,pk2
|
||||
2,1,0
|
||||
1,0,1
|
||||
0,0,0
|
||||
EOF
|
||||
)
|
||||
|
||||
# Execute updated saved query and verify once output
|
||||
run dolt sql -r csv -x name1
|
||||
run dolt sql -x name1 -r csv
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
}
|
||||
|
||||
@test "can update saved query with --save" {
|
||||
Q1="select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1"
|
||||
Q2="select pk from one_pk order by pk"
|
||||
dolt sql -q "$Q1" -s name1
|
||||
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
id,display_order,name,query,description
|
||||
name1,1,name1,"select pk, pk1, pk2 from one_pk,two_pk where one_pk.c1=two_pk.c1 order by 1",""
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql --list-saved -r csv
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
|
||||
dolt sql -q "$Q2" -s name1
|
||||
|
||||
# execute list-saved and verify output. I have no idea why the
|
||||
# query isn't quoted, but I assume it's a bash
|
||||
# interpretation thing. Has quotes when run by hand.
|
||||
EXPECTED=$(cat <<'EOF'
|
||||
id,display_order,name,query,description
|
||||
name1,1,name1,select pk from one_pk order by pk,""
|
||||
EOF
|
||||
)
|
||||
|
||||
run dolt sql --list-saved -r csv
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "$EXPECTED" ]] || false
|
||||
}
|
||||
@@ -2197,3 +2197,28 @@ EOF
|
||||
run grep -F "Dropping persisted '__dolt_local_user__@localhost' because this account name is reserved for Dolt" server_log.txt
|
||||
[ $status -eq 0 ]
|
||||
}
|
||||
|
||||
@test "sql-server: can create and use saved queries with --host and --use-db" {
|
||||
cd repo1
|
||||
dolt sql -q "create table test (i int)"
|
||||
start_sql_server_with_args --host 0.0.0.0
|
||||
|
||||
cd ../repo2
|
||||
|
||||
run dolt --host 0.0.0.0 --no-tls --port $PORT --use-db repo1 sql -q "show tables" --save "show"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
|
||||
run dolt --host 0.0.0.0 --no-tls --port $PORT --use-db repo1 sql -l -r csv
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "show,1,show,show tables,\"\"" ]] || false
|
||||
|
||||
run dolt --host 0.0.0.0 --no-tls --port $PORT --use-db repo1 sql -x "show"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
|
||||
stop_sql_server 1 && sleep 0.5
|
||||
rm -rf $BATS_TMPDIR/sql-server-test$$
|
||||
}
|
||||
Reference in New Issue
Block a user