mirror of
https://github.com/dolthub/dolt.git
synced 2026-05-02 03:10:42 -05:00
Added database collation support
This commit is contained in:
@@ -144,7 +144,19 @@ func (rcv *RootValue) MutateForeignKeyAddr(j int, n byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
const RootValueNumFields = 3
|
||||
func (rcv *RootValue) Collation() Collation {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
|
||||
if o != 0 {
|
||||
return Collation(rcv._tab.GetUint16(o + rcv._tab.Pos))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *RootValue) MutateCollation(n Collation) bool {
|
||||
return rcv._tab.MutateUint16Slot(10, uint16(n))
|
||||
}
|
||||
|
||||
const RootValueNumFields = 4
|
||||
|
||||
func RootValueStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(RootValueNumFields)
|
||||
@@ -164,6 +176,9 @@ func RootValueAddForeignKeyAddr(builder *flatbuffers.Builder, foreignKeyAddr fla
|
||||
func RootValueStartForeignKeyAddrVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(1, numElems, 1)
|
||||
}
|
||||
func RootValueAddCollation(builder *flatbuffers.Builder, collation Collation) {
|
||||
builder.PrependUint16Slot(3, uint16(collation), 0)
|
||||
}
|
||||
func RootValueEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ require (
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371
|
||||
github.com/dolthub/mmap-go v1.0.4-0.20201107010347-f9f2a9588a66
|
||||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81
|
||||
github.com/dolthub/vitess v0.0.0-20221004165409-08281765376f
|
||||
github.com/dolthub/vitess v0.0.0-20221031111135-9aad77e7b39f
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||
@@ -57,7 +57,7 @@ require (
|
||||
require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible
|
||||
github.com/cenkalti/backoff/v4 v4.1.3
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221028185331-adb56cc0306f
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221031123010-4bbadb83eb59
|
||||
github.com/google/flatbuffers v2.0.6+incompatible
|
||||
github.com/kch42/buzhash v0.0.0-20160816060738-9bdec3dec7c6
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
|
||||
@@ -178,8 +178,8 @@ github.com/dolthub/flatbuffers v1.13.0-dh.1 h1:OWJdaPep22N52O/0xsUevxJ6Qfw1M2txC
|
||||
github.com/dolthub/flatbuffers v1.13.0-dh.1/go.mod h1:CorYGaDmXjHz1Z7i50PYXG1Ricn31GcA2wNOTFIQAKE=
|
||||
github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
|
||||
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221028185331-adb56cc0306f h1:VbCM4g61oG+0HR4u1ty3ABGWjnRbd1EkyO0dOsrfR5k=
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221028185331-adb56cc0306f/go.mod h1:9Q9FhWO82GrV4he13V2ZuDE0T/eDZbPVMOWLcZluOvg=
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221031123010-4bbadb83eb59 h1:y1dCWhx4atYcarv8oaJ5aaVXOw+J4K7DDgb61N25ra0=
|
||||
github.com/dolthub/go-mysql-server v0.12.1-0.20221031123010-4bbadb83eb59/go.mod h1:KtpU4Sf7J+SIat/nxoA733QTn3tdL34NtoGxEBFcTsA=
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371 h1:oyPHJlzumKta1vnOQqUnfdz+pk3EmnHS3Nd0cCT0I2g=
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371/go.mod h1:dhGBqcCEfK5kuFmeO5+WOx3hqc1k3M29c1oS/R7N4ms=
|
||||
github.com/dolthub/jsonpath v0.0.0-20210609232853-d49537a30474 h1:xTrR+l5l+1Lfq0NvhiEsctylXinUMFhhsqaEcl414p8=
|
||||
@@ -188,8 +188,8 @@ github.com/dolthub/mmap-go v1.0.4-0.20201107010347-f9f2a9588a66 h1:WRPDbpJWEnPxP
|
||||
github.com/dolthub/mmap-go v1.0.4-0.20201107010347-f9f2a9588a66/go.mod h1:N5ZIbMGuDUpTpOFQ7HcsN6WSIpTGQjHP+Mz27AfmAgk=
|
||||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9XGFa6q5Ap4Z/OhNkAMBaK5YeuEzwJt+NZdhiE=
|
||||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY=
|
||||
github.com/dolthub/vitess v0.0.0-20221004165409-08281765376f h1:yE3Cbhk4ylOK1jYqFHnman6fpKN2Cap080GG/UpAVBs=
|
||||
github.com/dolthub/vitess v0.0.0-20221004165409-08281765376f/go.mod h1:oVFIBdqMFEkt4Xz2fzFJBNtzKhDEjwdCF0dzde39iKs=
|
||||
github.com/dolthub/vitess v0.0.0-20221031111135-9aad77e7b39f h1:2sNrQiE4pcdgCNp09RTOsmNeepgN5rL+ep8NF8Faw9U=
|
||||
github.com/dolthub/vitess v0.0.0-20221031111135-9aad77e7b39f/go.mod h1:oVFIBdqMFEkt4Xz2fzFJBNtzKhDEjwdCF0dzde39iKs=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
|
||||
@@ -37,9 +37,10 @@ import (
|
||||
const (
|
||||
ddbRootStructName = "dolt_db_root"
|
||||
|
||||
tablesKey = "tables"
|
||||
foreignKeyKey = "foreign_key"
|
||||
featureVersKey = "feature_ver"
|
||||
tablesKey = "tables"
|
||||
foreignKeyKey = "foreign_key"
|
||||
featureVersKey = "feature_ver"
|
||||
rootCollationKey = "root_collation_key"
|
||||
|
||||
// deprecated
|
||||
superSchemasKey = "super_schemas"
|
||||
@@ -85,9 +86,11 @@ type rvStorage interface {
|
||||
|
||||
GetTablesMap(ctx context.Context, vr types.ValueReadWriter, ns tree.NodeStore) (tableMap, error)
|
||||
GetForeignKeys(ctx context.Context, vr types.ValueReader) (types.Value, bool, error)
|
||||
GetCollation(ctx context.Context) (schema.Collation, error)
|
||||
|
||||
SetForeignKeyMap(ctx context.Context, vrw types.ValueReadWriter, m types.Value) (rvStorage, error)
|
||||
SetFeatureVersion(v FeatureVersion) (rvStorage, error)
|
||||
SetCollation(ctx context.Context, collation schema.Collation) (rvStorage, error)
|
||||
|
||||
EditTablesMap(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, edits []tableEdit) (rvStorage, error)
|
||||
|
||||
@@ -156,6 +159,17 @@ func (r nomsRvStorage) GetForeignKeys(context.Context, types.ValueReader) (types
|
||||
return v.(types.Map), true, nil
|
||||
}
|
||||
|
||||
func (r nomsRvStorage) GetCollation(ctx context.Context) (schema.Collation, error) {
|
||||
v, found, err := r.valueSt.MaybeGet(rootCollationKey)
|
||||
if err != nil {
|
||||
return schema.Collation_Unspecified, err
|
||||
}
|
||||
if !found {
|
||||
return schema.Collation_Default, nil
|
||||
}
|
||||
return schema.Collation(v.(types.Uint)), nil
|
||||
}
|
||||
|
||||
func (r nomsRvStorage) EditTablesMap(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, edits []tableEdit) (rvStorage, error) {
|
||||
m, err := r.GetTablesMap(ctx, vrw, ns)
|
||||
if err != nil {
|
||||
@@ -218,6 +232,14 @@ func (r nomsRvStorage) SetFeatureVersion(v FeatureVersion) (rvStorage, error) {
|
||||
return nomsRvStorage{st}, nil
|
||||
}
|
||||
|
||||
func (r nomsRvStorage) SetCollation(ctx context.Context, collation schema.Collation) (rvStorage, error) {
|
||||
st, err := r.valueSt.Set(rootCollationKey, types.Uint(collation))
|
||||
if err != nil {
|
||||
return nomsRvStorage{}, err
|
||||
}
|
||||
return nomsRvStorage{st}, nil
|
||||
}
|
||||
|
||||
func (r nomsRvStorage) DebugString(ctx context.Context) string {
|
||||
var buf bytes.Buffer
|
||||
err := types.WriteEncodedValue(ctx, &buf, r.valueSt)
|
||||
@@ -314,6 +336,7 @@ func EmptyRootValue(ctx context.Context, vrw types.ValueReadWriter, ns tree.Node
|
||||
fkoff := builder.CreateByteVector(empty[:])
|
||||
serial.RootValueStart(builder)
|
||||
serial.RootValueAddFeatureVersion(builder, int64(DoltFeatureVersion))
|
||||
serial.RootValueAddCollation(builder, serial.Collationutf8mb4_0900_bin)
|
||||
serial.RootValueAddTables(builder, tablesoff)
|
||||
serial.RootValueAddForeignKeyAddr(builder, fkoff)
|
||||
bs := serial.FinishMessage(builder, serial.RootValueEnd(builder), []byte(serial.RootValueFileID))
|
||||
@@ -361,6 +384,18 @@ func (root *RootValue) setFeatureVersion(v FeatureVersion) (*RootValue, error) {
|
||||
return root.withStorage(newStorage), nil
|
||||
}
|
||||
|
||||
func (root *RootValue) GetCollation(ctx context.Context) (schema.Collation, error) {
|
||||
return root.st.GetCollation(ctx)
|
||||
}
|
||||
|
||||
func (root *RootValue) SetCollation(ctx context.Context, collation schema.Collation) (*RootValue, error) {
|
||||
newStorage, err := root.st.SetCollation(ctx, collation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return root.withStorage(newStorage), nil
|
||||
}
|
||||
|
||||
func (root *RootValue) HasTable(ctx context.Context, tName string) (bool, error) {
|
||||
tableMap, err := root.st.GetTablesMap(ctx, root.vrw, root.ns)
|
||||
if err != nil {
|
||||
@@ -1165,6 +1200,15 @@ func (r fbRvStorage) GetForeignKeys(ctx context.Context, vr types.ValueReader) (
|
||||
return v.(types.SerialMessage), true, nil
|
||||
}
|
||||
|
||||
func (r fbRvStorage) GetCollation(ctx context.Context) (schema.Collation, error) {
|
||||
collation := r.srv.Collation()
|
||||
// Pre-existing repositories will return invalid here
|
||||
if collation == serial.Collationinvalid {
|
||||
return schema.Collation_Default, nil
|
||||
}
|
||||
return schema.Collation(collation), nil
|
||||
}
|
||||
|
||||
func (r fbRvStorage) EditTablesMap(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, edits []tableEdit) (rvStorage, error) {
|
||||
builder := flatbuffers.NewBuilder(80)
|
||||
|
||||
@@ -1222,6 +1266,7 @@ func (r fbRvStorage) EditTablesMap(ctx context.Context, vrw types.ValueReadWrite
|
||||
fkoff := builder.CreateByteVector(r.srv.ForeignKeyAddrBytes())
|
||||
serial.RootValueStart(builder)
|
||||
serial.RootValueAddFeatureVersion(builder, r.srv.FeatureVersion())
|
||||
serial.RootValueAddCollation(builder, r.srv.Collation())
|
||||
serial.RootValueAddTables(builder, tablesoff)
|
||||
serial.RootValueAddForeignKeyAddr(builder, fkoff)
|
||||
|
||||
@@ -1257,6 +1302,12 @@ func (r fbRvStorage) SetFeatureVersion(v FeatureVersion) (rvStorage, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r fbRvStorage) SetCollation(ctx context.Context, collation schema.Collation) (rvStorage, error) {
|
||||
ret := r.clone()
|
||||
ret.srv.MutateCollation(serial.Collation(collation))
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r fbRvStorage) clone() fbRvStorage {
|
||||
bs := make([]byte, len(r.srv.Table().Bytes))
|
||||
copy(bs, r.srv.Table().Bytes)
|
||||
|
||||
@@ -293,6 +293,6 @@ const (
|
||||
Collation_utf8mb4_zh_0900_as_cs = Collation(serial.Collationutf8mb4_zh_0900_as_cs)
|
||||
Collation_utf8mb4_0900_bin = Collation(serial.Collationutf8mb4_0900_bin)
|
||||
|
||||
Collation_Default = Collation_utf8mb4_0900_bin
|
||||
Collation_Invalid = Collation(serial.Collationinvalid)
|
||||
Collation_Default = Collation_utf8mb4_0900_bin
|
||||
Collation_Unspecified = Collation(serial.Collationinvalid)
|
||||
)
|
||||
|
||||
@@ -77,8 +77,8 @@ func (c CollationTupleComparator) Validated(types []val.Type) val.TupleComparato
|
||||
}
|
||||
i := 0
|
||||
for ; i < len(c.Collations); i++ {
|
||||
if types[i].Enc == val.StringEnc && c.Collations[i] == sql.Collation_Invalid {
|
||||
panic("string type encoding is missing its collation")
|
||||
if types[i].Enc == val.StringEnc && c.Collations[i] == sql.Collation_Unspecified {
|
||||
c.Collations[i] = sql.Collation_Default
|
||||
}
|
||||
}
|
||||
if len(c.Collations) == len(types) {
|
||||
@@ -90,7 +90,7 @@ func (c CollationTupleComparator) Validated(types []val.Type) val.TupleComparato
|
||||
if types[i].Enc == val.StringEnc {
|
||||
panic("string type encoding is missing its collation")
|
||||
}
|
||||
newCollations[i] = sql.Collation_Invalid
|
||||
newCollations[i] = sql.Collation_Unspecified
|
||||
}
|
||||
return CollationTupleComparator{Collations: newCollations}
|
||||
}
|
||||
|
||||
@@ -375,7 +375,7 @@ func (si *schemaImpl) GetKeyDescriptor() val.TupleDesc {
|
||||
useCollations = true
|
||||
collations = append(collations, sqlType.(sql.StringType).Collation())
|
||||
} else {
|
||||
collations = append(collations, sql.Collation_Invalid)
|
||||
collations = append(collations, sql.Collation_Unspecified)
|
||||
}
|
||||
return
|
||||
})
|
||||
@@ -397,7 +397,7 @@ func (si *schemaImpl) GetValueDescriptor() val.TupleDesc {
|
||||
var collations []sql.CollationID
|
||||
if IsKeyless(si) {
|
||||
tt = []val.Type{val.KeylessCardType}
|
||||
collations = []sql.CollationID{sql.Collation_Invalid}
|
||||
collations = []sql.CollationID{sql.Collation_Unspecified}
|
||||
}
|
||||
|
||||
useCollations := false // We only use collations if a string exists
|
||||
@@ -412,7 +412,7 @@ func (si *schemaImpl) GetValueDescriptor() val.TupleDesc {
|
||||
useCollations = true
|
||||
collations = append(collations, sqlType.(sql.StringType).Collation())
|
||||
} else {
|
||||
collations = append(collations, sql.Collation_Invalid)
|
||||
collations = append(collations, sql.Collation_Unspecified)
|
||||
}
|
||||
return
|
||||
})
|
||||
@@ -430,19 +430,19 @@ func (si *schemaImpl) GetValueDescriptor() val.TupleDesc {
|
||||
|
||||
// GetCollation implements the Schema interface.
|
||||
func (si *schemaImpl) GetCollation() Collation {
|
||||
// Schemas made before this change (and invalid schemas) will contain invalid, so we'll the default collation
|
||||
// Schemas made before this change (and invalid schemas) will contain unspecified, so we'll the inherent collation
|
||||
// instead (as that matches their behavior).
|
||||
if si.collation == Collation_Invalid {
|
||||
return Collation_Default
|
||||
if si.collation == Collation_Unspecified {
|
||||
return Collation_utf8mb4_0900_bin
|
||||
}
|
||||
return si.collation
|
||||
}
|
||||
|
||||
// SetCollation implements the Schema interface.
|
||||
func (si *schemaImpl) SetCollation(collation Collation) {
|
||||
// Schemas made before this change may try to set this to invalid, so we'll set it to the default collation.
|
||||
if collation == Collation_Invalid {
|
||||
si.collation = Collation_Default
|
||||
// Schemas made before this change may try to set this to unspecified, so we'll set it to the inherent collation.
|
||||
if collation == Collation_Unspecified {
|
||||
si.collation = Collation_utf8mb4_0900_bin
|
||||
} else {
|
||||
si.collation = collation
|
||||
}
|
||||
|
||||
@@ -91,12 +91,21 @@ type Database struct {
|
||||
revision string
|
||||
}
|
||||
|
||||
var _ SqlDatabase = Database{}
|
||||
var _ dsess.RevisionDatabase = Database{}
|
||||
var _ globalstate.StateProvider = Database{}
|
||||
var _ sql.CollatedDatabase = Database{}
|
||||
var _ sql.Database = Database{}
|
||||
var _ sql.StoredProcedureDatabase = Database{}
|
||||
var _ sql.TableCreator = Database{}
|
||||
var _ sql.ViewDatabase = Database{}
|
||||
var _ sql.TableDropper = Database{}
|
||||
var _ sql.TableRenamer = Database{}
|
||||
var _ sql.TemporaryTableCreator = Database{}
|
||||
var _ sql.TemporaryTableDatabase = Database{}
|
||||
var _ dsess.RevisionDatabase = Database{}
|
||||
var _ sql.TransactionDatabase = Database{}
|
||||
var _ sql.TriggerDatabase = Database{}
|
||||
var _ sql.VersionedDatabase = Database{}
|
||||
var _ sql.ViewDatabase = Database{}
|
||||
|
||||
type ReadOnlyDatabase struct {
|
||||
Database
|
||||
@@ -160,17 +169,6 @@ func (db Database) EditOptions() editor.Options {
|
||||
return db.editOpts
|
||||
}
|
||||
|
||||
var _ SqlDatabase = Database{}
|
||||
var _ sql.VersionedDatabase = Database{}
|
||||
var _ sql.TableDropper = Database{}
|
||||
var _ sql.TableCreator = Database{}
|
||||
var _ sql.TemporaryTableCreator = Database{}
|
||||
var _ sql.TableRenamer = Database{}
|
||||
var _ sql.TriggerDatabase = Database{}
|
||||
var _ sql.StoredProcedureDatabase = Database{}
|
||||
var _ sql.TransactionDatabase = Database{}
|
||||
var _ globalstate.StateProvider = Database{}
|
||||
|
||||
// NewDatabase returns a new dolt database to use in queries.
|
||||
func NewDatabase(ctx context.Context, name string, dbData env.DbData, editOpts editor.Options) (Database, error) {
|
||||
globalState, err := globalstate.NewGlobalStateStoreForDb(ctx, dbData.Ddb)
|
||||
@@ -1280,6 +1278,38 @@ func (db Database) GetAllTemporaryTables(ctx *sql.Context) ([]sql.Table, error)
|
||||
return sess.GetAllTemporaryTables(ctx, db.Name())
|
||||
}
|
||||
|
||||
// GetCollation implements the interface sql.CollatedDatabase.
|
||||
func (db Database) GetCollation(ctx *sql.Context) sql.CollationID {
|
||||
root, err := db.GetRoot(ctx)
|
||||
if err != nil {
|
||||
return sql.Collation_Default
|
||||
}
|
||||
collation, err := root.GetCollation(ctx)
|
||||
if err != nil {
|
||||
return sql.Collation_Default
|
||||
}
|
||||
return sql.CollationID(collation)
|
||||
}
|
||||
|
||||
// SetCollation implements the interface sql.CollatedDatabase.
|
||||
func (db Database) SetCollation(ctx *sql.Context, collation sql.CollationID) error {
|
||||
if err := branch_control.CheckAccess(ctx, branch_control.Permissions_Write); err != nil {
|
||||
return err
|
||||
}
|
||||
if collation == sql.Collation_Unspecified {
|
||||
collation = sql.Collation_Default
|
||||
}
|
||||
root, err := db.GetRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newRoot, err := root.SetCollation(ctx, schema.Collation(collation))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.SetRoot(ctx, newRoot)
|
||||
}
|
||||
|
||||
// TODO: this is a hack to make user space DBs appear to the analyzer as full DBs with state etc., but the state is
|
||||
// really skeletal. We need to reexamine the DB / session initialization to make this simpler -- most of these things
|
||||
// aren't needed at initialization time and for most code paths.
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dprocedures"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
@@ -60,6 +61,7 @@ type DoltDatabaseProvider struct {
|
||||
var _ sql.DatabaseProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ sql.FunctionProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ sql.MutableDatabaseProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ sql.CollatedDatabaseProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ sql.ExternalStoredProcedureProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ sql.TableFunctionProvider = (*DoltDatabaseProvider)(nil)
|
||||
var _ dsess.DoltDatabaseProvider = (*DoltDatabaseProvider)(nil)
|
||||
@@ -298,6 +300,10 @@ func (p DoltDatabaseProvider) GetRemoteDB(ctx *sql.Context, srcDB *doltdb.DoltDB
|
||||
}
|
||||
|
||||
func (p DoltDatabaseProvider) CreateDatabase(ctx *sql.Context, name string) error {
|
||||
return p.CreateCollatedDatabase(ctx, name, sql.Collation_Default)
|
||||
}
|
||||
|
||||
func (p DoltDatabaseProvider) CreateCollatedDatabase(ctx *sql.Context, name string, collation sql.CollationID) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
@@ -350,6 +356,25 @@ func (p DoltDatabaseProvider) CreateDatabase(ctx *sql.Context, name string) erro
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the collation
|
||||
if collation != sql.Collation_Default {
|
||||
workingRoot, err := newEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newRoot, err := workingRoot.SetCollation(ctx, schema.Collation(collation))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// As this is a newly created database, we set both the working and staged roots to the same root value
|
||||
if err = newEnv.UpdateWorkingRoot(ctx, newRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = newEnv.UpdateStagedRoot(ctx, newRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// if calling process has a lockfile, also create one for new database
|
||||
if env.FsIsLocked(p.fs) {
|
||||
err := newEnv.Lock()
|
||||
|
||||
@@ -46,7 +46,7 @@ var skipPrepared bool
|
||||
// SkipPreparedsCount is used by the "ci-check-repo CI workflow
|
||||
// as a reminder to consider prepareds when adding a new
|
||||
// enginetest suite.
|
||||
const SkipPreparedsCount = 81
|
||||
const SkipPreparedsCount = 82
|
||||
|
||||
const skipPreparedFlag = "DOLT_SKIP_PREPARED_ENGINETESTS"
|
||||
|
||||
@@ -1426,6 +1426,12 @@ func TestCharsetCollationWire(t *testing.T) {
|
||||
enginetest.TestCharsetCollationWire(t, harness, newSessionBuilder(harness))
|
||||
}
|
||||
|
||||
func TestDatabaseCollationWire(t *testing.T) {
|
||||
skipOldFormat(t)
|
||||
harness := newDoltHarness(t)
|
||||
enginetest.TestDatabaseCollationWire(t, harness, newSessionBuilder(harness))
|
||||
}
|
||||
|
||||
func TestAddDropPrimaryKeys(t *testing.T) {
|
||||
t.Run("adding and dropping primary keys does not result in duplicate NOT NULL constraints", func(t *testing.T) {
|
||||
harness := newDoltHarness(t)
|
||||
|
||||
@@ -88,9 +88,9 @@ func BasicSelectTests() []SelectTest {
|
||||
var headCommitHash string
|
||||
switch types.Format_Default {
|
||||
case types.Format_DOLT:
|
||||
headCommitHash = "4ej7hfduufg4o2837g3gc4p5uolrlmv9"
|
||||
headCommitHash = "a0gt4vif0b0bf19g89k87gs55qqlqpod"
|
||||
case types.Format_DOLT_DEV:
|
||||
headCommitHash = "4ej7hfduufg4o2837g3gc4p5uolrlmv9"
|
||||
headCommitHash = "a0gt4vif0b0bf19g89k87gs55qqlqpod"
|
||||
case types.Format_LD_1:
|
||||
headCommitHash = "73hc2robs4v0kt9taoe3m5hd49dmrgun"
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@ func ParseCreateTableStatement(ctx context.Context, root *doltdb.RootValue, quer
|
||||
|
||||
ts := ddl.(*sqlparser.DDL).TableSpec
|
||||
s, collation, err := parse.TableSpecToSchema(sql.NewContext(ctx), ts, false)
|
||||
for _, col := range s.Schema {
|
||||
if collatedType, ok := col.Type.(sql.TypeWithCollation); ok {
|
||||
col.Type, err = collatedType.WithNewCollation(sql.Collation_Default)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
include "prolly.fbs";
|
||||
include "collation.fbs";
|
||||
|
||||
namespace serial;
|
||||
|
||||
@@ -22,6 +23,8 @@ table RootValue {
|
||||
tables:[ubyte]; // Serialized AddressMap.
|
||||
|
||||
foreign_key_addr:[ubyte];
|
||||
|
||||
collation:Collation;
|
||||
}
|
||||
|
||||
// KEEP THIS IN SYNC WITH fileidentifiers.go
|
||||
|
||||
@@ -26,10 +26,9 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/dolthub/dolt/go/store/chunks"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
"github.com/dolthub/dolt/go/store/nbs"
|
||||
|
||||
"github.com/dolthub/dolt/go/store/chunks"
|
||||
"github.com/dolthub/dolt/go/store/prolly/tree"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
@@ -39,6 +39,10 @@ type database struct {
|
||||
ns tree.NodeStore
|
||||
}
|
||||
|
||||
const (
|
||||
databaseCollation = "db_collation"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrOptimisticLockFailed = errors.New("optimistic lock failed on database Root update")
|
||||
ErrMergeNeeded = errors.New("dataset head is not ancestor of commit")
|
||||
|
||||
@@ -21,7 +21,7 @@ teardown() {
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "r9jv07tf9un3fm1fg72v7ad9er89oeo7" ]] || false
|
||||
[[ ! "$output" =~ "hc7v93mjpbfassljk9kdk48b1fntsn6a" ]] || false
|
||||
[[ ! "$output" =~ "tdkt7s7805k1ml4hu37pm688g5i0b8ie" ]] || false
|
||||
|
||||
dolt migrate
|
||||
[[ $(cat ./.dolt/noms/manifest | cut -f 2 -d :) = "$TARGET_NBF" ]] || false
|
||||
@@ -29,7 +29,7 @@ teardown() {
|
||||
dolt tag -v
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "hc7v93mjpbfassljk9kdk48b1fntsn6a" ]] || false
|
||||
[[ "$output" =~ "tdkt7s7805k1ml4hu37pm688g5i0b8ie" ]] || false
|
||||
[[ ! "$output" =~ "r9jv07tf9un3fm1fg72v7ad9er89oeo7" ]] || false
|
||||
|
||||
# validate TEXT migration
|
||||
@@ -47,7 +47,7 @@ teardown() {
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "r9jv07tf9un3fm1fg72v7ad9er89oeo7" ]] || false
|
||||
[[ ! "$output" =~ "hc7v93mjpbfassljk9kdk48b1fntsn6a" ]] || false
|
||||
[[ ! "$output" =~ "tdkt7s7805k1ml4hu37pm688g5i0b8ie" ]] || false
|
||||
|
||||
dolt migrate
|
||||
[[ $(cat ./.dolt/noms/manifest | cut -f 2 -d :) = "$TARGET_NBF" ]] || false
|
||||
@@ -55,7 +55,7 @@ teardown() {
|
||||
dolt tag -v
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "hc7v93mjpbfassljk9kdk48b1fntsn6a" ]] || false
|
||||
[[ "$output" =~ "tdkt7s7805k1ml4hu37pm688g5i0b8ie" ]] || false
|
||||
[[ ! "$output" =~ "r9jv07tf9un3fm1fg72v7ad9er89oeo7" ]] || false
|
||||
|
||||
# validate TEXT migration
|
||||
@@ -72,7 +72,7 @@ teardown() {
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "u8s83gapv7ghnbmrtpm8q5es0dbl7lpd" ]] || false
|
||||
[[ ! "$output" =~ "i3f3orlfmbjgqnst90c8r96jps7tdtv9" ]] || false
|
||||
[[ ! "$output" =~ "apdp3stea20mmm80oiu2ipo07a7v1hvb" ]] || false
|
||||
|
||||
dolt migrate
|
||||
[[ $(cat ./.dolt/noms/manifest | cut -f 2 -d :) = "$TARGET_NBF" ]] || false
|
||||
@@ -80,6 +80,6 @@ teardown() {
|
||||
dolt tag -v
|
||||
run dolt tag -v
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "i3f3orlfmbjgqnst90c8r96jps7tdtv9" ]] || false
|
||||
[[ "$output" =~ "apdp3stea20mmm80oiu2ipo07a7v1hvb" ]] || false
|
||||
[[ ! "$output" =~ "u8s83gapv7ghnbmrtpm8q5es0dbl7lpd" ]] || false
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ teardown() {
|
||||
start_sql_server
|
||||
|
||||
dolt sql-client -u dolt --use-db '' -P $PORT -q "CREATE DATABASE test CHARACTER SET latin1 COLLATE latin1_swedish_ci;"
|
||||
skip "Defining charsets and collations on a database not supported"
|
||||
dolt sql-client -u dolt --use-db test -P $PORT -q "SELECT @@character_set_database" ";@@SESSION.character_set_database\nlatin1"
|
||||
dolt sql-client -u dolt --use-db test -P $PORT -q "SELECT @@character_set_database" ";@@SESSION.collation_database\nlatin1_swedish_ci"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user