Skip to content

Commit

Permalink
add virtual db
Browse files Browse the repository at this point in the history
  • Loading branch information
sjjian committed Nov 15, 2020
1 parent f23fd23 commit 559f15a
Show file tree
Hide file tree
Showing 6 changed files with 665 additions and 1 deletion.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# sql-calculator
# sql-calculator

## virtual db
模拟数据库的 ddl 执行得到数据库结构
```go
vb := NewVirtualDB("")
vb.ExecSQL("create database db1")
vb.ExecSQL("use db1")
vb.ExecSQL("create table t1(id int)")
vb.ExecSQL("alter table db1.t1 add column name varchar(255);")

vb.Text()
/*
output:
CREATE DATABASE `db1`;
CREATE TABLE `db1`.`t1` (`id` INT,`name` VARCHAR(255));
*/
```
9 changes: 9 additions & 0 deletions cmd/sql-diff/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
"fmt"
)

func main() {
fmt.Println("hello world")
}
19 changes: 19 additions & 0 deletions virtualdb/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package virtualdb

import "errors"

const (
NotExistSchemaErrorPattern = "not exist schema: %s"
DuplicateSchemaErrorPattern = "duplicate schema: %s"
NotExistTableErrorPattern = "not exist table: %s.%s"
DuplicateTableErrorPattern = "duplicate table: %s.%s"
NotExistColumnErrorPattern = "not exist column %s in %s.%s"
DuplicateColumnErrorPattern = "duplicate column %s in %s.%s"
NotExistIndexErrorPattern = "not exist index %s in %s.%s"
DuplicateIndexErrorPattern = "duplicate index %s in %s.%s"
)

var (
NoPrimaryKeyError = errors.New("no primary key")
ExistPrimaryKeyError = errors.New("primary key exists")
)
96 changes: 96 additions & 0 deletions virtualdb/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package virtualdb

import (
"fmt"
"github.com/pingcap/parser"
"github.com/pingcap/parser/ast"
"github.com/pingcap/parser/format"
_ "github.com/pingcap/tidb/types/parser_driver"
"strings"
)

func restoreToSql(stmt ast.StmtNode) (string, error) {
var sb strings.Builder
ctx := format.NewRestoreCtx(format.DefaultRestoreFlags, &sb)
err := stmt.Restore(ctx)
if err != nil {
return "", err
}
return sb.String(), nil
}

// parseCreateTableStmt parse create table sql text to CreateTableStmt ast.
func parseCreateTableStmt(sql string) (*ast.CreateTableStmt, error) {
t, err := parseOneSql(sql)
if err != nil {
return nil, err
}
createStmt, ok := t.(*ast.CreateTableStmt)
if !ok {
return nil, fmt.Errorf("stmt not support")
}
return createStmt, nil
}

func parseOneSql(sql string) (ast.StmtNode, error) {
p := parser.New()
stmt, err := p.ParseOneStmt(sql, "", "")
if err != nil {
return nil, err
}
return stmt, nil
}

func getAlterTableSpecByTp(specs []*ast.AlterTableSpec, ts ...ast.AlterTableType) []*ast.AlterTableSpec {
s := []*ast.AlterTableSpec{}
if specs == nil {
return s
}
for _, spec := range specs {
for _, tp := range ts {
if spec.Tp == tp {
s = append(s, spec)
}
}
}
return s
}

func hasOneInOptions(Options []*ast.ColumnOption, opTp ...ast.ColumnOptionType) bool {
// has one exists, return true
for _, tp := range opTp {
for _, op := range Options {
if tp == op.Tp {
return true
}
}
}
return false
}

func getPrimaryKey(stmt *ast.CreateTableStmt) (map[string]struct{}, bool) {
hasPk := false
pkColumnsName := map[string]struct{}{}
for _, constraint := range stmt.Constraints {
if constraint.Tp == ast.ConstraintPrimaryKey {
hasPk = true
for _, col := range constraint.Keys {
pkColumnsName[col.Column.Name.L] = struct{}{}
}
}
}
if !hasPk {
for _, col := range stmt.Cols {
if hasOneInOptions(col.Options, ast.ColumnOptionPrimaryKey) {
hasPk = true
pkColumnsName[col.Name.Name.L] = struct{}{}
}
}
}
return pkColumnsName, hasPk
}

func hasPrimaryKey(stmt *ast.CreateTableStmt) bool {
_, hasPk := getPrimaryKey(stmt)
return hasPk
}
Loading

0 comments on commit 559f15a

Please sign in to comment.