зеркало из https://github.com/github/vitess-gh.git
Коммит
0698355fb7
|
@ -6,6 +6,21 @@
|
|||
"delete from nouser"
|
||||
"table nouser not found"
|
||||
|
||||
# explicit keyspace reference
|
||||
"update main.m1 set val = 1"
|
||||
{
|
||||
"Original": "update main.m1 set val = 1",
|
||||
"Instructions": {
|
||||
"Opcode": "UpdateUnsharded",
|
||||
"Keyspace": {
|
||||
"Name": "main",
|
||||
"Sharded": false
|
||||
},
|
||||
"Query": "update m1 set val = 1",
|
||||
"Table": "m1"
|
||||
}
|
||||
}
|
||||
|
||||
# update unsharded
|
||||
"update main1 set val = 1"
|
||||
{
|
||||
|
|
|
@ -790,6 +790,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
# implicit table reference for unsharded keyspace
|
||||
"select main.foo.col from main.foo"
|
||||
{
|
||||
"Original": "select main.foo.col from main.foo",
|
||||
"Instructions": {
|
||||
"Opcode": "SelectUnsharded",
|
||||
"Keyspace": {
|
||||
"Name": "main",
|
||||
"Sharded": false
|
||||
},
|
||||
"Query": "select foo.col from foo",
|
||||
"FieldQuery": "select foo.col from foo where 1 != 1"
|
||||
}
|
||||
}
|
||||
|
||||
# implicit table reference for sharded keyspace
|
||||
"select user.foo.col from user.foo"
|
||||
"table foo not found"
|
||||
|
||||
# duplicate symbols
|
||||
"select user.id from user join user"
|
||||
"duplicate symbol: user"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"Owner": "user"
|
||||
}
|
||||
},
|
||||
"Classes": {
|
||||
"Tables": {
|
||||
"user": {
|
||||
"ColVindexes": [
|
||||
{
|
||||
|
@ -77,23 +77,14 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"user": "user",
|
||||
"user_extra": "user_extra",
|
||||
"music": "music",
|
||||
"music_extra": "music_extra"
|
||||
}
|
||||
},
|
||||
"main": {
|
||||
"Classes": {
|
||||
"Tables": {
|
||||
"main1": {},
|
||||
"seq": {
|
||||
"Type": "Sequence"
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"main1": "",
|
||||
"seq": "seq"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,10 +146,6 @@
|
|||
"delete from user where col = (select id from main1)"
|
||||
"unsupported: subqueries in DML"
|
||||
|
||||
# qualified table name in DMLs
|
||||
"update u.user set id = 1"
|
||||
"unsupported: compex table expression in DML"
|
||||
|
||||
# update with no where clause
|
||||
"update user set val = 1"
|
||||
"unsupported: multi-shard where clause in DML"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"Type": "numeric"
|
||||
}
|
||||
},
|
||||
"Classes": {
|
||||
"Tables": {
|
||||
"user": {
|
||||
"ColVindexes": [
|
||||
{
|
||||
|
@ -89,26 +89,18 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"user": "user",
|
||||
"user_extra": "user_extra",
|
||||
"music": "music",
|
||||
"music_extra": "music_extra",
|
||||
"music_user_idx": "music_user_idx"
|
||||
}
|
||||
},
|
||||
"lookup": {
|
||||
"Sharded": false,
|
||||
"Classes": {
|
||||
"seq": {
|
||||
"Type": "Sequence"
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"user_seq": "seq",
|
||||
"music_seq": "seq",
|
||||
"name_user_idx": ""
|
||||
"user_seq": {
|
||||
"Type": "Sequence"
|
||||
},
|
||||
"music_seq": {
|
||||
"Type": "Sequence"
|
||||
},
|
||||
"name_user_idx": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,11 +65,11 @@ func (c *callerIDClient) checkCallerID(ctx context.Context, received string) (bo
|
|||
return true, fmt.Errorf("SUCCESS: callerid matches")
|
||||
}
|
||||
|
||||
func (c *callerIDClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (c *callerIDClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if ok, err := c.checkCallerID(ctx, sql); ok {
|
||||
return nil, err
|
||||
}
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
}
|
||||
|
||||
func (c *callerIDClient) ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
|
@ -118,11 +118,11 @@ func (c *callerIDClient) ExecuteBatchKeyspaceIds(ctx context.Context, queries []
|
|||
return c.fallbackClient.ExecuteBatchKeyspaceIds(ctx, queries, tabletType, asTransaction, session)
|
||||
}
|
||||
|
||||
func (c *callerIDClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (c *callerIDClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
if ok, err := c.checkCallerID(ctx, sql); ok {
|
||||
return err
|
||||
}
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, tabletType, sendReply)
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, keyspace, tabletType, sendReply)
|
||||
}
|
||||
|
||||
func (c *callerIDClient) StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
|
|
|
@ -86,18 +86,19 @@ func echoQueryResult(vals map[string]interface{}) *sqltypes.Result {
|
|||
return qr
|
||||
}
|
||||
|
||||
func (c *echoClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (c *echoClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if strings.HasPrefix(sql, EchoPrefix) {
|
||||
return echoQueryResult(map[string]interface{}{
|
||||
"callerId": callerid.EffectiveCallerIDFromContext(ctx),
|
||||
"query": sql,
|
||||
"bindVars": bindVariables,
|
||||
"keyspace": keyspace,
|
||||
"tabletType": tabletType,
|
||||
"session": session,
|
||||
"notInTransaction": notInTransaction,
|
||||
}), nil
|
||||
}
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
}
|
||||
|
||||
func (c *echoClient) ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
|
@ -205,17 +206,18 @@ func (c *echoClient) ExecuteBatchKeyspaceIds(ctx context.Context, queries []*vtg
|
|||
return c.fallbackClient.ExecuteBatchKeyspaceIds(ctx, queries, tabletType, asTransaction, session)
|
||||
}
|
||||
|
||||
func (c *echoClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (c *echoClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
if strings.HasPrefix(sql, EchoPrefix) {
|
||||
sendReply(echoQueryResult(map[string]interface{}{
|
||||
"callerId": callerid.EffectiveCallerIDFromContext(ctx),
|
||||
"query": sql,
|
||||
"bindVars": bindVariables,
|
||||
"keyspace": keyspace,
|
||||
"tabletType": tabletType,
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, tabletType, sendReply)
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, keyspace, tabletType, sendReply)
|
||||
}
|
||||
|
||||
func (c *echoClient) StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
|
|
|
@ -118,14 +118,14 @@ func trimmedRequestToError(received string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *errorClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (c *errorClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if err := requestToPartialError(sql, session); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := requestToError(sql); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
return c.fallbackClient.Execute(ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
}
|
||||
|
||||
func (c *errorClient) ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
|
@ -192,11 +192,11 @@ func (c *errorClient) ExecuteBatchKeyspaceIds(ctx context.Context, queries []*vt
|
|||
return c.fallbackClient.ExecuteBatchKeyspaceIds(ctx, queries, tabletType, asTransaction, session)
|
||||
}
|
||||
|
||||
func (c *errorClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (c *errorClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
if err := requestToError(sql); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, tabletType, sendReply)
|
||||
return c.fallbackClient.StreamExecute(ctx, sql, bindVariables, keyspace, tabletType, sendReply)
|
||||
}
|
||||
|
||||
func (c *errorClient) StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
|
|
|
@ -27,8 +27,8 @@ func newFallbackClient(fallback vtgateservice.VTGateService) fallbackClient {
|
|||
return fallbackClient{fallback: fallback}
|
||||
}
|
||||
|
||||
func (c fallbackClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
return c.fallback.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
func (c fallbackClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
return c.fallback.Execute(ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
}
|
||||
|
||||
func (c fallbackClient) ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
|
@ -55,8 +55,8 @@ func (c fallbackClient) ExecuteBatchKeyspaceIds(ctx context.Context, queries []*
|
|||
return c.fallback.ExecuteBatchKeyspaceIds(ctx, queries, tabletType, asTransaction, session)
|
||||
}
|
||||
|
||||
func (c fallbackClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
return c.fallback.StreamExecute(ctx, sql, bindVariables, tabletType, sendReply)
|
||||
func (c fallbackClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
return c.fallback.StreamExecute(ctx, sql, bindVariables, keyspace, tabletType, sendReply)
|
||||
}
|
||||
|
||||
func (c fallbackClient) StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
|
|
|
@ -29,7 +29,7 @@ func newTerminalClient() *terminalClient {
|
|||
return &terminalClient{}
|
||||
}
|
||||
|
||||
func (c *terminalClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (c *terminalClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if sql == "quit://" {
|
||||
log.Fatal("Received quit:// query. Going down.")
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func (c *terminalClient) ExecuteBatchKeyspaceIds(ctx context.Context, queries []
|
|||
return nil, errTerminal
|
||||
}
|
||||
|
||||
func (c *terminalClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (c *terminalClient) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
return errTerminal
|
||||
}
|
||||
|
||||
|
|
|
@ -114,6 +114,8 @@ type ExecuteRequest struct {
|
|||
TabletType topodata.TabletType `protobuf:"varint,4,opt,name=tablet_type,json=tabletType,enum=topodata.TabletType" json:"tablet_type,omitempty"`
|
||||
// not_in_transaction is deprecated and should not be used.
|
||||
NotInTransaction bool `protobuf:"varint,5,opt,name=not_in_transaction,json=notInTransaction" json:"not_in_transaction,omitempty"`
|
||||
// keyspace to target the query to.
|
||||
Keyspace string `protobuf:"bytes,6,opt,name=keyspace" json:"keyspace,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ExecuteRequest) Reset() { *m = ExecuteRequest{} }
|
||||
|
@ -774,6 +776,8 @@ type StreamExecuteRequest struct {
|
|||
Query *query.BoundQuery `protobuf:"bytes,2,opt,name=query" json:"query,omitempty"`
|
||||
// tablet_type is the type of tablets that this query is targeted to.
|
||||
TabletType topodata.TabletType `protobuf:"varint,3,opt,name=tablet_type,json=tabletType,enum=topodata.TabletType" json:"tablet_type,omitempty"`
|
||||
// keyspace to target the query to.
|
||||
Keyspace string `protobuf:"bytes,4,opt,name=keyspace" json:"keyspace,omitempty"`
|
||||
}
|
||||
|
||||
func (m *StreamExecuteRequest) Reset() { *m = StreamExecuteRequest{} }
|
||||
|
@ -1376,87 +1380,88 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 1304 bytes of a gzipped FileDescriptorProto
|
||||
// 1316 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x59, 0x4f, 0x6f, 0xe3, 0x44,
|
||||
0x14, 0x97, 0xe3, 0x34, 0x69, 0x9e, 0x93, 0xb4, 0xf5, 0xb6, 0xdb, 0x10, 0x96, 0x6d, 0xb1, 0x40,
|
||||
0x5b, 0x60, 0x65, 0x69, 0xb3, 0xfc, 0x13, 0x42, 0x02, 0x1a, 0x2a, 0x14, 0x2d, 0xac, 0xca, 0xb4,
|
||||
0x42, 0x1c, 0x40, 0x96, 0x9b, 0x8c, 0x5a, 0xd3, 0xc4, 0x0e, 0x9e, 0x71, 0xa0, 0x1c, 0xb8, 0x21,
|
||||
0x71, 0xdb, 0x13, 0x12, 0x42, 0x5c, 0x90, 0xf8, 0x02, 0x7c, 0x04, 0x4e, 0x1c, 0x39, 0x70, 0xe0,
|
||||
0xc6, 0x47, 0x80, 0x23, 0x17, 0x0e, 0x8c, 0x67, 0xc6, 0x7f, 0xe2, 0x36, 0x69, 0x9a, 0xb4, 0x55,
|
||||
0x7a, 0xaa, 0x67, 0xde, 0x9b, 0x79, 0xef, 0xfd, 0x7e, 0x6f, 0xde, 0xcc, 0x6b, 0xa0, 0x3c, 0xa0,
|
||||
0x87, 0x36, 0xc5, 0x66, 0xdf, 0xf7, 0xa8, 0xa7, 0x17, 0xc4, 0xa8, 0xae, 0x7d, 0x1e, 0x60, 0xff,
|
||||
0x44, 0x4c, 0xd6, 0xab, 0xd4, 0xeb, 0x7b, 0x1d, 0x9b, 0xda, 0x72, 0xac, 0x0d, 0xa8, 0xdf, 0x6f,
|
||||
0x8b, 0x81, 0xf1, 0x87, 0x02, 0xc5, 0x3d, 0x4c, 0x88, 0xe3, 0xb9, 0xfa, 0xf3, 0x50, 0x75, 0x5c,
|
||||
0x8b, 0xfa, 0xb6, 0x4b, 0xec, 0x36, 0x65, 0x33, 0x35, 0x65, 0x53, 0xd9, 0x5a, 0x44, 0x15, 0xc7,
|
||||
0xdd, 0x4f, 0x26, 0xf5, 0x26, 0x54, 0xc9, 0x91, 0xed, 0x77, 0x2c, 0x22, 0xd6, 0x91, 0x5a, 0x6e,
|
||||
0x53, 0xdd, 0xd2, 0x1a, 0x77, 0x4c, 0xe9, 0x8b, 0xdc, 0xcf, 0xdc, 0x0b, 0xb5, 0xe4, 0x00, 0x55,
|
||||
0x48, 0x6a, 0x44, 0xea, 0x9f, 0x40, 0x39, 0x2d, 0x66, 0xb6, 0x0b, 0xd4, 0xf6, 0x0f, 0x31, 0xe5,
|
||||
0x36, 0xb5, 0x46, 0xc5, 0x14, 0x21, 0xec, 0xf3, 0x49, 0x24, 0x85, 0xa1, 0x8b, 0x29, 0xff, 0x2c,
|
||||
0xa7, 0xc3, 0x6c, 0x2b, 0x5b, 0x2a, 0xaa, 0xa4, 0x66, 0x5b, 0x1d, 0xe3, 0x5f, 0x05, 0xaa, 0x3b,
|
||||
0x5f, 0xe2, 0x76, 0x40, 0x31, 0xc2, 0x6c, 0x23, 0x42, 0xf5, 0xfb, 0x50, 0x6a, 0xdb, 0xdd, 0x2e,
|
||||
0xf6, 0xc3, 0x45, 0xc2, 0xc6, 0x92, 0x29, 0x90, 0x68, 0xf2, 0xf9, 0xd6, 0xbb, 0x68, 0x51, 0x68,
|
||||
0xb4, 0x3a, 0xfa, 0x0b, 0x50, 0x94, 0xd1, 0x71, 0x03, 0x42, 0x37, 0x1d, 0x1c, 0x8a, 0xe4, 0xfa,
|
||||
0x3d, 0x58, 0xe0, 0xae, 0xd6, 0x54, 0xae, 0xb8, 0x22, 0x1d, 0xdf, 0xf6, 0x02, 0xb7, 0xf3, 0x61,
|
||||
0x14, 0x97, 0xe3, 0x34, 0x69, 0x9e, 0x93, 0xb4, 0xeb, 0x6d, 0x77, 0x43, 0x58, 0xb6, 0xc5, 0x02,
|
||||
0x6d, 0x81, 0x95, 0xa5, 0xcd, 0xf2, 0x4f, 0x08, 0x09, 0x68, 0xa8, 0x50, 0xb4, 0xb0, 0x2a, 0xd3,
|
||||
0x0a, 0x71, 0x00, 0x59, 0x6e, 0x32, 0x6a, 0x4d, 0x13, 0x3b, 0x78, 0xc6, 0x81, 0x72, 0xe0, 0x86,
|
||||
0xc4, 0x6d, 0x0f, 0x08, 0x09, 0x21, 0x2e, 0x7c, 0x04, 0xbe, 0x01, 0x9c, 0x38, 0x72, 0xe0, 0xc0,
|
||||
0x8d, 0x8f, 0x00, 0x5f, 0x80, 0x03, 0xe3, 0x99, 0xf1, 0x9f, 0xb8, 0x49, 0x9a, 0x26, 0x6d, 0x95,
|
||||
0x9e, 0xea, 0x99, 0xf7, 0x66, 0xde, 0x7b, 0xbf, 0xdf, 0x9b, 0x37, 0xf3, 0x1a, 0x28, 0x0f, 0xe8,
|
||||
0xa1, 0x4d, 0xb1, 0xd9, 0xf7, 0x3d, 0xea, 0xe9, 0x05, 0x31, 0xaa, 0x6b, 0x9f, 0x07, 0xd8, 0x3f,
|
||||
0x11, 0x93, 0xf5, 0x2a, 0xf5, 0xfa, 0x5e, 0xc7, 0xa6, 0xb6, 0x1c, 0x6b, 0x03, 0xea, 0xf7, 0xdb,
|
||||
0x62, 0x60, 0xfc, 0xa9, 0x40, 0x71, 0x0f, 0x13, 0xe2, 0x78, 0xae, 0xfe, 0x3c, 0x54, 0x1d, 0xd7,
|
||||
0xa2, 0xbe, 0xed, 0x12, 0xbb, 0x4d, 0xd9, 0x4c, 0x4d, 0xd9, 0x54, 0xb6, 0x96, 0x51, 0xc5, 0x71,
|
||||
0xf7, 0x93, 0x49, 0xbd, 0x09, 0x55, 0x72, 0x64, 0xfb, 0x1d, 0x8b, 0x88, 0x75, 0xa4, 0x96, 0xdb,
|
||||
0x54, 0xb7, 0xb4, 0xc6, 0x1d, 0x53, 0xfa, 0x22, 0xf7, 0x33, 0xf7, 0x42, 0x2d, 0x39, 0x40, 0x15,
|
||||
0x92, 0x1a, 0x91, 0xfa, 0x27, 0x50, 0x4e, 0x8b, 0x99, 0xed, 0x02, 0xb5, 0xfd, 0x43, 0x4c, 0xb9,
|
||||
0x4d, 0xad, 0x51, 0x31, 0x45, 0x08, 0xfb, 0x7c, 0x12, 0x49, 0x61, 0xe8, 0x62, 0xca, 0x3f, 0xcb,
|
||||
0xe9, 0x30, 0xdb, 0xca, 0x96, 0x8a, 0x2a, 0xa9, 0xd9, 0x56, 0xc7, 0xf8, 0x2e, 0x07, 0xd5, 0x9d,
|
||||
0x2f, 0x71, 0x3b, 0xa0, 0x18, 0x61, 0xb6, 0x11, 0xa1, 0xfa, 0x7d, 0x28, 0xb5, 0xed, 0x6e, 0x17,
|
||||
0xfb, 0xe1, 0x22, 0x61, 0x63, 0xc5, 0x14, 0x48, 0x34, 0xf9, 0x7c, 0xeb, 0x5d, 0xb4, 0x2c, 0x34,
|
||||
0x5a, 0x1d, 0xfd, 0x05, 0x28, 0xca, 0xe8, 0xb8, 0x01, 0xa1, 0x9b, 0x0e, 0x0e, 0x45, 0x72, 0xfd,
|
||||
0x1e, 0x2c, 0x71, 0x57, 0x6b, 0x2a, 0x57, 0xbc, 0x21, 0x1d, 0xdf, 0xf6, 0x02, 0xb7, 0xf3, 0x61,
|
||||
0xf8, 0x89, 0x84, 0x5c, 0x7f, 0x05, 0x34, 0x6a, 0x1f, 0x74, 0x31, 0xb5, 0xe8, 0x49, 0x1f, 0xd7,
|
||||
0xf2, 0x4c, 0xbd, 0xda, 0x58, 0x35, 0x63, 0x76, 0xf6, 0xb9, 0x70, 0x9f, 0xc9, 0x10, 0xd0, 0xf8,
|
||||
0x9b, 0x39, 0xae, 0xbb, 0x1e, 0xb5, 0x32, 0xcc, 0x2c, 0x70, 0x66, 0x96, 0x99, 0xa4, 0x95, 0x26,
|
||||
0xc7, 0x78, 0xa2, 0xc0, 0x52, 0x1c, 0x39, 0xe9, 0x33, 0xa8, 0x31, 0x03, 0x6d, 0x01, 0xfb, 0xbe,
|
||||
0xe7, 0x67, 0xc2, 0x46, 0xbb, 0xcd, 0x9d, 0x70, 0x1a, 0x09, 0xe9, 0x45, 0x62, 0x7e, 0x11, 0x0a,
|
||||
0x3e, 0x26, 0x41, 0x97, 0xca, 0xa0, 0x75, 0x19, 0xb4, 0x88, 0x97, 0x4b, 0x90, 0xd4, 0x30, 0x7e,
|
||||
0xc9, 0xc1, 0xaa, 0xf4, 0x88, 0x33, 0x4e, 0xe6, 0x87, 0x91, 0x3a, 0x2c, 0x1e, 0xe3, 0x13, 0xd2,
|
||||
0xb7, 0xdb, 0x82, 0x8e, 0x12, 0x8a, 0xc7, 0xfa, 0x6d, 0x28, 0xf0, 0x8c, 0x25, 0x0c, 0x6a, 0x95,
|
||||
0x49, 0xe4, 0x28, 0xcb, 0x62, 0x61, 0x26, 0x16, 0x8b, 0x23, 0x58, 0xfc, 0x4e, 0x81, 0xb5, 0x0c,
|
||||
0x66, 0x73, 0xc1, 0xe5, 0xaf, 0x39, 0x78, 0x4a, 0xfa, 0xf5, 0x48, 0x02, 0xd5, 0xba, 0x29, 0x84,
|
||||
0x3e, 0x0b, 0xe5, 0xe8, 0x9b, 0xf9, 0x27, 0x68, 0x2d, 0x23, 0xed, 0x38, 0x89, 0xe3, 0x7a, 0xb8,
|
||||
0xfd, 0x41, 0x81, 0xfa, 0x59, 0x18, 0xce, 0x05, 0xc1, 0xbf, 0xe7, 0x60, 0x3d, 0x71, 0x0e, 0xd9,
|
||||
0xee, 0x21, 0xbe, 0x21, 0xf4, 0x3e, 0x00, 0x60, 0xdf, 0x96, 0xcf, 0x5d, 0xe6, 0xe4, 0x86, 0x91,
|
||||
0xc6, 0xd4, 0x45, 0xd1, 0xa0, 0xd2, 0x71, 0x14, 0xd7, 0xf5, 0xd0, 0xfd, 0xbd, 0x02, 0xb5, 0xd3,
|
||||
0x88, 0xce, 0x05, 0xd9, 0xdf, 0xe6, 0x63, 0xb2, 0x77, 0x5c, 0xea, 0xd0, 0x93, 0x1b, 0x73, 0x96,
|
||||
0x19, 0x05, 0x98, 0x7b, 0x6c, 0xb5, 0xbd, 0x6e, 0xd0, 0x73, 0x2d, 0xd7, 0xee, 0x61, 0x7e, 0x27,
|
||||
0x96, 0xd0, 0xb2, 0x90, 0x34, 0xb9, 0xe0, 0x31, 0x9b, 0xd7, 0x3f, 0x86, 0x5b, 0x52, 0x7b, 0xa8,
|
||||
0x00, 0x14, 0x78, 0x8e, 0x6c, 0x45, 0x9e, 0x8e, 0x40, 0xc2, 0x8c, 0x26, 0xd0, 0x8a, 0xd8, 0xe4,
|
||||
0xd1, 0xe8, 0x82, 0x51, 0x9c, 0x29, 0x83, 0x16, 0xcf, 0xce, 0xa0, 0xfa, 0x01, 0x2c, 0x46, 0x3e,
|
||||
0xe8, 0x1b, 0x90, 0xe7, 0x96, 0x14, 0x6e, 0x49, 0x8b, 0x1e, 0x49, 0xa1, 0x01, 0x2e, 0xd0, 0x57,
|
||||
0x61, 0x61, 0x60, 0x77, 0x03, 0xcc, 0x79, 0x28, 0x23, 0x31, 0x60, 0xcb, 0xb4, 0x54, 0xe8, 0x1c,
|
||||
0xfa, 0x32, 0x82, 0xa4, 0xf4, 0xa5, 0xb3, 0x34, 0x05, 0xc0, 0x5c, 0x64, 0xa9, 0x0b, 0x4b, 0x3c,
|
||||
0x39, 0xf8, 0x45, 0xc8, 0x15, 0x92, 0x1c, 0x52, 0x2e, 0x90, 0x43, 0xb9, 0x91, 0x17, 0xbc, 0x9a,
|
||||
0xbe, 0xe0, 0x8d, 0x6f, 0x92, 0x3b, 0x6e, 0xdb, 0xa6, 0xed, 0xa3, 0x6b, 0x7a, 0xb4, 0x3c, 0x80,
|
||||
0x62, 0xe8, 0xb3, 0x83, 0x85, 0x3f, 0x5a, 0x63, 0x3d, 0x52, 0xcd, 0x44, 0x8f, 0x22, 0xbd, 0x69,
|
||||
0x1f, 0x94, 0xec, 0x0d, 0x6d, 0x93, 0x33, 0x1e, 0x93, 0x15, 0x9b, 0xa4, 0x0b, 0xd7, 0x8f, 0xc9,
|
||||
0x3d, 0x35, 0x84, 0xc3, 0x95, 0x25, 0xc5, 0x7d, 0x28, 0x0a, 0xca, 0x23, 0x04, 0xce, 0xca, 0x8a,
|
||||
0x48, 0xc5, 0xf8, 0x1a, 0x56, 0x39, 0x30, 0xc9, 0x71, 0xbc, 0xc4, 0xdc, 0xc8, 0xbe, 0x15, 0xd4,
|
||||
0x53, 0x6f, 0x05, 0xe3, 0x49, 0x0e, 0xee, 0xa6, 0xe1, 0xb9, 0xce, 0xf7, 0xd0, 0xab, 0xd9, 0x5c,
|
||||
0xb9, 0x33, 0x94, 0x2b, 0x19, 0x48, 0xae, 0x2b, 0x61, 0x7e, 0x52, 0x60, 0x63, 0x24, 0x22, 0x73,
|
||||
0x92, 0x35, 0x3f, 0x2b, 0xb0, 0xba, 0x47, 0x7d, 0x6c, 0xf7, 0x66, 0x6a, 0x0f, 0xe3, 0x24, 0xcb,
|
||||
0x5d, 0xac, 0xe7, 0x53, 0x27, 0x43, 0xdc, 0x68, 0xc2, 0x5a, 0xc6, 0x4b, 0x89, 0x5f, 0x52, 0x38,
|
||||
0x95, 0x73, 0x0b, 0xe7, 0x5f, 0xec, 0x00, 0x0f, 0xed, 0x32, 0x4b, 0x25, 0x9b, 0x38, 0xe2, 0xf4,
|
||||
0xb1, 0x52, 0x47, 0x96, 0xdc, 0xfc, 0xb8, 0x9e, 0x6a, 0x61, 0x42, 0x94, 0x5a, 0xf0, 0xf4, 0x99,
|
||||
0xf1, 0x4d, 0x81, 0xd5, 0xdf, 0x2c, 0x77, 0x87, 0xf6, 0x9a, 0xf9, 0x38, 0x5f, 0x0a, 0x60, 0xd9,
|
||||
0x3a, 0x94, 0x3f, 0xb7, 0x67, 0x99, 0x14, 0xbb, 0xc7, 0xb0, 0x39, 0x3a, 0xde, 0x29, 0x00, 0xfc,
|
||||
0x4f, 0x81, 0x67, 0xb2, 0x1b, 0xce, 0xd2, 0x3e, 0x5c, 0x0a, 0x7c, 0xc3, 0x3d, 0x41, 0x7e, 0x8a,
|
||||
0x9e, 0x60, 0x52, 0x38, 0xdf, 0x87, 0xbb, 0xa3, 0xa2, 0x9f, 0x02, 0xcc, 0x37, 0xa1, 0xbc, 0x8d,
|
||||
0x0f, 0x1d, 0x77, 0x2a, 0xe8, 0x8c, 0x37, 0xa0, 0x22, 0x57, 0x4b, 0xd3, 0xa9, 0x6a, 0xaa, 0x8c,
|
||||
0xaf, 0xa6, 0xc6, 0x11, 0x54, 0x9a, 0x5e, 0xaf, 0xe7, 0xd0, 0xab, 0xbe, 0xc3, 0x8c, 0x65, 0xa8,
|
||||
0x46, 0x96, 0x84, 0x9b, 0xc6, 0x67, 0xb0, 0x84, 0xbc, 0x6e, 0xf7, 0xc0, 0x6e, 0x1f, 0x5f, 0xb9,
|
||||
0x75, 0x1d, 0x96, 0x13, 0x5b, 0xd2, 0xfe, 0x3f, 0x39, 0x58, 0xd9, 0xeb, 0x77, 0x1d, 0x2a, 0x29,
|
||||
0x99, 0xc6, 0x85, 0x71, 0x8f, 0x8a, 0x89, 0x3b, 0x1f, 0x76, 0xea, 0x49, 0xe8, 0x87, 0x6c, 0x6e,
|
||||
0x64, 0xb1, 0xd4, 0xf8, 0x9c, 0x68, 0x6b, 0xc2, 0x07, 0x7d, 0xa4, 0x12, 0xb8, 0x94, 0xa7, 0xa9,
|
||||
0x8a, 0x40, 0x6a, 0xb0, 0x19, 0xfd, 0x65, 0x58, 0x77, 0x83, 0x9e, 0xe5, 0x7b, 0x5f, 0x10, 0xab,
|
||||
0xcf, 0x9c, 0xe7, 0x3b, 0x5b, 0x7d, 0xdb, 0xa7, 0xbc, 0xcf, 0x55, 0xd1, 0x2d, 0x26, 0x46, 0x4c,
|
||||
0xba, 0x8b, 0x7d, 0x6e, 0x7c, 0x97, 0x89, 0xf4, 0xb7, 0xa1, 0x64, 0x77, 0x0f, 0x3d, 0xdf, 0xa1,
|
||||
0x47, 0x3d, 0xd9, 0xcd, 0x18, 0xd2, 0xcd, 0x53, 0xc8, 0x98, 0xef, 0x44, 0x9a, 0x28, 0x59, 0xa4,
|
||||
0xbf, 0x04, 0x7a, 0x40, 0xb0, 0x25, 0x9c, 0x13, 0x46, 0x07, 0x0d, 0xd9, 0xda, 0x2c, 0x31, 0x49,
|
||||
0xb2, 0xcd, 0x47, 0x0d, 0xe3, 0x37, 0x15, 0xf4, 0xf4, 0xbe, 0x32, 0x5f, 0x5f, 0x63, 0xd7, 0x44,
|
||||
0x38, 0x4b, 0x18, 0xde, 0xe1, 0x91, 0xdd, 0x88, 0x69, 0x3c, 0xa5, 0x6b, 0x86, 0x6e, 0x23, 0xa9,
|
||||
0x5e, 0xff, 0x14, 0xca, 0xd1, 0xc1, 0xe3, 0xe1, 0xa4, 0xd9, 0x50, 0xc6, 0xd6, 0x86, 0xdc, 0x04,
|
||||
0xb5, 0xa1, 0xfe, 0x16, 0x94, 0xf8, 0x15, 0x73, 0xee, 0xde, 0xc9, 0x3d, 0x97, 0x4b, 0xdf, 0x73,
|
||||
0xf5, 0x3f, 0x15, 0xc8, 0xf3, 0xc5, 0x13, 0x3f, 0x52, 0x3f, 0x80, 0x6a, 0xec, 0xa5, 0x60, 0x4f,
|
||||
0x64, 0xf6, 0xbd, 0x31, 0x90, 0xa4, 0x21, 0x40, 0xe5, 0xe3, 0x34, 0x20, 0x4d, 0x00, 0xf1, 0xaf,
|
||||
0x7b, 0xbe, 0x95, 0xc8, 0xc3, 0xe7, 0xc6, 0x6c, 0x15, 0x87, 0x8b, 0x4a, 0x24, 0x8e, 0x5c, 0x87,
|
||||
0x3c, 0x71, 0xbe, 0x12, 0xcf, 0x47, 0x15, 0xf1, 0x6f, 0xe3, 0x21, 0xac, 0xbd, 0x87, 0xe9, 0x9e,
|
||||
0x3f, 0x88, 0xee, 0x91, 0xe8, 0xf8, 0x8c, 0x81, 0xc9, 0x40, 0x70, 0x3b, 0xbb, 0x48, 0x66, 0xc0,
|
||||
0xeb, 0xec, 0x04, 0xf8, 0x03, 0x6b, 0x68, 0xa5, 0xd6, 0x58, 0x4b, 0xe8, 0x49, 0x2f, 0xd2, 0x48,
|
||||
0x32, 0xd8, 0xae, 0x43, 0xad, 0xed, 0xf5, 0xcc, 0x13, 0x2f, 0xa0, 0xc1, 0x01, 0x36, 0x07, 0x0e,
|
||||
0x65, 0x27, 0x5e, 0xfc, 0xd6, 0x71, 0x50, 0xe0, 0x7f, 0x1e, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff,
|
||||
0xad, 0x6e, 0xed, 0xad, 0x34, 0x19, 0x00, 0x00,
|
||||
0xf2, 0x4c, 0xbd, 0xda, 0x58, 0x33, 0x63, 0x76, 0xf6, 0xb9, 0x70, 0x9f, 0xc9, 0x10, 0xd0, 0xf8,
|
||||
0x9b, 0x39, 0xae, 0xbb, 0x1e, 0xb5, 0x32, 0xcc, 0x2c, 0x71, 0x66, 0x56, 0x99, 0xa4, 0x35, 0x44,
|
||||
0x4e, 0x1d, 0x96, 0x8f, 0xf1, 0x09, 0xe9, 0xdb, 0x6d, 0x5c, 0x2b, 0x30, 0x9d, 0x12, 0x8a, 0xc7,
|
||||
0xc6, 0x13, 0x05, 0x56, 0x62, 0x54, 0x48, 0x9f, 0xd1, 0x80, 0x19, 0xa0, 0x4b, 0xd8, 0xf7, 0x3d,
|
||||
0x3f, 0x03, 0x09, 0xda, 0x6d, 0xee, 0x84, 0xd3, 0x48, 0x48, 0xcf, 0x83, 0xc7, 0x8b, 0x50, 0xf0,
|
||||
0x31, 0x09, 0xba, 0x54, 0x02, 0xa2, 0x4b, 0x40, 0x04, 0x16, 0x5c, 0x82, 0xa4, 0x86, 0xf1, 0x4b,
|
||||
0x0e, 0xd6, 0xa4, 0x47, 0x3c, 0x1b, 0xc8, 0xe2, 0xb0, 0x95, 0x06, 0x32, 0x3f, 0x0c, 0xa4, 0x7e,
|
||||
0x0b, 0x0a, 0x3c, 0x9b, 0x09, 0xa3, 0x41, 0x65, 0x12, 0x39, 0xca, 0x32, 0x5c, 0x98, 0x8b, 0xe1,
|
||||
0xe2, 0x68, 0x86, 0x8d, 0xef, 0x15, 0x58, 0xcf, 0x60, 0xb6, 0x10, 0x5c, 0xfe, 0x96, 0x83, 0xa7,
|
||||
0xa4, 0x5f, 0x8f, 0x24, 0x50, 0xad, 0xeb, 0x42, 0xe8, 0xb3, 0x50, 0x8e, 0xbe, 0x99, 0x7f, 0x82,
|
||||
0xd6, 0x32, 0xd2, 0x8e, 0x93, 0x38, 0xae, 0x86, 0xdb, 0x1f, 0x15, 0xa8, 0x8f, 0xc2, 0x70, 0x21,
|
||||
0x08, 0xfe, 0x23, 0x07, 0xb7, 0x13, 0xe7, 0x90, 0xed, 0x1e, 0xe2, 0x6b, 0x42, 0xef, 0x03, 0x00,
|
||||
0xf6, 0x6d, 0xf9, 0xdc, 0x65, 0x4e, 0x6e, 0x18, 0x69, 0x4c, 0x5d, 0x14, 0x0d, 0x2a, 0x1d, 0x47,
|
||||
0x71, 0x5d, 0x0d, 0xdd, 0x3f, 0x28, 0x50, 0x3b, 0x8d, 0xe8, 0x42, 0x90, 0xfd, 0x6d, 0x3e, 0x26,
|
||||
0x7b, 0xc7, 0xa5, 0x0e, 0x3d, 0xb9, 0x36, 0x67, 0x99, 0x51, 0x80, 0xb9, 0xc7, 0x56, 0xdb, 0xeb,
|
||||
0x06, 0x3d, 0xd7, 0x72, 0xed, 0x1e, 0xe6, 0xf7, 0x65, 0x09, 0xad, 0x0a, 0x49, 0x93, 0x0b, 0x1e,
|
||||
0xb3, 0x79, 0xfd, 0x63, 0xb8, 0x29, 0xb5, 0x87, 0x0a, 0x40, 0x81, 0xe7, 0xc8, 0x56, 0xe4, 0xe9,
|
||||
0x18, 0x24, 0xcc, 0x68, 0x02, 0xdd, 0x10, 0x9b, 0x3c, 0x1a, 0x5f, 0x30, 0x8a, 0x73, 0x65, 0xd0,
|
||||
0xf2, 0xe8, 0x0c, 0xaa, 0x1f, 0xc0, 0x72, 0xe4, 0x83, 0xbe, 0x01, 0x79, 0x6e, 0x49, 0xe1, 0x96,
|
||||
0xb4, 0xe8, 0x01, 0x15, 0x1a, 0xe0, 0x02, 0x7d, 0x0d, 0x96, 0x06, 0x76, 0x37, 0xc0, 0x9c, 0x87,
|
||||
0x32, 0x12, 0x03, 0xb6, 0x4c, 0x4b, 0x85, 0xce, 0xa1, 0x2f, 0x23, 0x48, 0x4a, 0x5f, 0x3a, 0x4b,
|
||||
0x53, 0x00, 0x2c, 0x44, 0x96, 0xba, 0xb0, 0xc2, 0x93, 0x83, 0x5f, 0x84, 0x5c, 0x21, 0xc9, 0x21,
|
||||
0xe5, 0x1c, 0x39, 0x94, 0x1b, 0x7b, 0xc1, 0xab, 0xe9, 0x0b, 0xde, 0xf8, 0x26, 0xb9, 0xe3, 0xb6,
|
||||
0x6d, 0xda, 0x3e, 0xba, 0xa2, 0x47, 0xcb, 0x03, 0x28, 0x86, 0x3e, 0x3b, 0x58, 0xf8, 0xa3, 0x35,
|
||||
0x6e, 0x47, 0xaa, 0x99, 0xe8, 0x51, 0xa4, 0x37, 0xeb, 0x63, 0x93, 0xbd, 0xaf, 0x6d, 0x32, 0xe2,
|
||||
0xa1, 0x59, 0xb1, 0x49, 0xba, 0x70, 0xfd, 0x94, 0xdc, 0x53, 0x43, 0x38, 0x5c, 0x5a, 0x52, 0xdc,
|
||||
0x87, 0xa2, 0xa0, 0x3c, 0x42, 0x60, 0x54, 0x56, 0x44, 0x2a, 0xc6, 0xd7, 0xb0, 0xc6, 0x81, 0x49,
|
||||
0x8e, 0xe3, 0x05, 0xe6, 0x46, 0xf6, 0xad, 0xa0, 0x9e, 0x7a, 0x2b, 0x18, 0x4f, 0x72, 0x70, 0x37,
|
||||
0x0d, 0xcf, 0x55, 0xbe, 0x87, 0x5e, 0xcd, 0xe6, 0xca, 0x9d, 0xa1, 0x5c, 0xc9, 0x40, 0x72, 0x55,
|
||||
0x09, 0xf3, 0xb3, 0x02, 0x1b, 0x63, 0x11, 0x59, 0x90, 0xac, 0xf9, 0x55, 0x81, 0xb5, 0x3d, 0xea,
|
||||
0x63, 0xbb, 0x37, 0x57, 0xeb, 0x18, 0x27, 0x59, 0xee, 0x7c, 0xfd, 0xa0, 0x3a, 0x25, 0xe2, 0x13,
|
||||
0xee, 0x3e, 0xa3, 0x09, 0xeb, 0x99, 0x08, 0x24, 0xb6, 0x49, 0x51, 0x55, 0xce, 0x2c, 0xaa, 0x7f,
|
||||
0xb3, 0xc3, 0x3d, 0xb4, 0xcb, 0x3c, 0x55, 0x6e, 0x6a, 0x34, 0xd2, 0x61, 0xa9, 0x63, 0xcb, 0x71,
|
||||
0x7e, 0x52, 0xbf, 0xb5, 0x34, 0x1d, 0x82, 0x46, 0x0b, 0x9e, 0x1e, 0x19, 0xdf, 0x0c, 0x58, 0xfd,
|
||||
0xc3, 0xf2, 0x7a, 0x68, 0xaf, 0xb9, 0x8f, 0xfa, 0x85, 0x00, 0x96, 0xad, 0x51, 0xf9, 0x33, 0xfb,
|
||||
0x99, 0x69, 0xb1, 0x7b, 0x0c, 0x9b, 0xe3, 0xe3, 0x9d, 0x01, 0xc0, 0xff, 0x14, 0x78, 0x26, 0xbb,
|
||||
0xe1, 0x3c, 0xad, 0xc5, 0x85, 0xc0, 0x37, 0xdc, 0x2f, 0xe4, 0x67, 0xe8, 0x17, 0xa6, 0x85, 0xf3,
|
||||
0x7d, 0xb8, 0x3b, 0x2e, 0xfa, 0x19, 0xc0, 0x7c, 0x13, 0xca, 0xdb, 0xf8, 0xd0, 0x71, 0x67, 0x82,
|
||||
0xce, 0x78, 0x03, 0x2a, 0x72, 0xb5, 0x34, 0x9d, 0xaa, 0xb4, 0xca, 0xe4, 0x4a, 0x6b, 0x1c, 0x41,
|
||||
0xa5, 0xe9, 0xf5, 0x7a, 0x0e, 0xbd, 0xec, 0xfb, 0xcd, 0x58, 0x85, 0x6a, 0x64, 0x49, 0xb8, 0x69,
|
||||
0x7c, 0x06, 0x2b, 0xc8, 0xeb, 0x76, 0x0f, 0xec, 0xf6, 0xf1, 0xa5, 0x5b, 0xd7, 0x61, 0x35, 0xb1,
|
||||
0x25, 0xed, 0xff, 0x9b, 0x83, 0x1b, 0x7b, 0xfd, 0xae, 0x43, 0x25, 0x25, 0xb3, 0xb8, 0x30, 0xe9,
|
||||
0xc1, 0x31, 0x75, 0x57, 0xc4, 0x4e, 0x3d, 0x09, 0xfd, 0x90, 0x8d, 0x8f, 0x2c, 0x96, 0x1a, 0x9f,
|
||||
0x13, 0x2d, 0x4f, 0xf8, 0xd8, 0x8f, 0x54, 0x02, 0x97, 0xf2, 0x34, 0x55, 0x11, 0x48, 0x0d, 0x36,
|
||||
0xa3, 0xbf, 0x0c, 0xb7, 0xdd, 0xa0, 0x67, 0xf9, 0xde, 0x17, 0xc4, 0xea, 0x33, 0xe7, 0xf9, 0xce,
|
||||
0x56, 0xdf, 0xf6, 0x29, 0xef, 0x81, 0x55, 0x74, 0x93, 0x89, 0x11, 0x93, 0xee, 0x62, 0x9f, 0x1b,
|
||||
0xdf, 0x65, 0x22, 0xfd, 0x6d, 0x28, 0xd9, 0xdd, 0x43, 0xcf, 0x77, 0xe8, 0x51, 0x4f, 0x76, 0x3a,
|
||||
0x86, 0x74, 0xf3, 0x14, 0x32, 0xe6, 0x3b, 0x91, 0x26, 0x4a, 0x16, 0xe9, 0x2f, 0x81, 0x1e, 0x10,
|
||||
0x6c, 0x09, 0xe7, 0x84, 0xd1, 0x41, 0x43, 0xb6, 0x3d, 0x2b, 0x4c, 0x92, 0x6c, 0xf3, 0x51, 0xc3,
|
||||
0xf8, 0x5d, 0x05, 0x3d, 0xbd, 0xaf, 0xcc, 0xd7, 0xd7, 0xd8, 0x35, 0x11, 0xce, 0x12, 0x86, 0x77,
|
||||
0x78, 0x64, 0x37, 0x62, 0x1a, 0x4f, 0xe9, 0x9a, 0xa1, 0xdb, 0x48, 0xaa, 0xd7, 0x3f, 0x85, 0x72,
|
||||
0x74, 0xf0, 0x78, 0x38, 0x69, 0x36, 0x94, 0x89, 0xb5, 0x21, 0x37, 0x45, 0x6d, 0xa8, 0xbf, 0x05,
|
||||
0x25, 0x7e, 0xc5, 0x9c, 0xb9, 0x77, 0x72, 0xcf, 0xe5, 0xd2, 0xf7, 0x5c, 0xfd, 0x2f, 0x05, 0xf2,
|
||||
0x7c, 0xf1, 0xd4, 0x0f, 0xd8, 0x0f, 0xa0, 0x1a, 0x7b, 0x29, 0xd8, 0x13, 0x99, 0x7d, 0x6f, 0x02,
|
||||
0x24, 0x69, 0x08, 0x50, 0xf9, 0x38, 0x0d, 0x48, 0x13, 0x40, 0xfc, 0xcb, 0x9f, 0x6f, 0x25, 0xf2,
|
||||
0xf0, 0xb9, 0x09, 0x5b, 0xc5, 0xe1, 0xa2, 0x12, 0x89, 0x23, 0xd7, 0x21, 0x4f, 0x9c, 0xaf, 0xc4,
|
||||
0xa3, 0x45, 0x45, 0xfc, 0xdb, 0x78, 0x08, 0xeb, 0xef, 0x61, 0xba, 0xe7, 0x0f, 0xa2, 0x7b, 0x24,
|
||||
0x3a, 0x3e, 0x13, 0x60, 0x32, 0x10, 0xdc, 0xca, 0x2e, 0x92, 0x19, 0xf0, 0x3a, 0x3b, 0x01, 0xfe,
|
||||
0xc0, 0x1a, 0x5a, 0xa9, 0x35, 0xd6, 0x13, 0x7a, 0xd2, 0x8b, 0x34, 0x92, 0x0c, 0xb6, 0xeb, 0x50,
|
||||
0x6b, 0x7b, 0x3d, 0xf3, 0xc4, 0x0b, 0x68, 0x70, 0x80, 0xcd, 0x81, 0x43, 0xd9, 0x89, 0x17, 0xbf,
|
||||
0x91, 0x1c, 0x14, 0xf8, 0x9f, 0x87, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x12, 0x77, 0x8b, 0xc2,
|
||||
0x6c, 0x19, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ type fakeVTGateService struct {
|
|||
type queryExecute struct {
|
||||
SQL string
|
||||
BindVariables map[string]interface{}
|
||||
Keyspace string
|
||||
TabletType topodatapb.TabletType
|
||||
Session *vtgatepb.Session
|
||||
NotInTransaction bool
|
||||
|
@ -36,7 +37,7 @@ type queryExecuteSpecificShard struct {
|
|||
}
|
||||
|
||||
// Execute is part of the VTGateService interface
|
||||
func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
execCase, ok := execMap[sql]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no match for: %s", sql)
|
||||
|
@ -44,6 +45,7 @@ func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariabl
|
|||
query := &queryExecute{
|
||||
SQL: sql,
|
||||
BindVariables: bindVariables,
|
||||
Keyspace: keyspace,
|
||||
TabletType: tabletType,
|
||||
Session: session,
|
||||
NotInTransaction: notInTransaction,
|
||||
|
@ -109,7 +111,7 @@ func (f *fakeVTGateService) ExecuteBatchKeyspaceIds(ctx context.Context, queries
|
|||
}
|
||||
|
||||
// StreamExecute is part of the VTGateService interface
|
||||
func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
execCase, ok := execMap[sql]
|
||||
if !ok {
|
||||
return fmt.Errorf("no match for: %s", sql)
|
||||
|
@ -117,6 +119,7 @@ func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindV
|
|||
query := &queryExecute{
|
||||
SQL: sql,
|
||||
BindVariables: bindVariables,
|
||||
Keyspace: keyspace,
|
||||
TabletType: tabletType,
|
||||
}
|
||||
if !reflect.DeepEqual(query, execCase.execQuery) {
|
||||
|
|
|
@ -37,7 +37,7 @@ func (vtg *VTGate) Execute(ctx context.Context, request *vtgatepb.ExecuteRequest
|
|||
if err != nil {
|
||||
return nil, vterrors.ToGRPCError(err)
|
||||
}
|
||||
result, err := vtg.server.Execute(ctx, string(request.Query.Sql), bv, request.TabletType, request.Session, request.NotInTransaction)
|
||||
result, err := vtg.server.Execute(ctx, string(request.Query.Sql), bv, request.Keyspace, request.TabletType, request.Session, request.NotInTransaction)
|
||||
return &vtgatepb.ExecuteResponse{
|
||||
Result: sqltypes.ResultToProto3(result),
|
||||
Session: request.Session,
|
||||
|
@ -196,6 +196,7 @@ func (vtg *VTGate) StreamExecute(request *vtgatepb.StreamExecuteRequest, stream
|
|||
vtgErr := vtg.server.StreamExecute(ctx,
|
||||
string(request.Query.Sql),
|
||||
bv,
|
||||
request.Keyspace,
|
||||
request.TabletType,
|
||||
func(value *sqltypes.Result) error {
|
||||
return stream.Send(&vtgatepb.StreamExecuteResponse{
|
||||
|
|
|
@ -68,9 +68,15 @@ type builder interface {
|
|||
SupplyCol(ref colref) int
|
||||
}
|
||||
|
||||
// VSchema defines the interface for this package to fetch
|
||||
// info about tables.
|
||||
type VSchema interface {
|
||||
Find(keyspace, tablename string) (table *vindexes.Table, err error)
|
||||
}
|
||||
|
||||
// Build builds a plan for a query based on the specified vschema.
|
||||
// It's the main entry point for this package.
|
||||
func Build(query string, vschema *vindexes.VSchema) (*engine.Plan, error) {
|
||||
func Build(query string, vschema VSchema) (*engine.Plan, error) {
|
||||
statement, err := sqlparser.Parse(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -14,15 +14,23 @@ import (
|
|||
"github.com/youtube/vitess/go/vt/vtgate/vindexes"
|
||||
)
|
||||
|
||||
// dmlFormatter strips out keyspace name from dmls.
|
||||
func dmlFormatter(buf *sqlparser.TrackedBuffer, node sqlparser.SQLNode) {
|
||||
switch node := node.(type) {
|
||||
case *sqlparser.TableName:
|
||||
node.Name.Format(buf)
|
||||
return
|
||||
}
|
||||
node.Format(buf)
|
||||
}
|
||||
|
||||
// buildUpdatePlan builds the instructions for an UPDATE statement.
|
||||
func buildUpdatePlan(upd *sqlparser.Update, vschema *vindexes.VSchema) (*engine.Route, error) {
|
||||
func buildUpdatePlan(upd *sqlparser.Update, vschema VSchema) (*engine.Route, error) {
|
||||
route := &engine.Route{
|
||||
Query: generateQuery(upd),
|
||||
}
|
||||
// We allow only one table in an update.
|
||||
tablename := sqlparser.GetTableName(upd.Table)
|
||||
var err error
|
||||
route.Table, err = vschema.FindTable(tablename)
|
||||
route.Table, err = vschema.Find(string(upd.Table.Qualifier), string(upd.Table.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -47,7 +55,7 @@ func buildUpdatePlan(upd *sqlparser.Update, vschema *vindexes.VSchema) (*engine.
|
|||
}
|
||||
|
||||
func generateQuery(statement sqlparser.Statement) string {
|
||||
buf := sqlparser.NewTrackedBuffer(nil)
|
||||
buf := sqlparser.NewTrackedBuffer(dmlFormatter)
|
||||
statement.Format(buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
@ -68,14 +76,12 @@ func isIndexChanging(setClauses sqlparser.UpdateExprs, colVindexes []*vindexes.C
|
|||
}
|
||||
|
||||
// buildUpdatePlan builds the instructions for a DELETE statement.
|
||||
func buildDeletePlan(del *sqlparser.Delete, vschema *vindexes.VSchema) (*engine.Route, error) {
|
||||
func buildDeletePlan(del *sqlparser.Delete, vschema VSchema) (*engine.Route, error) {
|
||||
route := &engine.Route{
|
||||
Query: generateQuery(del),
|
||||
}
|
||||
// We allow only one table in a delete.
|
||||
tablename := sqlparser.GetTableName(del.Table)
|
||||
var err error
|
||||
route.Table, err = vschema.FindTable(tablename)
|
||||
route.Table, err = vschema.Find(string(del.Table.Qualifier), string(del.Table.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,12 +13,11 @@ import (
|
|||
"github.com/youtube/vitess/go/vt/vtgate/vindexes"
|
||||
)
|
||||
|
||||
// This file has functions to analyze the FROM clause
|
||||
// for select statements.
|
||||
// This file has functions to analyze the FROM clause.
|
||||
|
||||
// processTableExprs analyzes the FROM clause. It produces a builder
|
||||
// with all the routes identified.
|
||||
func processTableExprs(tableExprs sqlparser.TableExprs, vschema *vindexes.VSchema) (builder, error) {
|
||||
func processTableExprs(tableExprs sqlparser.TableExprs, vschema VSchema) (builder, error) {
|
||||
if len(tableExprs) != 1 {
|
||||
return nil, errors.New("unsupported: ',' join operator")
|
||||
}
|
||||
|
@ -26,7 +25,7 @@ func processTableExprs(tableExprs sqlparser.TableExprs, vschema *vindexes.VSchem
|
|||
}
|
||||
|
||||
// processTableExpr produces a builder subtree for the given TableExpr.
|
||||
func processTableExpr(tableExpr sqlparser.TableExpr, vschema *vindexes.VSchema) (builder, error) {
|
||||
func processTableExpr(tableExpr sqlparser.TableExpr, vschema VSchema) (builder, error) {
|
||||
switch tableExpr := tableExpr.(type) {
|
||||
case *sqlparser.AliasedTableExpr:
|
||||
return processAliasedTable(tableExpr, vschema)
|
||||
|
@ -55,7 +54,7 @@ func processTableExpr(tableExpr sqlparser.TableExpr, vschema *vindexes.VSchema)
|
|||
// vindex columns will be added to the tabsym.
|
||||
// A symtab symbol can only point to a route. This means that we canoot
|
||||
// support complex joins in subqueries yet.
|
||||
func processAliasedTable(tableExpr *sqlparser.AliasedTableExpr, vschema *vindexes.VSchema) (builder, error) {
|
||||
func processAliasedTable(tableExpr *sqlparser.AliasedTableExpr, vschema VSchema) (builder, error) {
|
||||
switch expr := tableExpr.Expr.(type) {
|
||||
case *sqlparser.TableName:
|
||||
eroute, table, err := getTablePlan(expr, vschema)
|
||||
|
@ -118,8 +117,8 @@ func processAliasedTable(tableExpr *sqlparser.AliasedTableExpr, vschema *vindexe
|
|||
// getTablePlan produces the initial engine.Route for the specified TableName.
|
||||
// It also returns the associated vschema info (*Table) so that
|
||||
// it can be used to create the symbol table entry.
|
||||
func getTablePlan(tableName *sqlparser.TableName, vschema *vindexes.VSchema) (*engine.Route, *vindexes.Table, error) {
|
||||
table, err := vschema.FindTable(string(tableName.Name))
|
||||
func getTablePlan(tableName *sqlparser.TableName, vschema VSchema) (*engine.Route, *vindexes.Table, error) {
|
||||
table, err := vschema.Find(string(tableName.Qualifier), string(tableName.Name))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -140,7 +139,7 @@ func getTablePlan(tableName *sqlparser.TableName, vschema *vindexes.VSchema) (*e
|
|||
// processJoin produces a builder subtree for the given Join.
|
||||
// If the left and right nodes can be part of the same route,
|
||||
// then it's a route. Otherwise, it's a join.
|
||||
func processJoin(ajoin *sqlparser.JoinTableExpr, vschema *vindexes.VSchema) (builder, error) {
|
||||
func processJoin(ajoin *sqlparser.JoinTableExpr, vschema VSchema) (builder, error) {
|
||||
switch ajoin.Join {
|
||||
case sqlparser.JoinStr, sqlparser.StraightJoinStr, sqlparser.LeftJoinStr:
|
||||
case sqlparser.RightJoinStr:
|
||||
|
|
|
@ -14,13 +14,12 @@ import (
|
|||
)
|
||||
|
||||
// buildInsertPlan builds the route for an INSERT statement.
|
||||
func buildInsertPlan(ins *sqlparser.Insert, vschema *vindexes.VSchema) (*engine.Route, error) {
|
||||
func buildInsertPlan(ins *sqlparser.Insert, vschema VSchema) (*engine.Route, error) {
|
||||
route := &engine.Route{
|
||||
Query: generateQuery(ins),
|
||||
}
|
||||
tablename := sqlparser.GetTableName(ins.Table)
|
||||
var err error
|
||||
route.Table, err = vschema.FindTable(tablename)
|
||||
route.Table, err = vschema.Find(string(ins.Table.Qualifier), string(ins.Table.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ type route struct {
|
|||
ERoute *engine.Route
|
||||
}
|
||||
|
||||
func newRoute(from sqlparser.TableExprs, eroute *engine.Route, table *vindexes.Table, vschema *vindexes.VSchema, alias, astName sqlparser.SQLName) *route {
|
||||
func newRoute(from sqlparser.TableExprs, eroute *engine.Route, table *vindexes.Table, vschema VSchema, alias, astName sqlparser.SQLName) *route {
|
||||
// We have some circular pointer references here:
|
||||
// The route points to the symtab idicating
|
||||
// the symtab that should be used to resolve symbols
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// buildSelectPlan is the new function to build a Select plan.
|
||||
func buildSelectPlan(sel *sqlparser.Select, vschema *vindexes.VSchema) (primitive engine.Primitive, err error) {
|
||||
func buildSelectPlan(sel *sqlparser.Select, vschema VSchema) (primitive engine.Primitive, err error) {
|
||||
bindvars := getBindvars(sel)
|
||||
builder, err := processSelect(sel, vschema, nil)
|
||||
if err != nil {
|
||||
|
@ -43,7 +43,7 @@ func getBindvars(node sqlparser.SQLNode) map[string]struct{} {
|
|||
}
|
||||
|
||||
// processSelect builds a primitive tree for the given query or subquery.
|
||||
func processSelect(sel *sqlparser.Select, vschema *vindexes.VSchema, outer builder) (builder, error) {
|
||||
func processSelect(sel *sqlparser.Select, vschema VSchema, outer builder) (builder, error) {
|
||||
bldr, err := processTableExprs(sel.From, vschema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -50,12 +50,12 @@ type symtab struct {
|
|||
Colsyms []*colsym
|
||||
Externs []*sqlparser.ColName
|
||||
Outer *symtab
|
||||
VSchema *vindexes.VSchema
|
||||
VSchema VSchema
|
||||
}
|
||||
|
||||
// newSymtab creates a new symtab initialized
|
||||
// to contain the provided table alias.
|
||||
func newSymtab(vschema *vindexes.VSchema) *symtab {
|
||||
func newSymtab(vschema VSchema) *symtab {
|
||||
return &symtab{
|
||||
VSchema: vschema,
|
||||
}
|
||||
|
|
|
@ -45,14 +45,21 @@ func NewPlanner(vschema *vindexes.VSchema, cacheSize int) *Planner {
|
|||
|
||||
// GetPlan computes the plan for the given query. If one is in
|
||||
// the cache, it reuses it.
|
||||
func (plr *Planner) GetPlan(sql string) (*engine.Plan, error) {
|
||||
func (plr *Planner) GetPlan(sql, keyspace string) (*engine.Plan, error) {
|
||||
if plr.vschema == nil {
|
||||
return nil, errors.New("vschema not initialized")
|
||||
}
|
||||
if result, ok := plr.plans.Get(sql); ok {
|
||||
key := sql
|
||||
if keyspace != "" {
|
||||
key = keyspace + ":" + sql
|
||||
}
|
||||
if result, ok := plr.plans.Get(key); ok {
|
||||
return result.(*engine.Plan), nil
|
||||
}
|
||||
plan, err := planbuilder.Build(sql, plr.vschema)
|
||||
plan, err := planbuilder.Build(sql, &wrappedVSchema{
|
||||
vschema: plr.vschema,
|
||||
keyspace: keyspace,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -95,3 +102,15 @@ func (plr *Planner) ServeHTTP(response http.ResponseWriter, request *http.Reques
|
|||
response.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
type wrappedVSchema struct {
|
||||
vschema *vindexes.VSchema
|
||||
keyspace string
|
||||
}
|
||||
|
||||
func (vs *wrappedVSchema) Find(keyspace, tablename string) (table *vindexes.Table, err error) {
|
||||
if keyspace == "" {
|
||||
keyspace = vs.keyspace
|
||||
}
|
||||
return vs.vschema.Find(keyspace, tablename)
|
||||
}
|
||||
|
|
|
@ -17,17 +17,19 @@ type requestContext struct {
|
|||
ctx context.Context
|
||||
sql string
|
||||
bindVars map[string]interface{}
|
||||
keyspace string
|
||||
tabletType topodatapb.TabletType
|
||||
session *vtgatepb.Session
|
||||
notInTransaction bool
|
||||
router *Router
|
||||
}
|
||||
|
||||
func newRequestContext(ctx context.Context, sql string, bindVars map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool, router *Router) *requestContext {
|
||||
func newRequestContext(ctx context.Context, sql string, bindVars map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool, router *Router) *requestContext {
|
||||
return &requestContext{
|
||||
ctx: ctx,
|
||||
sql: sql,
|
||||
bindVars: bindVars,
|
||||
keyspace: keyspace,
|
||||
tabletType: tabletType,
|
||||
session: session,
|
||||
notInTransaction: notInTransaction,
|
||||
|
@ -36,7 +38,9 @@ func newRequestContext(ctx context.Context, sql string, bindVars map[string]inte
|
|||
}
|
||||
|
||||
func (vc *requestContext) Execute(query string, bindvars map[string]interface{}) (*sqltypes.Result, error) {
|
||||
return vc.router.Execute(vc.ctx, query, bindvars, vc.tabletType, vc.session, false)
|
||||
// We have to use an empty keyspace here, becasue vindexes that call back can reference
|
||||
// any table.
|
||||
return vc.router.Execute(vc.ctx, query, bindvars, "", vc.tabletType, vc.session, false)
|
||||
}
|
||||
|
||||
func (vc *requestContext) ExecuteRoute(route *engine.Route, joinvars map[string]interface{}) (*sqltypes.Result, error) {
|
||||
|
|
|
@ -59,12 +59,12 @@ func NewRouter(serv topo.SrvTopoServer, cell string, vschema *vindexes.VSchema,
|
|||
}
|
||||
|
||||
// Execute routes a non-streaming query.
|
||||
func (rtr *Router) Execute(ctx context.Context, sql string, bindVars map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (rtr *Router) Execute(ctx context.Context, sql string, bindVars map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if bindVars == nil {
|
||||
bindVars = make(map[string]interface{})
|
||||
}
|
||||
vcursor := newRequestContext(ctx, sql, bindVars, tabletType, session, notInTransaction, rtr)
|
||||
plan, err := rtr.planner.GetPlan(sql)
|
||||
vcursor := newRequestContext(ctx, sql, bindVars, keyspace, tabletType, session, notInTransaction, rtr)
|
||||
plan, err := rtr.planner.GetPlan(sql, keyspace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -72,12 +72,12 @@ func (rtr *Router) Execute(ctx context.Context, sql string, bindVars map[string]
|
|||
}
|
||||
|
||||
// StreamExecute executes a streaming query.
|
||||
func (rtr *Router) StreamExecute(ctx context.Context, sql string, bindVars map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (rtr *Router) StreamExecute(ctx context.Context, sql string, bindVars map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
if bindVars == nil {
|
||||
bindVars = make(map[string]interface{})
|
||||
}
|
||||
vcursor := newRequestContext(ctx, sql, bindVars, tabletType, nil, false, rtr)
|
||||
plan, err := rtr.planner.GetPlan(sql)
|
||||
vcursor := newRequestContext(ctx, sql, bindVars, keyspace, tabletType, nil, false, rtr)
|
||||
plan, err := rtr.planner.GetPlan(sql, keyspace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ var routerVSchema = createTestVSchema(`
|
|||
"Type": "numeric"
|
||||
}
|
||||
},
|
||||
"Classes": {
|
||||
"Tables": {
|
||||
"user": {
|
||||
"ColVindexes": [
|
||||
{
|
||||
|
@ -67,10 +67,10 @@ var routerVSchema = createTestVSchema(`
|
|||
"Name": "name_user_map"
|
||||
}
|
||||
],
|
||||
"Autoinc" : {
|
||||
"Col": "id",
|
||||
"Sequence": "user_seq"
|
||||
}
|
||||
"Autoinc" : {
|
||||
"Col": "id",
|
||||
"Sequence": "user_seq"
|
||||
}
|
||||
},
|
||||
"user_extra": {
|
||||
"ColVindexes": [
|
||||
|
@ -91,10 +91,10 @@ var routerVSchema = createTestVSchema(`
|
|||
"Name": "music_user_map"
|
||||
}
|
||||
],
|
||||
"Autoinc" : {
|
||||
"Col": "id",
|
||||
"Sequence": "user_seq"
|
||||
}
|
||||
"Autoinc" : {
|
||||
"Col": "id",
|
||||
"Sequence": "user_seq"
|
||||
}
|
||||
},
|
||||
"music_extra": {
|
||||
"ColVindexes": [
|
||||
|
@ -136,34 +136,22 @@ var routerVSchema = createTestVSchema(`
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"user": "user",
|
||||
"user_extra": "user_extra",
|
||||
"music": "music",
|
||||
"music_extra": "music_extra",
|
||||
"music_extra_reversed": "music_extra_reversed",
|
||||
"noauto_table": "noauto_table",
|
||||
"ksid_table": "ksid_table"
|
||||
}
|
||||
},
|
||||
"TestBadSharding": {
|
||||
"Sharded": false,
|
||||
"Tables": {
|
||||
"sharded_table": ""
|
||||
"sharded_table": {}
|
||||
}
|
||||
},
|
||||
"TestUnsharded": {
|
||||
"Sharded": false,
|
||||
"Classes": {
|
||||
"seq": {
|
||||
"Type": "Sequence"
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"user_seq": "seq",
|
||||
"music_user_map": "",
|
||||
"name_user_map": ""
|
||||
"user_seq": {
|
||||
"Type": "Sequence"
|
||||
},
|
||||
"music_user_map": {},
|
||||
"name_user_map": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,6 +203,7 @@ func routerExec(router *Router, sql string, bv map[string]interface{}) (*sqltype
|
|||
return router.Execute(context.Background(),
|
||||
sql,
|
||||
bv,
|
||||
"",
|
||||
topodatapb.TabletType_MASTER,
|
||||
nil,
|
||||
false)
|
||||
|
@ -222,7 +211,7 @@ func routerExec(router *Router, sql string, bv map[string]interface{}) (*sqltype
|
|||
|
||||
func routerStream(router *Router, sql string) (qr *sqltypes.Result, err error) {
|
||||
results := make(chan *sqltypes.Result, 10)
|
||||
err = router.StreamExecute(context.Background(), sql, nil, topodatapb.TabletType_MASTER, func(qr *sqltypes.Result) error {
|
||||
err = router.StreamExecute(context.Background(), sql, nil, "", topodatapb.TabletType_MASTER, func(qr *sqltypes.Result) error {
|
||||
results <- qr
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -6,7 +6,6 @@ package vindexes
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
|
@ -48,8 +47,8 @@ type ColVindex struct {
|
|||
|
||||
// KeyspaceSchema contains the schema(table) for a keyspace.
|
||||
type KeyspaceSchema struct {
|
||||
Sharded bool
|
||||
Tables map[string]*Table
|
||||
Keyspace *Keyspace
|
||||
Tables map[string]*Table
|
||||
}
|
||||
|
||||
// Autoinc contains the auto-inc information for a table.
|
||||
|
@ -67,67 +66,58 @@ func BuildVSchema(source *VSchemaFormal) (vschema *VSchema, err error) {
|
|||
tables: make(map[string]*Table),
|
||||
Keyspaces: make(map[string]*KeyspaceSchema),
|
||||
}
|
||||
keyspaces := buildKeyspaces(source, vschema)
|
||||
buildKeyspaces(source, vschema)
|
||||
// We have to build the sequences first to avoid
|
||||
// forward reference errors.
|
||||
err = buildSequences(source, vschema, keyspaces)
|
||||
err = buildSequences(source, vschema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = buildTables(source, vschema, keyspaces)
|
||||
err = buildTables(source, vschema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return vschema, nil
|
||||
}
|
||||
|
||||
func buildKeyspaces(source *VSchemaFormal, vschema *VSchema) map[string]*Keyspace {
|
||||
k := make(map[string]*Keyspace)
|
||||
func buildKeyspaces(source *VSchemaFormal, vschema *VSchema) {
|
||||
for ksname, ks := range source.Keyspaces {
|
||||
k[ksname] = &Keyspace{
|
||||
Name: ksname,
|
||||
Sharded: ks.Sharded,
|
||||
}
|
||||
vschema.Keyspaces[ksname] = &KeyspaceSchema{
|
||||
Sharded: ks.Sharded,
|
||||
Tables: make(map[string]*Table),
|
||||
Keyspace: &Keyspace{
|
||||
Name: ksname,
|
||||
Sharded: ks.Sharded,
|
||||
},
|
||||
Tables: make(map[string]*Table),
|
||||
}
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
func buildSequences(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*Keyspace) error {
|
||||
func buildSequences(source *VSchemaFormal, vschema *VSchema) error {
|
||||
for ksname, ks := range source.Keyspaces {
|
||||
keyspace := keyspaces[ksname]
|
||||
for tname, cname := range ks.Tables {
|
||||
if cname == "" {
|
||||
keyspace := vschema.Keyspaces[ksname].Keyspace
|
||||
for tname, table := range ks.Tables {
|
||||
if table.Type != "Sequence" {
|
||||
continue
|
||||
}
|
||||
class, ok := ks.Classes[cname]
|
||||
if !ok {
|
||||
return fmt.Errorf("class %s not found for table %s", cname, tname)
|
||||
t := &Table{
|
||||
Name: tname,
|
||||
Keyspace: keyspace,
|
||||
IsSequence: true,
|
||||
}
|
||||
if class.Type == "Sequence" {
|
||||
t := &Table{
|
||||
Name: tname,
|
||||
Keyspace: keyspace,
|
||||
IsSequence: true,
|
||||
}
|
||||
if _, ok := vschema.tables[tname]; ok {
|
||||
vschema.tables[tname] = nil
|
||||
} else {
|
||||
vschema.tables[tname] = t
|
||||
}
|
||||
vschema.Keyspaces[ksname].Tables[tname] = t
|
||||
if _, ok := vschema.tables[tname]; ok {
|
||||
vschema.tables[tname] = nil
|
||||
} else {
|
||||
vschema.tables[tname] = t
|
||||
}
|
||||
vschema.Keyspaces[ksname].Tables[tname] = t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*Keyspace) error {
|
||||
func buildTables(source *VSchemaFormal, vschema *VSchema) error {
|
||||
for ksname, ks := range source.Keyspaces {
|
||||
keyspace := keyspaces[ksname]
|
||||
keyspace := vschema.Keyspaces[ksname].Keyspace
|
||||
vindexes := make(map[string]Vindex)
|
||||
for vname, vindexInfo := range ks.Vindexes {
|
||||
vindex, err := CreateVindex(vindexInfo.Type, vname, vindexInfo.Params)
|
||||
|
@ -142,12 +132,8 @@ func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*
|
|||
}
|
||||
vindexes[vname] = vindex
|
||||
}
|
||||
for tname, cname := range ks.Tables {
|
||||
class, ok := ks.Classes[cname]
|
||||
if !ok && cname != "" {
|
||||
return fmt.Errorf("class %s not found for table %s", cname, tname)
|
||||
}
|
||||
if class.Type == "Sequence" {
|
||||
for tname, table := range ks.Tables {
|
||||
if table.Type == "Sequence" {
|
||||
continue
|
||||
}
|
||||
t := &Table{
|
||||
|
@ -163,10 +149,10 @@ func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*
|
|||
if !keyspace.Sharded {
|
||||
continue
|
||||
}
|
||||
for i, ind := range class.ColVindexes {
|
||||
for i, ind := range table.ColVindexes {
|
||||
vindexInfo, ok := ks.Vindexes[ind.Name]
|
||||
if !ok {
|
||||
return fmt.Errorf("vindex %s not found for class %s", ind.Name, cname)
|
||||
return fmt.Errorf("vindex %s not found for table %s", ind.Name, tname)
|
||||
}
|
||||
vindex := vindexes[ind.Name]
|
||||
owned := false
|
||||
|
@ -183,10 +169,10 @@ func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*
|
|||
if i == 0 {
|
||||
// Perform Primary vindex check.
|
||||
if _, ok := columnVindex.Vindex.(Unique); !ok {
|
||||
return fmt.Errorf("primary vindex %s is not Unique for class %s", ind.Name, cname)
|
||||
return fmt.Errorf("primary vindex %s is not Unique for table %s", ind.Name, tname)
|
||||
}
|
||||
if owned {
|
||||
return fmt.Errorf("primary vindex %s cannot be owned for class %s", ind.Name, cname)
|
||||
return fmt.Errorf("primary vindex %s cannot be owned for table %s", ind.Name, tname)
|
||||
}
|
||||
}
|
||||
t.ColVindexes = append(t.ColVindexes, columnVindex)
|
||||
|
@ -195,11 +181,11 @@ func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*
|
|||
}
|
||||
}
|
||||
t.Ordered = colVindexSorted(t.ColVindexes)
|
||||
if class.Autoinc != nil {
|
||||
t.Autoinc = &Autoinc{Col: class.Autoinc.Col, ColVindexNum: -1}
|
||||
seq, ok := vschema.tables[class.Autoinc.Sequence]
|
||||
if table.Autoinc != nil {
|
||||
t.Autoinc = &Autoinc{Col: table.Autoinc.Col, ColVindexNum: -1}
|
||||
seq, ok := vschema.tables[table.Autoinc.Sequence]
|
||||
if !ok {
|
||||
return fmt.Errorf("sequence %s not found for class %s", class.Autoinc.Sequence, cname)
|
||||
return fmt.Errorf("sequence %s not found for table %s", table.Autoinc.Sequence, tname)
|
||||
}
|
||||
t.Autoinc.Sequence = seq
|
||||
for i, cv := range t.ColVindexes {
|
||||
|
@ -214,18 +200,43 @@ func buildTables(source *VSchemaFormal, vschema *VSchema, keyspaces map[string]*
|
|||
return nil
|
||||
}
|
||||
|
||||
// FindTable returns a pointer to the Table if found.
|
||||
// Otherwise, it returns a reason, which is equivalent to an error.
|
||||
func (vschema *VSchema) FindTable(tablename string) (table *Table, err error) {
|
||||
if tablename == "" {
|
||||
return nil, errors.New("unsupported: compex table expression in DML")
|
||||
}
|
||||
table, ok := vschema.tables[tablename]
|
||||
if table == nil {
|
||||
if ok {
|
||||
return nil, fmt.Errorf("ambiguous table reference: %s", tablename)
|
||||
// Find returns a pointer to the Table. If a keyspace is specified, only tables
|
||||
// from that keyspace are searched. If the specified keyspace is unsharded
|
||||
// and no tables matched, it's considered valid: Find will construct a table
|
||||
// of that name and return it. If no kesypace is specified, then a table is returned
|
||||
// only if its name is unique across all keyspaces. If there is only one
|
||||
// keyspace in the vschema, and it's unsharded, then all table requests are considered
|
||||
// valid and belonging to that keyspace.
|
||||
func (vschema *VSchema) Find(keyspace, tablename string) (table *Table, err error) {
|
||||
if keyspace == "" {
|
||||
table, ok := vschema.tables[tablename]
|
||||
if table == nil {
|
||||
if ok {
|
||||
return nil, fmt.Errorf("ambiguous table reference: %s", tablename)
|
||||
}
|
||||
if len(vschema.Keyspaces) != 1 {
|
||||
return nil, fmt.Errorf("table %s not found", tablename)
|
||||
}
|
||||
// Loop happens only once.
|
||||
for _, ks := range vschema.Keyspaces {
|
||||
if ks.Keyspace.Sharded {
|
||||
return nil, fmt.Errorf("table %s not found", tablename)
|
||||
}
|
||||
return &Table{Name: tablename, Keyspace: ks.Keyspace}, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("table %s not found", tablename)
|
||||
return table, nil
|
||||
}
|
||||
ks, ok := vschema.Keyspaces[keyspace]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("keyspace %s not found in vschema", keyspace)
|
||||
}
|
||||
table = ks.Tables[tablename]
|
||||
if table == nil {
|
||||
if ks.Keyspace.Sharded {
|
||||
return nil, fmt.Errorf("table %s not found", tablename)
|
||||
}
|
||||
return &Table{Name: tablename, Keyspace: ks.Keyspace}, nil
|
||||
}
|
||||
return table, nil
|
||||
}
|
||||
|
@ -257,8 +268,7 @@ type VSchemaFormal struct {
|
|||
type KeyspaceFormal struct {
|
||||
Sharded bool
|
||||
Vindexes map[string]VindexFormal
|
||||
Classes map[string]ClassFormal
|
||||
Tables map[string]string
|
||||
Tables map[string]TableFormal
|
||||
}
|
||||
|
||||
// VindexFormal is the info for each index as loaded from
|
||||
|
@ -269,9 +279,9 @@ type VindexFormal struct {
|
|||
Owner string
|
||||
}
|
||||
|
||||
// ClassFormal is the info for each table class as loaded from
|
||||
// TableFormal is the info for each table as loaded from
|
||||
// the source.
|
||||
type ClassFormal struct {
|
||||
type TableFormal struct {
|
||||
Type string
|
||||
ColVindexes []ColVindexFormal
|
||||
Autoinc *AutoincFormal
|
||||
|
|
|
@ -85,8 +85,8 @@ func TestUnshardedVSchema(t *testing.T) {
|
|||
good := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"unsharded": {
|
||||
Tables: map[string]string{
|
||||
"t1": "",
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -95,11 +95,12 @@ func TestUnshardedVSchema(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
ks := &Keyspace{
|
||||
Name: "unsharded",
|
||||
}
|
||||
t1 := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "unsharded",
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ks,
|
||||
}
|
||||
want := &VSchema{
|
||||
tables: map[string]*Table{
|
||||
|
@ -107,6 +108,7 @@ func TestUnshardedVSchema(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"unsharded": {
|
||||
Keyspace: ks,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1,
|
||||
},
|
||||
|
@ -136,7 +138,7 @@ func TestShardedVSchemaOwned(t *testing.T) {
|
|||
Owner: "t1",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -149,9 +151,6 @@ func TestShardedVSchemaOwned(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -159,12 +158,13 @@ func TestShardedVSchemaOwned(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
ks := &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
}
|
||||
t1 := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ks,
|
||||
ColVindexes: []*ColVindex{
|
||||
{
|
||||
Col: "c1",
|
||||
|
@ -197,7 +197,7 @@ func TestShardedVSchemaOwned(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
Keyspace: ks,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1,
|
||||
},
|
||||
|
@ -226,7 +226,7 @@ func TestShardedVSchemaNotOwned(t *testing.T) {
|
|||
Owner: "",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -239,9 +239,6 @@ func TestShardedVSchemaNotOwned(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -249,12 +246,13 @@ func TestShardedVSchemaNotOwned(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
ks := &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
}
|
||||
t1 := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ks,
|
||||
ColVindexes: []*ColVindex{
|
||||
{
|
||||
Col: "c1",
|
||||
|
@ -282,7 +280,7 @@ func TestShardedVSchemaNotOwned(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
Keyspace: ks,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1,
|
||||
},
|
||||
|
@ -308,39 +306,6 @@ func TestLoadVSchemaFail(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBuildVSchemaClassNotFoundFail(t *testing.T) {
|
||||
bad := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
Vindexes: map[string]VindexFormal{
|
||||
"stfu": {
|
||||
Type: "stfu",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
"notexist": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
Col: "c1",
|
||||
Name: "noexist",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := BuildVSchema(&bad)
|
||||
want := "class t1 not found for table t1"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("BuildVSchema: %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildVSchemaVindexNotFoundFail(t *testing.T) {
|
||||
bad := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
|
@ -351,7 +316,7 @@ func TestBuildVSchemaVindexNotFoundFail(t *testing.T) {
|
|||
Type: "noexist",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -361,9 +326,6 @@ func TestBuildVSchemaVindexNotFoundFail(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -384,7 +346,7 @@ func TestBuildVSchemaInvalidVindexFail(t *testing.T) {
|
|||
Type: "stf",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -394,9 +356,6 @@ func TestBuildVSchemaInvalidVindexFail(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -411,40 +370,36 @@ func TestBuildVSchemaDupSeq(t *testing.T) {
|
|||
good := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"ksa": {
|
||||
Classes: map[string]ClassFormal{
|
||||
"seq": {
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
Type: "Sequence",
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "seq",
|
||||
},
|
||||
},
|
||||
"ksb": {
|
||||
Classes: map[string]ClassFormal{
|
||||
"seq": {
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
Type: "Sequence",
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "seq",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ksa := &Keyspace{
|
||||
Name: "ksa",
|
||||
}
|
||||
ksb := &Keyspace{
|
||||
Name: "ksb",
|
||||
}
|
||||
got, _ := BuildVSchema(&good)
|
||||
t1a := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksa",
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ksa,
|
||||
IsSequence: true,
|
||||
}
|
||||
t1b := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksb",
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ksb,
|
||||
IsSequence: true,
|
||||
}
|
||||
want := &VSchema{
|
||||
|
@ -453,11 +408,13 @@ func TestBuildVSchemaDupSeq(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"ksa": {
|
||||
Keyspace: ksa,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1a,
|
||||
},
|
||||
},
|
||||
"ksb": {
|
||||
Keyspace: ksb,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1b,
|
||||
},
|
||||
|
@ -475,29 +432,31 @@ func TestBuildVSchemaDupTable(t *testing.T) {
|
|||
good := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"ksa": {
|
||||
Tables: map[string]string{
|
||||
"t1": "",
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
"ksb": {
|
||||
Tables: map[string]string{
|
||||
"t1": "",
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
got, _ := BuildVSchema(&good)
|
||||
ksa := &Keyspace{
|
||||
Name: "ksa",
|
||||
}
|
||||
t1a := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksa",
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ksa,
|
||||
}
|
||||
ksb := &Keyspace{
|
||||
Name: "ksb",
|
||||
}
|
||||
t1b := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksb",
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: ksb,
|
||||
}
|
||||
want := &VSchema{
|
||||
tables: map[string]*Table{
|
||||
|
@ -505,11 +464,13 @@ func TestBuildVSchemaDupTable(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"ksa": {
|
||||
Keyspace: ksa,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1a,
|
||||
},
|
||||
},
|
||||
"ksb": {
|
||||
Keyspace: ksb,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1b,
|
||||
},
|
||||
|
@ -533,7 +494,7 @@ func TestBuildVSchemaNoindexFail(t *testing.T) {
|
|||
Type: "stfu",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -543,14 +504,11 @@ func TestBuildVSchemaNoindexFail(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := BuildVSchema(&bad)
|
||||
want := "vindex notexist not found for class t1"
|
||||
want := "vindex notexist not found for table t1"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("BuildVSchema: %v, want %v", err, want)
|
||||
}
|
||||
|
@ -566,7 +524,7 @@ func TestBuildVSchemaNotUniqueFail(t *testing.T) {
|
|||
Type: "stln",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -576,14 +534,11 @@ func TestBuildVSchemaNotUniqueFail(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := BuildVSchema(&bad)
|
||||
want := "primary vindex stln is not Unique for class t1"
|
||||
want := "primary vindex stln is not Unique for table t1"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("BuildVSchema: %v, want %v", err, want)
|
||||
}
|
||||
|
@ -600,7 +555,7 @@ func TestBuildVSchemaPrimaryNonFunctionalFail(t *testing.T) {
|
|||
Owner: "t1",
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -610,14 +565,11 @@ func TestBuildVSchemaPrimaryNonFunctionalFail(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := BuildVSchema(&bad)
|
||||
want := "primary vindex stlu cannot be owned for class t1"
|
||||
want := "primary vindex stlu cannot be owned for table t1"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("BuildVSchema: %v, want %v", err, want)
|
||||
}
|
||||
|
@ -627,14 +579,11 @@ func TestSequence(t *testing.T) {
|
|||
good := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"unsharded": {
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"seq": {
|
||||
Type: "Sequence",
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"seq": "seq",
|
||||
},
|
||||
},
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
|
@ -646,7 +595,7 @@ func TestSequence(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
ColVindexes: []ColVindexFormal{
|
||||
{
|
||||
|
@ -660,9 +609,6 @@ func TestSequence(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -670,19 +616,21 @@ func TestSequence(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
ksu := &Keyspace{
|
||||
Name: "unsharded",
|
||||
}
|
||||
kss := &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
}
|
||||
seq := &Table{
|
||||
Name: "seq",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "unsharded",
|
||||
},
|
||||
Name: "seq",
|
||||
Keyspace: ksu,
|
||||
IsSequence: true,
|
||||
}
|
||||
t1 := &Table{
|
||||
Name: "t1",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "sharded",
|
||||
Sharded: true,
|
||||
},
|
||||
Name: "t1",
|
||||
Keyspace: kss,
|
||||
ColVindexes: []*ColVindex{
|
||||
{
|
||||
Col: "c1",
|
||||
|
@ -711,12 +659,13 @@ func TestSequence(t *testing.T) {
|
|||
},
|
||||
Keyspaces: map[string]*KeyspaceSchema{
|
||||
"unsharded": {
|
||||
Keyspace: ksu,
|
||||
Tables: map[string]*Table{
|
||||
"seq": seq,
|
||||
},
|
||||
},
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
Keyspace: kss,
|
||||
Tables: map[string]*Table{
|
||||
"t1": t1,
|
||||
},
|
||||
|
@ -735,7 +684,7 @@ func TestBadSequence(t *testing.T) {
|
|||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"sharded": {
|
||||
Sharded: true,
|
||||
Classes: map[string]ClassFormal{
|
||||
Tables: map[string]TableFormal{
|
||||
"t1": {
|
||||
Autoinc: &AutoincFormal{
|
||||
Col: "c1",
|
||||
|
@ -743,14 +692,11 @@ func TestBadSequence(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tables: map[string]string{
|
||||
"t1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := BuildVSchema(&bad)
|
||||
want := "sequence seq not found for class t1"
|
||||
want := "sequence seq not found for table t1"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("BuildVSchema: %v, want %v", err, want)
|
||||
}
|
||||
|
@ -760,47 +706,108 @@ func TestFind(t *testing.T) {
|
|||
input := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"ksa": {
|
||||
Tables: map[string]string{
|
||||
"ta": "",
|
||||
"t1": "",
|
||||
Tables: map[string]TableFormal{
|
||||
"ta": {},
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
"ksb": {
|
||||
Tables: map[string]string{
|
||||
"tb": "",
|
||||
"t1": "",
|
||||
Sharded: true,
|
||||
Tables: map[string]TableFormal{
|
||||
"tb": {},
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
vschema, _ := BuildVSchema(&input)
|
||||
_, err := vschema.FindTable("")
|
||||
wantErr := "unsupported: compex table expression in DML"
|
||||
_, err := vschema.Find("", "t1")
|
||||
wantErr := "ambiguous table reference: t1"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
|
||||
t.Errorf("Find(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
_, err = vschema.FindTable("t1")
|
||||
wantErr = "ambiguous table reference: t1"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
_, err = vschema.FindTable("none")
|
||||
_, err = vschema.Find("", "none")
|
||||
wantErr = "table none not found"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
|
||||
t.Errorf("Find(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
got, err := vschema.FindTable("ta")
|
||||
got, err := vschema.Find("", "ta")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
want := &Table{
|
||||
ta := &Table{
|
||||
Name: "ta",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksa",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, want)
|
||||
if !reflect.DeepEqual(got, ta) {
|
||||
t.Errorf("Find(\"t1a\"): %+v, want %+v", got, ta)
|
||||
}
|
||||
got, err = vschema.Find("ksa", "ta")
|
||||
if !reflect.DeepEqual(got, ta) {
|
||||
t.Errorf("Find(\"t1a\"): %+v, want %+v", got, ta)
|
||||
}
|
||||
none := &Table{
|
||||
Name: "none",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksa",
|
||||
},
|
||||
}
|
||||
got, err = vschema.Find("ksa", "none")
|
||||
if !reflect.DeepEqual(got, none) {
|
||||
t.Errorf("Find(\"t1a\"): %+v, want %+v", got, none)
|
||||
}
|
||||
_, err = vschema.Find("ksb", "none")
|
||||
wantErr = "table none not found"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("Find(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
_, err = vschema.Find("none", "aa")
|
||||
wantErr = "keyspace none not found in vschema"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("Find(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindSingleKeyspace(t *testing.T) {
|
||||
input := VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"ksa": {
|
||||
Tables: map[string]TableFormal{
|
||||
"ta": {},
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
vschema, _ := BuildVSchema(&input)
|
||||
none := &Table{
|
||||
Name: "none",
|
||||
Keyspace: &Keyspace{
|
||||
Name: "ksa",
|
||||
},
|
||||
}
|
||||
got, _ := vschema.Find("", "none")
|
||||
if !reflect.DeepEqual(got, none) {
|
||||
t.Errorf("Find(\"t1a\"): %+v, want %+v", got, none)
|
||||
}
|
||||
input = VSchemaFormal{
|
||||
Keyspaces: map[string]KeyspaceFormal{
|
||||
"ksb": {
|
||||
Sharded: true,
|
||||
Tables: map[string]TableFormal{
|
||||
"tb": {},
|
||||
"t1": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
vschema, _ = BuildVSchema(&input)
|
||||
_, err := vschema.Find("", "none")
|
||||
wantErr := "table none not found"
|
||||
if err == nil || err.Error() != wantErr {
|
||||
t.Errorf("Find(\"\"): %v, want %s", err, wantErr)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ func (vtg *VTGate) InitializeConnections(ctx context.Context) (err error) {
|
|||
}
|
||||
|
||||
// Execute executes a non-streaming query by routing based on the values in the query.
|
||||
func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
startTime := time.Now()
|
||||
statsKey := []string{"Execute", "Any", strings.ToLower(tabletType.String())}
|
||||
defer vtg.timings.Record(statsKey, startTime)
|
||||
|
@ -168,7 +168,7 @@ func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[st
|
|||
return nil, errTooManyInFlight
|
||||
}
|
||||
|
||||
qr, err := vtg.router.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
qr, err := vtg.router.Execute(ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
if err == nil {
|
||||
vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows)))
|
||||
return qr, nil
|
||||
|
@ -177,6 +177,7 @@ func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[st
|
|||
query := map[string]interface{}{
|
||||
"Sql": sql,
|
||||
"BindVariables": bindVariables,
|
||||
"Keyspace": keyspace,
|
||||
"TabletType": strings.ToLower(tabletType.String()),
|
||||
"Session": session,
|
||||
"NotInTransaction": notInTransaction,
|
||||
|
@ -410,7 +411,7 @@ func (vtg *VTGate) ExecuteBatchKeyspaceIds(ctx context.Context, queries []*vtgat
|
|||
}
|
||||
|
||||
// StreamExecute executes a streaming query by routing based on the values in the query.
|
||||
func (vtg *VTGate) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (vtg *VTGate) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
startTime := time.Now()
|
||||
statsKey := []string{"StreamExecute", "Any", strings.ToLower(tabletType.String())}
|
||||
defer vtg.timings.Record(statsKey, startTime)
|
||||
|
@ -426,6 +427,7 @@ func (vtg *VTGate) StreamExecute(ctx context.Context, sql string, bindVariables
|
|||
ctx,
|
||||
sql,
|
||||
bindVariables,
|
||||
keyspace,
|
||||
tabletType,
|
||||
func(reply *sqltypes.Result) error {
|
||||
rowCount += int64(len(reply.Rows))
|
||||
|
@ -438,6 +440,7 @@ func (vtg *VTGate) StreamExecute(ctx context.Context, sql string, bindVariables
|
|||
query := map[string]interface{}{
|
||||
"Sql": sql,
|
||||
"BindVariables": bindVariables,
|
||||
"Keyspace": keyspace,
|
||||
"TabletType": strings.ToLower(tabletType.String()),
|
||||
}
|
||||
logError(err, query, vtg.logStreamExecute)
|
||||
|
|
|
@ -35,7 +35,7 @@ func init() {
|
|||
"TestUnsharded": {
|
||||
"Sharded": false,
|
||||
"Tables": {
|
||||
"t1": ""
|
||||
"t1": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ func TestVTGateExecute(t *testing.T) {
|
|||
qr, err := rpcVTGate.Execute(context.Background(),
|
||||
"select id from t1",
|
||||
nil,
|
||||
"",
|
||||
topodatapb.TabletType_MASTER,
|
||||
nil,
|
||||
false)
|
||||
|
@ -68,6 +69,7 @@ func TestVTGateExecute(t *testing.T) {
|
|||
rpcVTGate.Execute(context.Background(),
|
||||
"select id from t1",
|
||||
nil,
|
||||
"",
|
||||
topodatapb.TabletType_MASTER,
|
||||
session,
|
||||
false)
|
||||
|
@ -95,12 +97,43 @@ func TestVTGateExecute(t *testing.T) {
|
|||
rpcVTGate.Execute(context.Background(),
|
||||
"select id from t1",
|
||||
nil,
|
||||
"",
|
||||
topodatapb.TabletType_MASTER,
|
||||
session,
|
||||
false)
|
||||
rpcVTGate.Rollback(context.Background(), session)
|
||||
}
|
||||
|
||||
func TestVTGateExecuteWithKeyspace(t *testing.T) {
|
||||
sandbox := createSandbox(KsTestUnsharded)
|
||||
sbc := &sandboxConn{}
|
||||
sandbox.MapTestConn("0", sbc)
|
||||
qr, err := rpcVTGate.Execute(context.Background(),
|
||||
"select id from none",
|
||||
nil,
|
||||
KsTestUnsharded,
|
||||
topodatapb.TabletType_MASTER,
|
||||
nil,
|
||||
false)
|
||||
if err != nil {
|
||||
t.Errorf("want nil, got %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(singleRowResult, qr) {
|
||||
t.Errorf("want \n%+v, got \n%+v", singleRowResult, qr)
|
||||
}
|
||||
_, err = rpcVTGate.Execute(context.Background(),
|
||||
"select id from none",
|
||||
nil,
|
||||
"aa",
|
||||
topodatapb.TabletType_MASTER,
|
||||
nil,
|
||||
false)
|
||||
want := "keyspace aa not found in vschema"
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("Execute: %v, want %s", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVTGateExecuteShards(t *testing.T) {
|
||||
sandbox := createSandbox("TestVTGateExecuteShards")
|
||||
sbc := &sandboxConn{}
|
||||
|
@ -532,6 +565,7 @@ func TestVTGateStreamExecute(t *testing.T) {
|
|||
err := rpcVTGate.StreamExecute(context.Background(),
|
||||
"select id from t1",
|
||||
nil,
|
||||
"",
|
||||
topodatapb.TabletType_MASTER,
|
||||
func(r *sqltypes.Result) error {
|
||||
qrs = append(qrs, r)
|
||||
|
|
|
@ -74,13 +74,14 @@ func (f *fakeVTGateService) checkCallerID(ctx context.Context, name string) {
|
|||
type queryExecute struct {
|
||||
SQL string
|
||||
BindVariables map[string]interface{}
|
||||
Keyspace string
|
||||
TabletType topodatapb.TabletType
|
||||
Session *vtgatepb.Session
|
||||
NotInTransaction bool
|
||||
}
|
||||
|
||||
// Execute is part of the VTGateService interface
|
||||
func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
if f.hasError {
|
||||
return nil, errTestVtGateError
|
||||
}
|
||||
|
@ -95,6 +96,7 @@ func (f *fakeVTGateService) Execute(ctx context.Context, sql string, bindVariabl
|
|||
query := &queryExecute{
|
||||
SQL: sql,
|
||||
BindVariables: bindVariables,
|
||||
Keyspace: keyspace,
|
||||
TabletType: tabletType,
|
||||
Session: session,
|
||||
NotInTransaction: notInTransaction,
|
||||
|
@ -370,7 +372,7 @@ func (f *fakeVTGateService) ExecuteBatchKeyspaceIds(ctx context.Context, queries
|
|||
}
|
||||
|
||||
// StreamExecute is part of the VTGateService interface
|
||||
func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
if f.panics {
|
||||
panic(fmt.Errorf("test forced panic"))
|
||||
}
|
||||
|
@ -382,6 +384,7 @@ func (f *fakeVTGateService) StreamExecute(ctx context.Context, sql string, bindV
|
|||
query := &queryExecute{
|
||||
SQL: sql,
|
||||
BindVariables: bindVariables,
|
||||
Keyspace: keyspace,
|
||||
TabletType: tabletType,
|
||||
}
|
||||
if !reflect.DeepEqual(query, execCase.execQuery) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
type VTGateService interface {
|
||||
// Regular query execution.
|
||||
// All these methods can change the provided session.
|
||||
Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error)
|
||||
Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error)
|
||||
ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error)
|
||||
ExecuteKeyspaceIds(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, keyspaceIds [][]byte, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error)
|
||||
ExecuteKeyRanges(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, keyRanges []*topodatapb.KeyRange, tabletType topodatapb.TabletType, session *vtgatepb.Session, notInTransaction bool) (*sqltypes.Result, error)
|
||||
|
@ -29,7 +29,7 @@ type VTGateService interface {
|
|||
ExecuteBatchKeyspaceIds(ctx context.Context, queries []*vtgatepb.BoundKeyspaceIdQuery, tabletType topodatapb.TabletType, asTransaction bool, session *vtgatepb.Session) ([]sqltypes.Result, error)
|
||||
|
||||
// Streaming queries
|
||||
StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error
|
||||
StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error
|
||||
StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error
|
||||
StreamExecuteKeyspaceIds(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, keyspaceIds [][]byte, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error
|
||||
StreamExecuteKeyRanges(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, keyRanges []*topodatapb.KeyRange, tabletType topodatapb.TabletType, sendReply func(*sqltypes.Result) error) error
|
||||
|
|
|
@ -33,15 +33,15 @@ func (_m *MockVTGateService) EXPECT() *_MockVTGateServiceRecorder {
|
|||
return _m.recorder
|
||||
}
|
||||
|
||||
func (_m *MockVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodata.TabletType, session *vtgate.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
ret := _m.ctrl.Call(_m, "Execute", ctx, sql, bindVariables, tabletType, session, notInTransaction)
|
||||
func (_m *MockVTGateService) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodata.TabletType, session *vtgate.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
ret := _m.ctrl.Call(_m, "Execute", ctx, sql, bindVariables, keyspace, tabletType, session, notInTransaction)
|
||||
ret0, _ := ret[0].(*sqltypes.Result)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (_mr *_MockVTGateServiceRecorder) Execute(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Execute", arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
func (_mr *_MockVTGateServiceRecorder) Execute(arg0, arg1, arg2, arg3, arg4, arg5, arg6 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Execute", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
}
|
||||
|
||||
func (_m *MockVTGateService) ExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodata.TabletType, session *vtgate.Session, notInTransaction bool) (*sqltypes.Result, error) {
|
||||
|
@ -110,14 +110,14 @@ func (_mr *_MockVTGateServiceRecorder) ExecuteBatchKeyspaceIds(arg0, arg1, arg2,
|
|||
return _mr.mock.ctrl.RecordCall(_mr.mock, "ExecuteBatchKeyspaceIds", arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
func (_m *MockVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType topodata.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
ret := _m.ctrl.Call(_m, "StreamExecute", ctx, sql, bindVariables, tabletType, sendReply)
|
||||
func (_m *MockVTGateService) StreamExecute(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, tabletType topodata.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
ret := _m.ctrl.Call(_m, "StreamExecute", ctx, sql, bindVariables, keyspace, tabletType, sendReply)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockVTGateServiceRecorder) StreamExecute(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "StreamExecute", arg0, arg1, arg2, arg3, arg4)
|
||||
func (_mr *_MockVTGateServiceRecorder) StreamExecute(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "StreamExecute", arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
func (_m *MockVTGateService) StreamExecuteShards(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, shards []string, tabletType topodata.TabletType, sendReply func(*sqltypes.Result) error) error {
|
||||
|
|
|
@ -41,6 +41,9 @@ message ExecuteRequest {
|
|||
|
||||
// not_in_transaction is deprecated and should not be used.
|
||||
bool not_in_transaction = 5;
|
||||
|
||||
// keyspace to target the query to.
|
||||
string keyspace = 6;
|
||||
}
|
||||
|
||||
// ExecuteResponse is the returned value from Execute.
|
||||
|
@ -345,6 +348,9 @@ message StreamExecuteRequest {
|
|||
|
||||
// tablet_type is the type of tablets that this query is targeted to.
|
||||
topodata.TabletType tablet_type = 3;
|
||||
|
||||
// keyspace to target the query to.
|
||||
string keyspace = 4;
|
||||
}
|
||||
|
||||
// StreamExecuteResponse is the returned value from StreamExecute.
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -126,7 +126,7 @@ vschema = '''{
|
|||
"Owner": "vt_music"
|
||||
}
|
||||
},
|
||||
"Classes": {
|
||||
"Tables": {
|
||||
"vt_user": {
|
||||
"ColVindexes": [
|
||||
{
|
||||
|
@ -203,29 +203,19 @@ vschema = '''{
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"vt_user": "vt_user",
|
||||
"vt_user2": "vt_user2",
|
||||
"vt_user_extra": "vt_user_extra",
|
||||
"vt_music": "vt_music",
|
||||
"vt_music_extra": "vt_music_extra",
|
||||
"join_user": "join_user",
|
||||
"join_user_extra": "join_user_extra"
|
||||
}
|
||||
},
|
||||
"lookup": {
|
||||
"Sharded": false,
|
||||
"Classes" : {
|
||||
"seq": {
|
||||
"Type": "Sequence"
|
||||
}
|
||||
},
|
||||
"Tables": {
|
||||
"vt_user_seq": "seq",
|
||||
"vt_music_seq": "seq",
|
||||
"music_user_map": "",
|
||||
"name_user2_map": ""
|
||||
"vt_user_seq": {
|
||||
"Type": "Sequence"
|
||||
},
|
||||
"vt_music_seq": {
|
||||
"Type": "Sequence"
|
||||
},
|
||||
"music_user_map": {},
|
||||
"name_user2_map": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче