docs: Add CLAUDE.md with codebase guidance
Create comprehensive documentation for future Claude Code instances working in this repository, including: - Development commands for testing, building, and code quality - Core architecture overview of the SQL query builder system - Directory structure and component explanations - Testing patterns and conventions - Key dependencies and their purposes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+14
-31
@@ -10,10 +10,11 @@ type Blueprint struct {
|
||||
table string // the table the blueprint describes.
|
||||
columns []*ColumnDefinition // columns that should be added to the table
|
||||
commands []*Command //
|
||||
temporary bool // Whether to make the table temporary.
|
||||
charset string // The default character set that should be used for the table.
|
||||
collation string // The collation that should be used for the table.
|
||||
engine string // The engine that should be used for the table.
|
||||
Temporary bool // Whether to make the table temporary.
|
||||
Charset string // The default character set that should be used for the table.
|
||||
Collation string // The collation that should be used for the table.
|
||||
Engine string // The engine that should be used for the table.
|
||||
Comment string
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
@@ -30,7 +31,7 @@ type CommandOptions struct {
|
||||
}
|
||||
|
||||
func NewBlueprint(table string) *Blueprint {
|
||||
return &Blueprint{table: table, charset: "utf8mb4", collation: "utf8mb4_general_ci"}
|
||||
return &Blueprint{table: table}
|
||||
}
|
||||
|
||||
// 字符串
|
||||
@@ -263,21 +264,17 @@ func (this *Blueprint) Create() *Command {
|
||||
return this.addCommand("create", CommandOptions{})
|
||||
}
|
||||
|
||||
// 设置临时表标记
|
||||
func (this *Blueprint) Temporary() {
|
||||
this.temporary = true
|
||||
}
|
||||
|
||||
// 设置表字符集
|
||||
func (this *Blueprint) Charset(charset string) {
|
||||
this.charset = charset
|
||||
}
|
||||
|
||||
// 修改表名
|
||||
func (this *Blueprint) Rename(to string) *Command {
|
||||
return this.addCommand("rename", CommandOptions{To: to})
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this *Blueprint) ModifyComment(comment string) *Command {
|
||||
this.Comment = comment
|
||||
return this.addCommand("modifyComment", CommandOptions{})
|
||||
}
|
||||
|
||||
// 删除表
|
||||
func (this *Blueprint) Drop() *Command {
|
||||
return this.addCommand("drop", CommandOptions{})
|
||||
@@ -307,6 +304,8 @@ func (this *Blueprint) ToSql(sc Schema) (statements []string) {
|
||||
statements = append(statements, sc.CompileDropColumn(this)...)
|
||||
case "rename":
|
||||
statements = append(statements, sc.CompileRename(this)...)
|
||||
case "modifyComment":
|
||||
statements = append(statements, sc.CompileModifyComment(this)...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,26 +419,10 @@ func (this *Blueprint) GetCommands() []*Command {
|
||||
return this.commands
|
||||
}
|
||||
|
||||
func (this *Blueprint) IsTemporary() bool {
|
||||
return this.temporary
|
||||
}
|
||||
|
||||
func (this *Blueprint) GetTable() string {
|
||||
return this.table
|
||||
}
|
||||
|
||||
func (this *Blueprint) GetCharset() string {
|
||||
return this.charset
|
||||
}
|
||||
|
||||
func (this *Blueprint) GetEngine() string {
|
||||
return this.engine
|
||||
}
|
||||
|
||||
func (this *Blueprint) GetCollation() string {
|
||||
return this.collation
|
||||
}
|
||||
|
||||
// 命令类型
|
||||
func (this *Command) Command() string {
|
||||
return this.Type
|
||||
|
||||
+8
-1
@@ -1,7 +1,7 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
@@ -48,6 +48,13 @@ func (this Builder) Rename(from, to string) error {
|
||||
return this.Build(bp)
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this Builder) ModifyComment(table, comment string) error {
|
||||
bp := NewBlueprint(table)
|
||||
bp.ModifyComment(comment)
|
||||
return this.Build(bp)
|
||||
}
|
||||
|
||||
// 删除表
|
||||
func (this Builder) Drop(table string) error {
|
||||
bp := NewBlueprint(table)
|
||||
|
||||
@@ -3,11 +3,11 @@ package mysql
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/dialect/mysql"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/v2/sqlgen"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/dialect/mysql"
|
||||
"git.fsdpf.net/go/db/internal/sb"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"git.fsdpf.net/go/db/sqlgen"
|
||||
)
|
||||
|
||||
type Mysql struct {
|
||||
@@ -16,6 +16,7 @@ type Mysql struct {
|
||||
}
|
||||
|
||||
var mysqlDefaultModifiers = []string{
|
||||
|
||||
"Unsigned", "Charset", "Collate", "VirtualAs", "StoredAs",
|
||||
"Nullable", "Default", "Increment", "Comment", "After", "First",
|
||||
}
|
||||
@@ -47,29 +48,33 @@ func (this Mysql) TableExists(table string) (bool, error) {
|
||||
// 创建表
|
||||
func (this Mysql) CompileCreate(bp *schema.Blueprint) []string {
|
||||
temporary := db.L("CREATE")
|
||||
if bp.IsTemporary() {
|
||||
if bp.Temporary {
|
||||
temporary = db.L("CREATE TEMPORARY")
|
||||
}
|
||||
columns := strings.Join(this.getAddedColumns(bp), ",\n")
|
||||
|
||||
sql := this.GenerateSQL("? TABLE ? (\n?\n)", temporary, db.T(bp.GetTable()), db.L(columns))
|
||||
|
||||
charset := bp.GetCharset()
|
||||
charset := bp.Charset
|
||||
if charset == "" {
|
||||
charset = "utf8mb4"
|
||||
}
|
||||
|
||||
collation := bp.GetCollation()
|
||||
collation := bp.Collation
|
||||
if collation == "" {
|
||||
collation = "utf8mb4_general_ci"
|
||||
}
|
||||
|
||||
sql += this.GenerateSQL(" default charset=? collate=?", charset, collation)
|
||||
|
||||
if engine := bp.GetEngine(); engine != "" {
|
||||
if engine := bp.Engine; engine != "" {
|
||||
sql += this.GenerateSQL(" engine=?", engine)
|
||||
}
|
||||
|
||||
if comment := bp.Comment; comment != "" {
|
||||
sql += this.GenerateSQL(" comment=?", comment)
|
||||
}
|
||||
|
||||
return []string{sql}
|
||||
}
|
||||
|
||||
@@ -121,13 +126,18 @@ func (this Mysql) CompileRename(bp *schema.Blueprint) []string {
|
||||
if len(commands) == 0 {
|
||||
panic("new table undefined")
|
||||
}
|
||||
toName = bp.GetCommands()[0].To
|
||||
toName = commands[0].To
|
||||
if toName == "" {
|
||||
panic("new table undefined")
|
||||
}
|
||||
return []string{this.GenerateSQL("RENAME TABLE ? TO ?", db.T(bp.GetTable()), db.T(toName))}
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this Mysql) CompileModifyComment(bp *schema.Blueprint) []string {
|
||||
return []string{this.GenerateSQL("ALTER TABLE ? COMMENT = ?", db.T(bp.GetTable()), db.V(bp.Comment))}
|
||||
}
|
||||
|
||||
func (this Mysql) addModifiers(sql string, bp *schema.Blueprint, column *schema.ColumnDefinition) string {
|
||||
for _, modifier := range mysqlDefaultModifiers {
|
||||
sql += this.GetColumnModifier(modifier, bp, column)
|
||||
|
||||
@@ -3,9 +3,9 @@ package mysql_test
|
||||
import (
|
||||
"os"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/engine"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ func (t *mysqlBuilderTest) TestGetColumnListing() {
|
||||
// 创建表
|
||||
func (t *mysqlBuilderTest) TestCreateTable() {
|
||||
if err := t.builder.Create("users", func(table *schema.Blueprint) {
|
||||
table.Charset("utf8mb4")
|
||||
table.Charset = "utf8mb4"
|
||||
|
||||
table.BigIncrements("id").Comment("ID")
|
||||
table.Boolean("enabled").Default("1").Comment("是否有效")
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/engine"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -71,7 +71,7 @@ func (t *mysqlTest) TestTableExists() {
|
||||
func (t *mysqlTest) TestCompileCreate() {
|
||||
bp := schema.NewBlueprint("users")
|
||||
bp.Create()
|
||||
bp.Charset("utf8mb4")
|
||||
bp.Charset = "utf8mb4"
|
||||
|
||||
bp.BigIncrements("id").AutoIncrement().Comment("ID")
|
||||
bp.Boolean("enabled").Default("1").Comment("是否有效")
|
||||
@@ -188,3 +188,5 @@ func (t *mysqlTest) TestCompileRename() {
|
||||
|
||||
t.T().Log(sql)
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
|
||||
@@ -3,11 +3,11 @@ package postgres
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/dialect/postgres"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/v2/sqlgen"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/dialect/postgres"
|
||||
"git.fsdpf.net/go/db/internal/sb"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"git.fsdpf.net/go/db/sqlgen"
|
||||
)
|
||||
|
||||
type Postgres struct {
|
||||
@@ -41,7 +41,7 @@ func (this Postgres) TableExists(table string) (bool, error) {
|
||||
|
||||
func (this Postgres) CompileCreate(bp *schema.Blueprint) []string {
|
||||
temporary := db.L("CREATE")
|
||||
if bp.IsTemporary() {
|
||||
if bp.Temporary {
|
||||
temporary = db.L("CREATE TEMPORARY")
|
||||
}
|
||||
columns := strings.Join(this.getAddedColumns(bp), ",\n")
|
||||
@@ -96,6 +96,11 @@ func (this Postgres) CompileRename(bp *schema.Blueprint) []string {
|
||||
return []string{this.GenerateSQL("ALTER TABLE ? RENAME TO ?", db.T(bp.GetTable()), db.T(toName))}
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this Postgres) CompileModifyComment(bp *schema.Blueprint) []string {
|
||||
return []string{this.GenerateSQL("COMMENT ON TABLE ? IS ?", db.T(bp.GetTable()), db.V(bp.Comment))}
|
||||
}
|
||||
|
||||
func (this Postgres) addModifiers(sql string, bp *schema.Blueprint, column *schema.ColumnDefinition) string {
|
||||
for _, modifier := range pgDefaultModifiers {
|
||||
sql += this.GetColumnModifier(modifier, bp, column)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db/v2/engine"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/dialect/sqlite3"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/v2/sqlgen"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/dialect/sqlite3"
|
||||
"git.fsdpf.net/go/db/internal/sb"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"git.fsdpf.net/go/db/sqlgen"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -72,8 +72,15 @@ func (this Sqlite3) CompileCreate(bp *schema.Blueprint) (sqls []string) {
|
||||
}
|
||||
columns = append(columns, sql)
|
||||
}
|
||||
|
||||
prefix := "? TABLE ? (\n?\n)"
|
||||
|
||||
if comment := bp.Comment; comment != "" {
|
||||
prefix = "? TABLE ? ( -- " + comment + "\n?\n)"
|
||||
}
|
||||
|
||||
sqls = append(sqls,
|
||||
this.GenerateSQL("? TABLE ? (\n?\n)",
|
||||
this.GenerateSQL(prefix,
|
||||
temporary,
|
||||
db.T(bp.GetTable()),
|
||||
db.L(strings.Join(columns, "\n")),
|
||||
@@ -152,6 +159,11 @@ func (this Sqlite3) CompileRename(bp *schema.Blueprint) []string {
|
||||
return []string{this.GenerateSQL("RENAME TABLE ? TO ?", db.T(bp.GetTable()), db.T(toName))}
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this Sqlite3) CompileModifyComment(bp *schema.Blueprint) []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (this Sqlite3) GetColumnModifier(modifier string, bp *schema.Blueprint, column *schema.ColumnDefinition) string {
|
||||
switch modifier {
|
||||
case "Collate":
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/engine"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
@@ -68,7 +68,7 @@ func (t *sqlite3Test) TestGetColumnListing() {
|
||||
func (t *sqlite3Test) TestCompileCreate() {
|
||||
bp := schema.NewBlueprint("users")
|
||||
bp.Create()
|
||||
bp.Charset("utf8mb4")
|
||||
bp.Charset = "utf8mb4"
|
||||
|
||||
bp.BigIncrements("id").AutoIncrement().Comment("ID")
|
||||
bp.Boolean("enabled").Default("1").Comment("是否有效")
|
||||
|
||||
@@ -3,11 +3,11 @@ package sqlserver
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/dialect/sqlserver"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/v2/sqlgen"
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/dialect/sqlserver"
|
||||
"git.fsdpf.net/go/db/internal/sb"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"git.fsdpf.net/go/db/sqlgen"
|
||||
)
|
||||
|
||||
type SQLServer struct {
|
||||
@@ -39,7 +39,7 @@ func (this SQLServer) TableExists(table string) (bool, error) {
|
||||
|
||||
func (this SQLServer) CompileCreate(bp *schema.Blueprint) []string {
|
||||
temporary := db.L("CREATE")
|
||||
if bp.IsTemporary() {
|
||||
if bp.Temporary {
|
||||
temporary = db.L("CREATE")
|
||||
}
|
||||
columns := strings.Join(this.getAddedColumns(bp), ",\n")
|
||||
@@ -94,6 +94,35 @@ func (this SQLServer) CompileRename(bp *schema.Blueprint) []string {
|
||||
return []string{this.GenerateSQL("EXEC sp_rename ?, ?", db.T(bp.GetTable()), db.T(toName))}
|
||||
}
|
||||
|
||||
// 修改表备注
|
||||
func (this SQLServer) CompileModifyComment(bp *schema.Blueprint) []string {
|
||||
return []string{
|
||||
this.GenerateSQL(`
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM sys.extended_properties
|
||||
WHERE major_id = OBJECT_ID(?)
|
||||
AND name = 'MS_Description'
|
||||
AND minor_id = 0
|
||||
)
|
||||
BEGIN
|
||||
EXEC sp_updateextendedproperty
|
||||
@name = N'MS_Description',
|
||||
@value = ?,
|
||||
@level0type = N'SCHEMA', @level0name = 'dbo',
|
||||
@level1type = N'TABLE', @level1name = ?
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
EXEC sp_addextendedproperty
|
||||
@name = N'MS_Description',
|
||||
@value = ?,
|
||||
@level0type = N'SCHEMA', @level0name = 'dbo',
|
||||
@level1type = N'TABLE', @level1name = ?
|
||||
END
|
||||
`, db.T(bp.GetTable()), db.V(bp.Comment), db.T(bp.GetTable()), db.V(bp.Comment), db.T(bp.GetTable())),
|
||||
}
|
||||
}
|
||||
|
||||
func (this SQLServer) addModifiers(sql string, bp *schema.Blueprint, column *schema.ColumnDefinition) string {
|
||||
for _, modifier := range sqlServerDefaultModifiers {
|
||||
sql += this.GetColumnModifier(modifier, bp, column)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db/v2/engine"
|
||||
"git.fsdpf.net/go/db/v2/schema"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db"
|
||||
)
|
||||
|
||||
type Schema interface {
|
||||
@@ -27,6 +27,8 @@ type Schema interface {
|
||||
CompileDropColumn(bp *Blueprint) []string
|
||||
// 表重命名
|
||||
CompileRename(bp *Blueprint) []string
|
||||
// 修改表备注
|
||||
CompileModifyComment(bp *Blueprint) []string
|
||||
// 生成SQL
|
||||
GenerateSQL(sql string, args ...any) string
|
||||
}
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func PrefixArray(prefix string, values []string) (items []string) {
|
||||
for _, value := range values {
|
||||
items = append(items, prefix+" "+value)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func QuoteString(value any) string {
|
||||
switch v := value.(type) {
|
||||
case []string:
|
||||
return strings.Join(lo.Map(v, func(item string, _ int) string {
|
||||
return "'" + item + "'"
|
||||
}), ", ")
|
||||
case string:
|
||||
return "'" + v + "'"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user