Skip to content

Commit e652752

Browse files
wph95lfkdsk
authored andcommitted
feature: engine plugin and csv dashbase example. (pingcap#5)
* first commit 1. plugin add Engine 2. show engine && show table status is work right with plugin 3. csv reader example * code support OnReaderNext and OnReaderOpen * plugin support selection
1 parent 39340ce commit e652752

20 files changed

+471
-55
lines changed

ddl/ddl_api.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"bytes"
2222
"context"
2323
"fmt"
24+
"github.com/pingcap/tidb/plugin"
2425
"strconv"
2526
"strings"
2627
"sync/atomic"
@@ -1370,6 +1371,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e
13701371
referIdent := ast.Ident{Schema: s.ReferTable.Schema, Name: s.ReferTable.Name}
13711372
return d.CreateTableWithLike(ctx, ident, referIdent, s.IfNotExists)
13721373
}
1374+
13731375
is := d.GetInfoSchemaWithInterceptor(ctx)
13741376
schema, ok := is.SchemaByName(ident.Schema)
13751377
if !ok {
@@ -1388,6 +1390,17 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e
13881390
if err != nil {
13891391
return errors.Trace(err)
13901392
}
1393+
1394+
engine := findTableOption(s.Options, ast.TableOptionEngine, "InnoDB")
1395+
var p *plugin.Plugin
1396+
if engine != "InnoDB" {
1397+
p = plugin.Get(plugin.Engine, engine)
1398+
if p == nil {
1399+
return infoschema.ErrorEngineError.GenWithStackByArgs(404)
1400+
}
1401+
tbInfo.Engine = engine
1402+
}
1403+
13911404
tbInfo.State = model.StatePublic
13921405
err = checkTableInfoValid(tbInfo)
13931406
if err != nil {
@@ -1759,6 +1772,19 @@ func resolveDefaultTableCharsetAndCollation(tbInfo *model.TableInfo, dbCharset s
17591772
return
17601773
}
17611774

1775+
func findTableOption(options []*ast.TableOption, tp ast.TableOptionType, _default string) string {
1776+
value := _default
1777+
for i := len(options) - 1; i >= 0; i-- {
1778+
op := options[i]
1779+
if op.Tp == tp {
1780+
// find the last one.
1781+
value = op.StrValue
1782+
break
1783+
}
1784+
}
1785+
return value
1786+
}
1787+
17621788
func findTableOptionCharset(options []*ast.TableOption) string {
17631789
var tableCharset string
17641790
for i := len(options) - 1; i >= 0; i-- {

executor/admin_plugins.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ package executor
1616
import (
1717
"context"
1818

19-
"github.com/pingcap/tidb/domain"
2019
"github.com/pingcap/tidb/planner/core"
21-
"github.com/pingcap/tidb/plugin"
2220
"github.com/pingcap/tidb/util/chunk"
2321
)
2422

@@ -41,12 +39,12 @@ func (e *AdminPluginsExec) Next(ctx context.Context, _ *chunk.Chunk) error {
4139
}
4240

4341
func (e *AdminPluginsExec) changeDisableFlagAndFlush(disabled bool) error {
44-
dom := domain.GetDomain(e.ctx)
45-
for _, pluginName := range e.Plugins {
46-
err := plugin.ChangeDisableFlagAndFlush(dom, pluginName, disabled)
47-
if err != nil {
48-
return err
49-
}
50-
}
42+
//dom := domain.GetDomain(e.ctx)
43+
//for _, pluginName := range e.Plugins {
44+
// err := plugin.ChangeDisableFlagAndFlush(dom, pluginName, disabled)
45+
// if err != nil {
46+
// return err
47+
// }
48+
//}
5149
return nil
5250
}

executor/builder.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"bytes"
1818
"context"
1919
"fmt"
20+
"github.com/pingcap/tidb/plugin"
2021
"math"
2122
"sort"
2223
"strings"
@@ -208,6 +209,8 @@ func (b *executorBuilder) build(p plannercore.Plan) Executor {
208209
return b.buildSQLBindExec(v)
209210
case *plannercore.SplitRegion:
210211
return b.buildSplitRegion(v)
212+
case *plannercore.PhysicalTableScan:
213+
return b.buildTableScan(v)
211214
default:
212215
if mp, ok := p.(MockPhysicalPlan); ok {
213216
return mp.GetExecutor()
@@ -1923,16 +1926,38 @@ func buildNoRangeTableReader(b *executorBuilder, v *plannercore.PhysicalTableRea
19231926
return e, nil
19241927
}
19251928

1929+
func (b *executorBuilder) buildTableScan(v *plannercore.PhysicalTableScan) Executor {
1930+
1931+
plugin.Get(plugin.Engine, "csv")
1932+
return &PluginScanExecutor{
1933+
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()),
1934+
Plugin: plugin.Get(plugin.Engine, "csv"),
1935+
Table: v.Table,
1936+
Columns: v.Columns,
1937+
}
1938+
}
1939+
19261940
// buildTableReader builds a table reader executor. It first build a no range table reader,
19271941
// and then update it ranges from table scan plan.
1928-
func (b *executorBuilder) buildTableReader(v *plannercore.PhysicalTableReader) *TableReaderExecutor {
1942+
func (b *executorBuilder) buildTableReader(v *plannercore.PhysicalTableReader) Executor {
1943+
ts := v.TablePlans[0].(*plannercore.PhysicalTableScan)
1944+
if ts.Table.Engine == "csv" {
1945+
if len(v.TablePlans) == 2 {
1946+
if tSelect, ok:=v.TablePlans[1].(*plannercore.PhysicalSelection);ok{
1947+
return b.buildSelection(tSelect)
1948+
}
1949+
1950+
}
1951+
1952+
return b.buildTableScan(ts)
1953+
}
1954+
19291955
ret, err := buildNoRangeTableReader(b, v)
19301956
if err != nil {
19311957
b.err = err
19321958
return nil
19331959
}
19341960

1935-
ts := v.TablePlans[0].(*plannercore.PhysicalTableScan)
19361961
ret.ranges = ts.Ranges
19371962
sctx := b.ctx.GetSessionVars().StmtCtx
19381963
sctx.TableIDs = append(sctx.TableIDs, ts.Table.ID)

executor/plugin_executor.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package executor
2+
3+
import (
4+
"fmt"
5+
"github.com/davecgh/go-spew/spew"
6+
"github.com/pingcap/parser/model"
7+
"github.com/pingcap/tidb/plugin"
8+
"github.com/pingcap/tidb/util/chunk"
9+
"golang.org/x/net/context"
10+
)
11+
12+
type PluginScanExecutor struct {
13+
baseExecutor
14+
Table *model.TableInfo
15+
Columns []*model.ColumnInfo
16+
Plugin *plugin.Plugin
17+
pm *plugin.EngineManifest
18+
meta *plugin.ExecutorMeta
19+
}
20+
21+
func (e *PluginScanExecutor) Open(ctx context.Context) error {
22+
e.pm = plugin.DeclareEngineManifest(e.Plugin.Manifest)
23+
e.meta = &plugin.ExecutorMeta{
24+
Table: e.Table,
25+
}
26+
e.pm.OnReaderOpen(ctx, e.meta)
27+
return nil
28+
}
29+
30+
func (e *PluginScanExecutor) Next(ctx context.Context, chk *chunk.Chunk) error {
31+
chk.Reset()
32+
err := e.pm.OnReaderNext(ctx, chk, e.meta)
33+
fmt.Println("pe next finished", spew.Sdump(err))
34+
return err
35+
}
36+
37+
func (e *PluginScanExecutor) Close() error {
38+
return nil
39+
}

executor/simple.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/pingcap/tidb/infoschema"
3232
"github.com/pingcap/tidb/kv"
3333
"github.com/pingcap/tidb/planner/core"
34-
"github.com/pingcap/tidb/plugin"
3534
"github.com/pingcap/tidb/privilege"
3635
"github.com/pingcap/tidb/sessionctx"
3736
"github.com/pingcap/tidb/sessionctx/variable"
@@ -987,13 +986,13 @@ func (e *SimpleExec) executeFlush(s *ast.FlushStmt) error {
987986
err = dom.PrivilegeHandle().Update(ctx.(sessionctx.Context))
988987
return err
989988
case ast.FlushTiDBPlugin:
990-
dom := domain.GetDomain(e.ctx)
991-
for _, pluginName := range s.Plugins {
992-
err := plugin.NotifyFlush(dom, pluginName)
993-
if err != nil {
994-
return err
995-
}
996-
}
989+
//dom := domain.GetDomain(e.ctx)
990+
//for _, pluginName := range s.Plugins {
991+
// err := plugin.NotifyFlush(dom, pluginName)
992+
// if err != nil {
993+
// return err
994+
// }
995+
//}
997996
}
998997
return nil
999998
}

infoschema/infoschema.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ var (
7171
ErrTableLocked = terror.ClassSchema.New(codeTableLocked, mysql.MySQLErrName[mysql.ErrTableLocked])
7272
// ErrAccessDenied return when the user doesn't have the permission to access the table.
7373
ErrAccessDenied = terror.ClassSchema.New(codeErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDenied])
74+
// ErrAccessDenied return when the user use custom engine have errors.
75+
ErrorEngineError = terror.ClassSchema.New(codeEngineError, "Got error %d from storage engine")
7476
)
7577

7678
// InfoSchema is the interface used to retrieve the schema information.
@@ -339,6 +341,8 @@ const (
339341
codeKeyNameDuplicate = 1061
340342
codeKeyNotExists = 1176
341343

344+
codeEngineError = mysql.ErrGetErrno
345+
342346
codeErrTableNotLockedForWrite = mysql.ErrTableNotLockedForWrite
343347
codeErrTableNotLocked = mysql.ErrTableNotLocked
344348
codeErrNonuniqTable = mysql.ErrNonuniqTable

infoschema/tables.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"context"
1818
"encoding/json"
1919
"fmt"
20+
"github.com/pingcap/tidb/plugin"
2021
"sort"
2122
"sync"
2223
"time"
@@ -969,6 +970,25 @@ func dataForEngines() (records [][]types.Datum) {
969970
"YES", // Savepoints
970971
),
971972
)
973+
974+
thirdEngine := plugin.List(plugin.Engine)
975+
for _, e := range thirdEngine {
976+
977+
records = append(records,
978+
types.MakeDatums(
979+
e.Name, // Engine
980+
"YES", // Support
981+
"Created By Plugin :)", // Comment
982+
"NO", // Transactions
983+
"NO", // XA
984+
"NO", // Savepoints
985+
),
986+
)
987+
988+
}
989+
990+
991+
972992
return records
973993
}
974994

@@ -1268,7 +1288,7 @@ func dataForTables(ctx sessionctx.Context, schemas []*model.DBInfo) ([][]types.D
12681288
schema.Name.O, // TABLE_SCHEMA
12691289
table.Name.O, // TABLE_NAME
12701290
"BASE TABLE", // TABLE_TYPE
1271-
"InnoDB", // ENGINE
1291+
table.Engine, // ENGINE
12721292
uint64(10), // VERSION
12731293
"Compact", // ROW_FORMAT
12741294
rowCount, // TABLE_ROWS

plugin/const.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
Schema
2626
// Daemon indicate a plugin that can run as daemon task.
2727
Daemon
28+
Engine
2829
// UDF indicate a plugin that can add user define func to tidb.
2930
UDF
3031
)
@@ -39,6 +40,8 @@ func (k Kind) String() (str string) {
3940
str = "Schema"
4041
case Daemon:
4142
str = "Daemon"
43+
case Engine:
44+
str = "Engine"
4245
case UDF:
4346
str = "UDF"
4447
}

plugin/csv/csv.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2019 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package main
15+
16+
import (
17+
"context"
18+
"fmt"
19+
"github.com/pingcap/tidb/plugin"
20+
"github.com/pingcap/tidb/util/chunk"
21+
)
22+
23+
type ReadExecutor struct {
24+
pos int
25+
}
26+
27+
var Files = make(map[string]*ReadExecutor)
28+
29+
// Validate implements TiDB plugin's Validate SPI.
30+
func Validate(ctx context.Context, m *plugin.Manifest) error {
31+
fmt.Println("csv plugin validate")
32+
return nil
33+
}
34+
35+
// OnInit implements TiDB plugin's OnInit SPI.
36+
func OnInit(ctx context.Context, manifest *plugin.Manifest) error {
37+
fmt.Println("csv init called")
38+
return nil
39+
}
40+
41+
// OnShutdown implements TiDB plugin's OnShutdown SPI.
42+
func OnShutdown(ctx context.Context, manifest *plugin.Manifest) error {
43+
fmt.Println("csv shutdown called")
44+
return nil
45+
}
46+
47+
func OnReaderOpen(ctx context.Context, meta *plugin.ExecutorMeta) {
48+
Files[meta.Table.Name.L] = &ReadExecutor{
49+
pos: 0,
50+
}
51+
}
52+
53+
func OnReaderNext(ctx context.Context, chk *chunk.Chunk, meta *plugin.ExecutorMeta) error {
54+
if _, ok := Files[meta.Table.Name.L]; !ok {
55+
fmt.Println("have some problem")
56+
return nil
57+
}
58+
e := Files[meta.Table.Name.L]
59+
if e.pos > 5 {
60+
return nil
61+
}
62+
chk.AppendInt64(0, int64(e.pos))
63+
chk.AppendString(1, "233333")
64+
e.pos += 1
65+
return nil
66+
}

0 commit comments

Comments
 (0)