implemented dolt_hashof_db function which returns the root hash of a database

This commit is contained in:
Brian Hendriks
2024-06-07 12:00:44 -07:00
parent 69d9d977ea
commit 9f7c29ad93
3 changed files with 145 additions and 0 deletions
@@ -0,0 +1,88 @@
// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dfunctions
import (
"fmt"
"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/go-mysql-server/sql/types"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
)
const HashOfDatabaseFuncName = "dolt_hashof_db"
type HashOfDatabase struct{}
// NewHashOfDatabase creates a new HashOfDatabase expression.
func NewHashOfDatabase() sql.Expression {
return &HashOfDatabase{}
}
// Children implements the Expression interface.
func (t *HashOfDatabase) Children() []sql.Expression {
return nil
}
// Eval implements the Expression interface.
func (t *HashOfDatabase) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
dbName := ctx.GetCurrentDatabase()
ds := dsess.DSessFromSess(ctx.Session)
roots, ok := ds.GetRoots(ctx, dbName)
if !ok {
return nil, sql.ErrDatabaseNotFound.New(dbName)
}
h, err := roots.Working.HashOf()
if err != nil {
return nil, fmt.Errorf("error getting hash of the database '%s': %w", dbName, err)
}
return h.String(), nil
}
// String implements the Stringer interface.
func (t *HashOfDatabase) String() string {
return fmt.Sprintf("%s()", HashOfDatabaseFuncName)
}
// Description implements the FunctionExpression interface
func (t *HashOfDatabase) Description() string {
return "returns a hash of the contents of the current database, typically used for detecting if a database has changed"
}
// IsNullable implements the Expression interface.
func (t *HashOfDatabase) IsNullable() bool {
return false
}
// Resolved implements the Expression interface.
func (*HashOfDatabase) Resolved() bool {
return true
}
// WithChildren implements the Expression interface.
func (t *HashOfDatabase) WithChildren(children ...sql.Expression) (sql.Expression, error) {
if len(children) != 0 {
return nil, sql.ErrInvalidChildrenNumber.New(t, len(children), 1)
}
return NewHashOfDatabase(), nil
}
// Type implements the Expression interface.
func (t *HashOfDatabase) Type() sql.Type {
return types.Text
}
@@ -25,6 +25,7 @@ var DoltFunctions = []sql.Function{
sql.Function2{Name: DoltMergeBaseFuncName, Fn: NewMergeBase},
sql.Function2{Name: HasAncestorFuncName, Fn: NewHasAncestor},
sql.Function1{Name: HashOfTableFuncName, Fn: NewHashOfTable},
sql.Function0{Name: HashOfDatabaseFuncName, Fn: NewHashOfDatabase},
}
// DolthubApiFunctions are the DoltFunctions that get exposed to Dolthub Api.
@@ -735,6 +735,62 @@ var DoltScripts = []queries.ScriptTest{
},
},
},
{
Name: "dolt_hashof_db tests",
SetUpScript: []string{
"CREATE TABLE t1 (pk int primary key);",
"CREATE TABLE t2 (pk int primary key);",
"CREATE TABLE t3 (pk int primary key);",
},
Assertions: []queries.ScriptTestAssertion{
{
Query: "SHOW TABLES;",
Expected: []sql.Row{
{"t1"},
{"t2"},
{"t3"},
},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"8s7m7m4djgi775km2e9iegrcjaqibq3a"}},
},
{
Query: "INSERT INTO t1 VALUES (1);",
Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"vm5tdcu609k8ocjpvf2mttqnog68jf8g"}},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"vm5tdcu609k8ocjpvf2mttqnog68jf8g"}},
},
{
Query: "INSERT INTO t2 VALUES (1);",
Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"ceip16r8mongns5t454huj3pj0hgtgeo"}},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"ceip16r8mongns5t454huj3pj0hgtgeo"}},
},
{
Query: "create procedure proc1() SELECT * FROM t3;",
Expected: []sql.Row{{types.OkResult{}}},
},
{
Query: "SELECT dolt_hashof_db();",
Expected: []sql.Row{{"nes9a42uqmoin7i56lmdg4qo7ad79tk5"}},
},
},
},
{
// https://github.com/dolthub/dolt/issues/7384
Name: "multiple unresolved foreign keys can be created on the same table",