You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
9.5 KiB
401 lines
9.5 KiB
// Copyright 2018 PingCAP, 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,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package core
|
|
|
|
import (
|
|
"github.com/pingcap/parser/auth"
|
|
"github.com/pingcap/parser/model"
|
|
"github.com/pingcap/parser/mysql"
|
|
"github.com/pingcap/tidb/domain"
|
|
"github.com/pingcap/tidb/infoschema"
|
|
"github.com/pingcap/tidb/sessionctx"
|
|
"github.com/pingcap/tidb/types"
|
|
"github.com/pingcap/tidb/util/mock"
|
|
)
|
|
|
|
func newLongType() types.FieldType {
|
|
return *(types.NewFieldType(mysql.TypeLong))
|
|
}
|
|
|
|
func newStringType() types.FieldType {
|
|
ft := types.NewFieldType(mysql.TypeVarchar)
|
|
ft.Charset, ft.Collate = types.DefaultCharsetForType(mysql.TypeVarchar)
|
|
return *ft
|
|
}
|
|
|
|
func newDateType() types.FieldType {
|
|
ft := types.NewFieldType(mysql.TypeDate)
|
|
return *ft
|
|
}
|
|
|
|
// MockSignedTable is only used for plan related tests.
|
|
func MockSignedTable() *model.TableInfo {
|
|
// column: a, b, c, d, e, c_str, d_str, e_str, f, g
|
|
// PK: a
|
|
// indices: c_d_e, e, f, g, f_g, c_d_e_str, c_d_e_str_prefix
|
|
indices := []*model.IndexInfo{
|
|
{
|
|
Name: model.NewCIStr("c_d_e"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("c"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 2,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("d"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 3,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("e"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 4,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
Unique: true,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("e"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("e"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 4,
|
|
},
|
|
},
|
|
State: model.StateWriteOnly,
|
|
Unique: true,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("f"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("f"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 8,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
Unique: true,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("g"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("g"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 9,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("f_g"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("f"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 8,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("g"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 9,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
Unique: true,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("c_d_e_str"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("c_str"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 5,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("d_str"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 6,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("e_str"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 7,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("e_d_c_str_prefix"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("e_str"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 7,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("d_str"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 6,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("c_str"),
|
|
Length: 10,
|
|
Offset: 5,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
},
|
|
}
|
|
pkColumn := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 0,
|
|
Name: model.NewCIStr("a"),
|
|
FieldType: newLongType(),
|
|
ID: 1,
|
|
}
|
|
col0 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 1,
|
|
Name: model.NewCIStr("b"),
|
|
FieldType: newLongType(),
|
|
ID: 2,
|
|
}
|
|
col1 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 2,
|
|
Name: model.NewCIStr("c"),
|
|
FieldType: newLongType(),
|
|
ID: 3,
|
|
}
|
|
col2 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 3,
|
|
Name: model.NewCIStr("d"),
|
|
FieldType: newLongType(),
|
|
ID: 4,
|
|
}
|
|
col3 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 4,
|
|
Name: model.NewCIStr("e"),
|
|
FieldType: newLongType(),
|
|
ID: 5,
|
|
}
|
|
colStr1 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 5,
|
|
Name: model.NewCIStr("c_str"),
|
|
FieldType: newStringType(),
|
|
ID: 6,
|
|
}
|
|
colStr2 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 6,
|
|
Name: model.NewCIStr("d_str"),
|
|
FieldType: newStringType(),
|
|
ID: 7,
|
|
}
|
|
colStr3 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 7,
|
|
Name: model.NewCIStr("e_str"),
|
|
FieldType: newStringType(),
|
|
ID: 8,
|
|
}
|
|
col4 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 8,
|
|
Name: model.NewCIStr("f"),
|
|
FieldType: newLongType(),
|
|
ID: 9,
|
|
}
|
|
col5 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 9,
|
|
Name: model.NewCIStr("g"),
|
|
FieldType: newLongType(),
|
|
ID: 10,
|
|
}
|
|
col6 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 10,
|
|
Name: model.NewCIStr("h"),
|
|
FieldType: newLongType(),
|
|
ID: 11,
|
|
}
|
|
col7 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 11,
|
|
Name: model.NewCIStr("i_date"),
|
|
FieldType: newDateType(),
|
|
ID: 12,
|
|
}
|
|
pkColumn.Flag = mysql.PriKeyFlag | mysql.NotNullFlag
|
|
// Column 'b', 'c', 'd', 'f', 'g' is not null.
|
|
col0.Flag = mysql.NotNullFlag
|
|
col1.Flag = mysql.NotNullFlag
|
|
col2.Flag = mysql.NotNullFlag
|
|
col4.Flag = mysql.NotNullFlag
|
|
col5.Flag = mysql.NotNullFlag
|
|
col6.Flag = mysql.NoDefaultValueFlag
|
|
table := &model.TableInfo{
|
|
Columns: []*model.ColumnInfo{pkColumn, col0, col1, col2, col3, colStr1, colStr2, colStr3, col4, col5, col6, col7},
|
|
Indices: indices,
|
|
Name: model.NewCIStr("t"),
|
|
PKIsHandle: true,
|
|
}
|
|
return table
|
|
}
|
|
|
|
// MockUnsignedTable is only used for plan related tests.
|
|
func MockUnsignedTable() *model.TableInfo {
|
|
// column: a, b
|
|
// PK: a
|
|
// indeices: b
|
|
indices := []*model.IndexInfo{
|
|
{
|
|
Name: model.NewCIStr("b"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("b"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 1,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
Unique: true,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("b_c"),
|
|
Columns: []*model.IndexColumn{
|
|
{
|
|
Name: model.NewCIStr("b"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 1,
|
|
},
|
|
{
|
|
Name: model.NewCIStr("c"),
|
|
Length: types.UnspecifiedLength,
|
|
Offset: 2,
|
|
},
|
|
},
|
|
State: model.StatePublic,
|
|
},
|
|
}
|
|
pkColumn := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 0,
|
|
Name: model.NewCIStr("a"),
|
|
FieldType: newLongType(),
|
|
ID: 1,
|
|
}
|
|
col0 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 1,
|
|
Name: model.NewCIStr("b"),
|
|
FieldType: newLongType(),
|
|
ID: 2,
|
|
}
|
|
col1 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 2,
|
|
Name: model.NewCIStr("c"),
|
|
FieldType: newLongType(),
|
|
ID: 3,
|
|
}
|
|
pkColumn.Flag = mysql.PriKeyFlag | mysql.NotNullFlag | mysql.UnsignedFlag
|
|
// Column 'b', 'c', 'd', 'f', 'g' is not null.
|
|
col0.Flag = mysql.NotNullFlag
|
|
col1.Flag = mysql.UnsignedFlag
|
|
table := &model.TableInfo{
|
|
Columns: []*model.ColumnInfo{pkColumn, col0, col1},
|
|
Indices: indices,
|
|
Name: model.NewCIStr("t2"),
|
|
PKIsHandle: true,
|
|
}
|
|
return table
|
|
}
|
|
|
|
// MockView is only used for plan related tests.
|
|
func MockView() *model.TableInfo {
|
|
selectStmt := "select b,c,d from t"
|
|
col0 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 0,
|
|
Name: model.NewCIStr("b"),
|
|
ID: 1,
|
|
}
|
|
col1 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 1,
|
|
Name: model.NewCIStr("c"),
|
|
ID: 2,
|
|
}
|
|
col2 := &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: 2,
|
|
Name: model.NewCIStr("d"),
|
|
ID: 3,
|
|
}
|
|
view := &model.ViewInfo{SelectStmt: selectStmt, Security: model.SecurityDefiner, Definer: &auth.UserIdentity{Username: "root", Hostname: ""}, Cols: []model.CIStr{col0.Name, col1.Name, col2.Name}}
|
|
table := &model.TableInfo{
|
|
Name: model.NewCIStr("v"),
|
|
Columns: []*model.ColumnInfo{col0, col1, col2},
|
|
View: view,
|
|
}
|
|
return table
|
|
}
|
|
|
|
// MockContext is only used for plan related tests.
|
|
func MockContext() sessionctx.Context {
|
|
ctx := mock.NewContext()
|
|
ctx.Store = &mock.Store{
|
|
Client: &mock.Client{},
|
|
}
|
|
ctx.GetSessionVars().CurrentDB = "test"
|
|
do := &domain.Domain{}
|
|
do.CreateStatsHandle(ctx)
|
|
domain.BindDomain(ctx, do)
|
|
return ctx
|
|
}
|
|
|
|
// MockPartitionInfoSchema mocks an info schema for partition table.
|
|
func MockPartitionInfoSchema(definitions []model.PartitionDefinition) infoschema.InfoSchema {
|
|
tableInfo := MockSignedTable()
|
|
cols := make([]*model.ColumnInfo, 0, len(tableInfo.Columns))
|
|
cols = append(cols, tableInfo.Columns...)
|
|
last := tableInfo.Columns[len(tableInfo.Columns)-1]
|
|
cols = append(cols, &model.ColumnInfo{
|
|
State: model.StatePublic,
|
|
Offset: last.Offset + 1,
|
|
Name: model.NewCIStr("ptn"),
|
|
FieldType: newLongType(),
|
|
ID: last.ID + 1,
|
|
})
|
|
partition := &model.PartitionInfo{
|
|
Type: model.PartitionTypeRange,
|
|
Expr: "ptn",
|
|
Enable: true,
|
|
Definitions: definitions,
|
|
}
|
|
tableInfo.Columns = cols
|
|
tableInfo.Partition = partition
|
|
is := infoschema.MockInfoSchema([]*model.TableInfo{tableInfo})
|
|
return is
|
|
}
|
|
|