github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/dfunctions/hashof.go (about) 1 // Copyright 2020 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dfunctions 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "strings" 22 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/dolthub/go-mysql-server/sql/expression" 25 26 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 27 "github.com/dolthub/dolt/go/libraries/doltcore/ref" 28 "github.com/dolthub/dolt/go/libraries/doltcore/sqle" 29 ) 30 31 const HashOfFuncName = "hashof" 32 33 type HashOf struct { 34 expression.UnaryExpression 35 } 36 37 // NewHashOf creates a new HashOf expression. 38 func NewHashOf(ctx *sql.Context, e sql.Expression) sql.Expression { 39 return &HashOf{expression.UnaryExpression{Child: e}} 40 } 41 42 // Eval implements the Expression interface. 43 func (t *HashOf) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 44 val, err := t.Child.Eval(ctx, row) 45 46 if err != nil { 47 return nil, err 48 } 49 50 if val == nil { 51 return nil, nil 52 } 53 54 paramStr, ok := val.(string) 55 56 if !ok { 57 return nil, errors.New("branch name is not a string") 58 } 59 60 name, as, err := doltdb.SplitAncestorSpec(paramStr) 61 if err != nil { 62 return nil, err 63 } 64 65 dbName := ctx.GetCurrentDatabase() 66 ddb, ok := sqle.DSessFromSess(ctx.Session).GetDoltDB(dbName) 67 if !ok { 68 return nil, sql.ErrDatabaseNotFound.New(dbName) 69 } 70 71 var cm *doltdb.Commit 72 if strings.ToUpper(name) == "HEAD" { 73 sess := sqle.DSessFromSess(ctx.Session) 74 75 cm, _, err = sess.GetHeadCommit(ctx, dbName) 76 if err != nil { 77 return nil, err 78 } 79 } else { 80 branchRef, err := getBranchInsensitive(ctx, name, ddb) 81 if err != nil { 82 return nil, err 83 } 84 85 cm, err = ddb.ResolveCommitRef(ctx, branchRef) 86 if err != nil { 87 return nil, err 88 } 89 } 90 91 cm, err = cm.GetAncestor(ctx, as) 92 if err != nil { 93 return nil, err 94 } 95 96 h, err := cm.HashOf() 97 if err != nil { 98 return nil, err 99 } 100 101 return h.String(), nil 102 } 103 104 func getBranchInsensitive(ctx context.Context, branchName string, ddb *doltdb.DoltDB) (br ref.DoltRef, err error) { 105 branchRefs, err := ddb.GetBranches(ctx) 106 107 if err != nil { 108 return br, err 109 } 110 111 for _, branchRef := range branchRefs { 112 if strings.ToLower(branchRef.GetPath()) == strings.ToLower(branchName) { 113 return branchRef, nil 114 } 115 } 116 117 return br, doltdb.ErrBranchNotFound 118 } 119 120 // String implements the Stringer interface. 121 func (t *HashOf) String() string { 122 return fmt.Sprintf("HASHOF(%s)", t.Child.String()) 123 } 124 125 // IsNullable implements the Expression interface. 126 func (t *HashOf) IsNullable() bool { 127 return t.Child.IsNullable() 128 } 129 130 // WithChildren implements the Expression interface. 131 func (t *HashOf) WithChildren(ctx *sql.Context, children ...sql.Expression) (sql.Expression, error) { 132 if len(children) != 1 { 133 return nil, sql.ErrInvalidChildrenNumber.New(t, len(children), 1) 134 } 135 return NewHashOf(ctx, children[0]), nil 136 } 137 138 // Type implements the Expression interface. 139 func (t *HashOf) Type() sql.Type { 140 return sql.Text 141 }