schema

package
v0.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2025 License: GPL-3.0 Imports: 19 Imported by: 0

Documentation

Overview

Package schema provides schema migration generation for ClickHouse.

This package compares current and target schemas to generate executable migration files with SQL statements. It supports all major ClickHouse schema objects including databases, tables, dictionaries, and views, ensuring safe and predictable migrations for ClickHouse deployments.

Key features:

  • Intelligent diff detection between current and target schemas
  • Generation of executable DDL statements (not just comments)
  • Proper operation ordering for safe migrations
  • Complete support for all schema objects: databases, tables, dictionaries, views
  • Smart rename detection to avoid unnecessary DROP+CREATE operations
  • Different migration strategies for different object types
  • Error handling for unsupported operations (engine/cluster changes)
  • Comprehensive testing with YAML fixtures and table-driven tests

Supported Operations:

  • Database operations: CREATE, ALTER, ATTACH, DETACH, DROP, RENAME DATABASE
  • Table operations: CREATE, ALTER, ATTACH, DETACH, DROP, RENAME TABLE
  • Dictionary operations: CREATE OR REPLACE, ATTACH, DETACH, DROP, RENAME DICTIONARY
  • View operations: CREATE, ALTER, ATTACH, DETACH, DROP, RENAME for both regular and materialized views

Migration Strategies:

  • Databases: Standard CREATE, ALTER, DROP operations
  • Tables: Full DDL support including column modifications
  • Dictionaries: CREATE OR REPLACE for modifications (since they can't be altered)
  • Regular Views: CREATE OR REPLACE for modifications
  • Materialized Views: DROP+CREATE for query changes (more reliable than ALTER TABLE MODIFY QUERY)
  • Integration Engine Tables: DROP+CREATE for all modifications (required due to read-only nature)

The migration generation process:

  1. Parse current schema state (from ClickHouse or SQL files)
  2. Parse target schema state (from SQL files)
  3. Compare the two states using intelligent algorithms
  4. Generate appropriate DDL for each difference with correct strategies
  5. Order operations correctly (databases → tables → dictionaries → views; CREATE → ALTER → RENAME → DROP)

Example usage:

// Parse current schema (from ClickHouse or existing SQL files)
currentSQL, _ := parser.ParseString("CREATE DATABASE analytics;")

// Parse target schema (from SQL string or file)
targetSQL, _ := parser.ParseString(targetSchemaString)

// Generate diff
diff, err := schema.GenerateDiff(
    currentSQL,
    targetSQL
)
if err != nil {
    // Handle error (e.g., unsupported operation like engine changes)
    log.Fatalf("Migration generation failed: %v", err)
}

// Format and write timestamped migration file
timestamp := time.Now().Format("20060102150405")
migrationFile := fmt.Sprintf("%s_migration.sql", timestamp)

var buf bytes.Buffer
format.FormatSQL(&buf, format.Defaults, diff)
os.WriteFile(migrationFile, buf.Bytes(), consts.ModeFile)

The package will return errors for operations that cannot be safely automated, such as database engine changes or cluster modifications. For integration engines and materialized views, it automatically uses DROP+CREATE strategies instead of reporting errors, ensuring migrations are both safe and executable.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnsupported is returned for operations that are fundamentally unsupported by ClickHouse
	ErrUnsupported = errors.New("unsupported operation")
	// ErrDictionaryAlter is returned when attempting to use ALTER operations on dictionaries
	ErrDictionaryAlter = errors.New("dictionary ALTER operations not supported")
	// ErrClusterChange is returned when attempting to change cluster configuration
	ErrClusterChange = errors.New("cluster configuration changes not supported")
	// ErrEngineChange is returned when attempting to change engine types
	ErrEngineChange = errors.New("engine type changes not supported")
	// ErrSystemObject is returned when attempting to modify system objects
	ErrSystemObject = errors.New("system object modifications not supported")
	// ErrInvalidType is returned for invalid type combinations
	ErrInvalidType = errors.New("invalid type combination")
	// ErrInvalidClause is returned when unsupported clauses are used with specific engines
	ErrInvalidClause = errors.New("invalid clause for engine type")
)

Invalid migration operation errors

View Source
var ErrNoDiff = errors.New("no differences found")

ErrNoDiff is returned when no differences are found between current and target schemas

Functions

func Compile

func Compile(path string, w io.Writer) error

Compile recursively compiles a schema file and its imports. It processes import directives (lines starting with "-- housekeeper:import") and includes the referenced files' contents in the output. Import paths are resolved relative to the current file's directory.

Example:

var buf bytes.Buffer
err := schema.Compile("db/main.sql", &buf)
if err != nil {
	log.Fatal(err)
}

// The compiled schema is now in buf
compiledSQL := buf.String()

// Parse the compiled schema
sql, err := parser.ParseString(compiledSQL)
if err != nil {
	log.Fatal(err)
}

func DetectNestedGroups added in v0.1.6

func DetectNestedGroups(columns []ColumnInfo) map[string][]ColumnInfo

DetectNestedGroups identifies groups of dotted columns that could potentially represent flattened Nested structures. This function analyzes a set of columns and groups together those that appear to be flattened representations of Nested types.

The function looks for columns with names containing dots where:

  • Multiple columns share the same prefix (before the first dot)
  • All columns in the group have Array data types
  • Groups with only one column are filtered out (unlikely to be Nested)

This is useful for:

  • Validation and debugging of flattened schemas
  • Reverse engineering original Nested structure from ClickHouse output
  • Schema analysis and documentation

Parameters:

  • columns: A slice of ColumnInfo to analyze for potential Nested groupings

Returns a map where:

  • Key: The prefix name (e.g., "profile" for "profile.name", "profile.age")
  • Value: A slice of ColumnInfo representing the potential Nested fields

Example:

Input: [`profile.name` Array(String), `profile.age` Array(UInt8), `metadata.key` Array(String)]
Output: {"profile": [profile.name, profile.age]} (metadata.key ignored - only one column)

func FilterExcluding added in v0.1.9

func FilterExcluding[T SchemaObject](from, exclude map[string]T) []string

FilterExcluding returns sorted keys from 'from' that don't exist in 'exclude'. Useful for finding objects to drop (exist in current but not in target).

func GenerateDiff

func GenerateDiff(current, target *parser.SQL) (*parser.SQL, error)

GenerateDiff creates a diff by comparing current and target schema states. It analyzes the differences between the current schema and the desired target schema, then generates appropriate DDL statements.

The migration includes all schema objects (roles, functions, databases, tables, dictionaries, views), processing them in the correct order: Roles → Functions → Databases → Named Collections → Tables → Dictionaries → Views (CREATE → ALTER → RENAME → DROP)

Migration strategies for different object types:

  • Roles: Standard DDL operations (CREATE, ALTER, DROP, RENAME, GRANT, REVOKE)
  • Functions: DROP+CREATE for modifications (since they can't be altered)
  • Databases: Standard DDL operations (CREATE, ALTER, DROP, RENAME)
  • Named Collections: Standard DDL operations (CREATE, ALTER, DROP)
  • Tables: Full DDL support including column modifications (CREATE, ALTER, DROP, RENAME)
  • Dictionaries: CREATE OR REPLACE for modifications (since they can't be altered)
  • Regular Views: CREATE OR REPLACE for modifications
  • Materialized Views: DROP+CREATE for query modifications (more reliable than ALTER TABLE MODIFY QUERY)

The function returns a *parser.SQL containing the migration statements, or an error if:

  • No differences are found between current and target schemas (returns ErrNoDiff)
  • An unsupported operation is detected (e.g., engine or cluster changes)
  • Schema comparison fails for any object type
  • Generated SQL cannot be parsed back into statements

Example:

currentSQL := `
	CREATE DATABASE analytics ENGINE = Atomic COMMENT 'Old comment';
	CREATE TABLE analytics.events (id UInt64, name String) ENGINE = MergeTree() ORDER BY id;
`
targetSQL := `
	CREATE DATABASE analytics ENGINE = Atomic COMMENT 'New comment';
	CREATE TABLE analytics.events (id UInt64, name String, timestamp DateTime) ENGINE = MergeTree() ORDER BY id;
	CREATE DICTIONARY analytics.users_dict (id UInt64) PRIMARY KEY id SOURCE(HTTP(url 'test')) LAYOUT(FLAT()) LIFETIME(600);
	CREATE VIEW analytics.daily_stats AS SELECT date, count() FROM events GROUP BY date;
`

current, _ := parser.ParseString(currentSQL)
target, _ := parser.ParseString(targetSQL)

diff, err := GenerateDiff(current, target)
if err != nil {
	log.Fatal(err)
}

// Format the migration SQL for output
var buf bytes.Buffer
format.FormatSQL(&buf, format.Defaults, diff)
fmt.Println(buf.String())

func GenerateMigrationFile

func GenerateMigrationFile(migrationDir string, current, target *parser.SQL) (string, error)

GenerateMigrationFile creates a timestamped migration file by comparing current and target schemas. The migration file is named using UTC timestamp in yyyyMMddhhmmss format and written to the specified directory. Returns the generated filename and any error encountered.

Parameters:

  • migrationDir: Directory where the migration file should be written
  • current: Current schema state
  • target: Target schema state

Returns:

  • filename: The generated migration filename (e.g., "20240806143022.sql")
  • error: Any error encountered during generation or file writing (returns ErrNoDiff if no differences found)

Example:

filename, err := GenerateMigrationFile("/path/to/migrations", currentSchema, targetSchema)
// Creates: /path/to/migrations/20240806143022.sql

func SortedKeys added in v0.1.9

func SortedKeys[T SchemaObject](m map[string]T) []string

SortedKeys returns sorted keys from a SchemaObject map. This provides deterministic iteration order for comparison operations.

Types

type ColumnDiff

type ColumnDiff struct {
	Type        ColumnDiffType // Type of column operation
	ColumnName  string         // Name of the column
	Current     *ColumnInfo    // Current column definition (nil for ADD)
	Target      *ColumnInfo    // Target column definition (nil for DROP)
	Description string         // Human-readable description
}

ColumnDiff represents a difference in column definitions

type ColumnDiffType

type ColumnDiffType string

ColumnDiffType represents the type of column difference

const (
	// ColumnDiffAdd indicates a column needs to be added
	ColumnDiffAdd ColumnDiffType = "ADD"
	// ColumnDiffDrop indicates a column needs to be dropped
	ColumnDiffDrop ColumnDiffType = "DROP"
	// ColumnDiffModify indicates a column needs to be modified
	ColumnDiffModify ColumnDiffType = "MODIFY"
)

type ColumnInfo

type ColumnInfo struct {
	Name        string              // Column name
	DataType    *parser.DataType    // Data type AST
	DefaultType string              // Default type: DEFAULT, MATERIALIZED, EPHEMERAL, ALIAS
	Default     *parser.Expression  // Default expression AST
	Codec       *parser.CodecClause // Codec AST
	TTL         *parser.TTLClause   // TTL AST
	Comment     string              // Column comment
}

ColumnInfo represents a single column definition

func ConvertNestedToFlattened added in v0.1.6

func ConvertNestedToFlattened(nested *parser.NestedType, prefix string, originalCol ColumnInfo) []ColumnInfo

ConvertNestedToFlattened converts a Nested data type to multiple Array columns with dotted names. This function takes a ClickHouse Nested type definition and expands it into the equivalent flattened representation that ClickHouse uses internally.

Parameters:

  • nested: The parsed Nested type from the DDL
  • prefix: The column name that will be used as the prefix for dotted names
  • originalCol: The original column info to preserve properties like DEFAULT, TTL, etc.

Example transformation:

Nested(name String, age UInt8) with prefix "profile"
becomes:
profile.name Array(String), profile.age Array(UInt8)

Properties from the original column (DEFAULT, TTL, CODEC, COMMENT) are preserved on each flattened column, maintaining consistency with the original definition.

Returns a slice of ColumnInfo representing the flattened Array columns.

func (ColumnInfo) Equal added in v0.1.3

func (c ColumnInfo) Equal(other ColumnInfo) bool

Equal compares two ColumnInfo instances for equality using AST comparison

type DatabaseDiff

type DatabaseDiff struct {
	DiffBase               // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current  *DatabaseInfo // Current state (nil if database doesn't exist)
	Target   *DatabaseInfo // Target state (nil if database should be dropped)
}

DatabaseDiff represents a difference between current and target database states. It contains all information needed to generate migration SQL statements for database operations including CREATE, ALTER, DROP, and RENAME.

type DatabaseDiffType

type DatabaseDiffType string

DatabaseDiffType represents the type of database difference

const (
	// DatabaseDiffCreate indicates a database needs to be created
	DatabaseDiffCreate DatabaseDiffType = "CREATE"
	// DatabaseDiffDrop indicates a database needs to be dropped
	DatabaseDiffDrop DatabaseDiffType = "DROP"
	// DatabaseDiffAlter indicates a database needs to be altered
	DatabaseDiffAlter DatabaseDiffType = "ALTER"
	// DatabaseDiffRename indicates a database needs to be renamed
	DatabaseDiffRename DatabaseDiffType = "RENAME"
)

type DatabaseInfo

type DatabaseInfo struct {
	Name    string // Database name
	Engine  string // Engine type (e.g., "Atomic", "MySQL", "Memory")
	Comment string // Database comment (without quotes)
	Cluster string // Cluster name if specified (empty if not clustered)
}

DatabaseInfo represents parsed database information extracted from DDL statements. This structure contains all the properties needed for database comparison and migration generation, including metadata for cluster and engine configuration.

func (*DatabaseInfo) GetCluster added in v0.1.9

func (d *DatabaseInfo) GetCluster() string

GetCluster implements SchemaObject interface

func (*DatabaseInfo) GetName added in v0.1.9

func (d *DatabaseInfo) GetName() string

GetName implements SchemaObject interface

func (*DatabaseInfo) PropertiesMatch added in v0.1.9

func (d *DatabaseInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two databases have identical properties (excluding name).

type DictionaryDiff

type DictionaryDiff struct {
	DiffBase                 // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current  *DictionaryInfo // Current state (nil if dictionary doesn't exist)
	Target   *DictionaryInfo // Target state (nil if dictionary should be dropped)
}

DictionaryDiff represents a difference between current and target dictionary states. It contains all information needed to generate migration SQL statements for dictionary operations including CREATE, DROP, REPLACE, and RENAME.

type DictionaryDiffType

type DictionaryDiffType string

DictionaryDiffType represents the type of dictionary difference

const (
	// DictionaryDiffCreate indicates a dictionary needs to be created
	DictionaryDiffCreate DictionaryDiffType = "CREATE"
	// DictionaryDiffDrop indicates a dictionary needs to be dropped
	DictionaryDiffDrop DictionaryDiffType = "DROP"
	// DictionaryDiffReplace indicates a dictionary needs to be replaced (since dictionaries can't be altered)
	DictionaryDiffReplace DictionaryDiffType = "REPLACE"
	// DictionaryDiffRename indicates a dictionary needs to be renamed
	DictionaryDiffRename DictionaryDiffType = "RENAME"
)

type DictionaryInfo

type DictionaryInfo struct {
	Name      string                       // Dictionary name
	Database  string                       // Database name (empty for default database)
	Cluster   string                       // Cluster name if specified (empty if not clustered)
	Comment   string                       // Dictionary comment (without quotes)
	Statement *parser.CreateDictionaryStmt // Full parsed CREATE DICTIONARY statement for deep comparison
}

DictionaryInfo represents parsed dictionary information extracted from DDL statements. This structure contains all the properties needed for dictionary comparison and migration generation, including the full parsed statement for deep comparison.

func (*DictionaryInfo) GetCluster added in v0.1.9

func (d *DictionaryInfo) GetCluster() string

GetCluster implements SchemaObject interface

func (*DictionaryInfo) GetName added in v0.1.9

func (d *DictionaryInfo) GetName() string

GetName implements SchemaObject interface. Returns the fully-qualified name (database.name or just name).

func (*DictionaryInfo) PropertiesMatch added in v0.1.9

func (d *DictionaryInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two dictionaries have identical properties (excluding name).

type DiffBase added in v0.1.9

type DiffBase struct {
	// Type is the operation type (CREATE, ALTER, DROP, RENAME, REPLACE, etc.)
	Type string

	// Name is the name of the object being modified
	Name string

	// NewName is the new name for rename operations (empty otherwise)
	NewName string

	// Description is a human-readable description of the change
	Description string

	// UpSQL is the SQL to apply the change (forward migration)
	UpSQL string

	// DownSQL is the SQL to rollback the change (reverse migration)
	DownSQL string
}

DiffBase contains the common fields shared by all diff types (DatabaseDiff, TableDiff, DictionaryDiff, ViewDiff, FunctionDiff, RoleDiff).

Embedding this struct in diff types eliminates the need to implement GetDiffType() and GetUpSQL() methods on each type individually.

Example usage:

type DatabaseDiff struct {
    DiffBase
    // Database-specific fields...
}

func (*DiffBase) GetDiffType added in v0.1.9

func (d *DiffBase) GetDiffType() string

GetDiffType implements diffProcessor interface

func (*DiffBase) GetUpSQL added in v0.1.9

func (d *DiffBase) GetUpSQL() string

GetUpSQL implements diffProcessor interface

type FunctionDiff added in v0.1.2

type FunctionDiff struct {
	DiffBase               // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current  *FunctionInfo // Current state (nil if function doesn't exist)
	Target   *FunctionInfo // Target state (nil if function should be dropped)
}

FunctionDiff represents a difference between current and target function states. It contains all information needed to generate migration SQL statements for function operations including CREATE, DROP, REPLACE, and RENAME.

type FunctionDiffType added in v0.1.2

type FunctionDiffType string

FunctionDiffType represents the type of function difference

const (
	// FunctionDiffCreate indicates a function needs to be created
	FunctionDiffCreate FunctionDiffType = "CREATE"
	// FunctionDiffDrop indicates a function needs to be dropped
	FunctionDiffDrop FunctionDiffType = "DROP"
	// FunctionDiffReplace indicates a function needs to be replaced (functions use DROP+CREATE for modifications)
	FunctionDiffReplace FunctionDiffType = "REPLACE"
	// FunctionDiffRename indicates a function needs to be renamed
	FunctionDiffRename FunctionDiffType = "RENAME"
)

type FunctionInfo added in v0.1.2

type FunctionInfo struct {
	Name       string             // Function name
	Parameters []string           // Function parameter names
	Expression *parser.Expression // Function expression/body AST
	Cluster    string             // Cluster name if specified (empty if not clustered)
}

FunctionInfo represents parsed function information extracted from DDL statements. This structure contains all the properties needed for function comparison and migration generation, including parameters, expression, and cluster configuration.

func (*FunctionInfo) GetCluster added in v0.1.9

func (f *FunctionInfo) GetCluster() string

GetCluster implements SchemaObject interface

func (*FunctionInfo) GetName added in v0.1.9

func (f *FunctionInfo) GetName() string

GetName implements SchemaObject interface

func (*FunctionInfo) PropertiesMatch added in v0.1.9

func (f *FunctionInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two functions have identical properties (excluding name).

type GrantInfo added in v0.1.2

type GrantInfo struct {
	Grantee    string   // Role or user receiving the grant
	Privileges []string // List of privileges or roles granted
	OnTarget   string   // Target object (database.table or *.*)
	WithGrant  bool     // WITH GRANT OPTION
	WithAdmin  bool     // WITH ADMIN OPTION
	Cluster    string   // Cluster name if specified
}

GrantInfo represents parsed grant/privilege information

type RenamePair added in v0.1.9

type RenamePair struct {
	OldName string
	NewName string
}

RenamePair represents a rename operation from OldName to NewName

func DetectRenames added in v0.1.9

func DetectRenames[T SchemaObject](current, target map[string]T) (
	renames []RenamePair,
	remainingCurrent map[string]T,
	remainingTarget map[string]T,
)

DetectRenames identifies potential rename operations between current and target states.

The algorithm finds objects that: 1. Exist in current but not in target (by name) 2. Have a matching object in target (by properties, excluding name) 3. That target object doesn't exist in current (by name)

When all three conditions are met, it's detected as a rename operation.

Returns:

  • renames: Slice of RenamePair indicating detected rename operations
  • remainingCurrent: Map of current objects that weren't renamed (for drop detection)
  • remainingTarget: Map of target objects that weren't renamed (for create detection)

Type parameter T must implement SchemaObject interface.

type RoleDiff added in v0.1.2

type RoleDiff struct {
	DiffBase           // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current  *RoleInfo // Current state (nil if role doesn't exist)
	Target   *RoleInfo // Target state (nil if role should be dropped)
}

RoleDiff represents a difference between current and target role states. It contains all information needed to generate migration SQL statements for role operations including CREATE, ALTER, DROP, RENAME, GRANT, and REVOKE.

type RoleDiffType added in v0.1.2

type RoleDiffType string

RoleDiffType represents the type of role difference

const (
	// RoleDiffCreate indicates a role needs to be created
	RoleDiffCreate RoleDiffType = "CREATE"
	// RoleDiffDrop indicates a role needs to be dropped
	RoleDiffDrop RoleDiffType = "DROP"
	// RoleDiffAlter indicates a role needs to be altered
	RoleDiffAlter RoleDiffType = "ALTER"
	// RoleDiffRename indicates a role needs to be renamed
	RoleDiffRename RoleDiffType = "RENAME"
	// RoleDiffGrant indicates privileges need to be granted
	RoleDiffGrant RoleDiffType = "GRANT"
	// RoleDiffRevoke indicates privileges need to be revoked
	RoleDiffRevoke RoleDiffType = "REVOKE"
)

type RoleInfo added in v0.1.2

type RoleInfo struct {
	Name     string            // Role name
	Settings map[string]string // Role settings (key-value pairs)
	Cluster  string            // Cluster name if specified (empty if not clustered)
}

RoleInfo represents parsed role information extracted from DDL statements. This structure contains all the properties needed for role comparison and migration generation, including settings and cluster configuration.

func (*RoleInfo) GetCluster added in v0.1.9

func (r *RoleInfo) GetCluster() string

GetCluster implements SchemaObject interface

func (*RoleInfo) GetName added in v0.1.9

func (r *RoleInfo) GetName() string

GetName implements SchemaObject interface

func (*RoleInfo) PropertiesMatch added in v0.1.9

func (r *RoleInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two roles have identical properties (excluding name).

type SchemaObject added in v0.1.9

type SchemaObject interface {
	// GetName returns the fully-qualified name of the schema object.
	// For objects with database prefixes (e.g., tables), this returns "db.name".
	// For global objects (e.g., databases), this returns just the name.
	GetName() string

	// GetCluster returns the cluster name if the object is clustered,
	// or an empty string if not clustered.
	GetCluster() string

	// PropertiesMatch returns true if this object has the same properties
	// as the other object, excluding the name. This is used for rename detection:
	// if two objects have different names but matching properties, it's a rename.
	//
	// Callers should pass the same concrete type as the receiver for the other parameter,
	// but implementations must still perform type checking via type assertion.
	PropertiesMatch(other SchemaObject) bool
}

SchemaObject is the interface implemented by all schema object Info types (DatabaseInfo, TableInfo, DictionaryInfo, ViewInfo, FunctionInfo, RoleInfo).

This interface enables generic algorithms for rename detection and comparison across all object types without type-specific code duplication.

type TableDiff

type TableDiff struct {
	DiffBase                   // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current       *TableInfo   // Current state (nil if table doesn't exist)
	Target        *TableInfo   // Target state (nil if table should be dropped)
	ColumnChanges []ColumnDiff // For ALTER operations - specific column changes
}

TableDiff represents a difference between current and target table states. It contains all information needed to generate migration SQL statements for table operations including CREATE, ALTER, DROP, and RENAME.

type TableDiffType

type TableDiffType string

TableDiffType represents the type of table difference

const (
	// TableDiffCreate indicates a table needs to be created
	TableDiffCreate TableDiffType = "CREATE"
	// TableDiffDrop indicates a table needs to be dropped
	TableDiffDrop TableDiffType = "DROP"
	// TableDiffAlter indicates a table needs to be altered
	TableDiffAlter TableDiffType = "ALTER"
	// TableDiffRename indicates a table needs to be renamed
	TableDiffRename TableDiffType = "RENAME"
)

type TableInfo

type TableInfo struct {
	Name          string              // Table name (without database prefix)
	Database      string              // Database name (empty if not specified)
	Engine        *parser.TableEngine // Engine AST
	Cluster       string              // Cluster name for distributed tables
	Comment       string              // Table comment
	OrderBy       *parser.Expression  // ORDER BY expression AST
	PartitionBy   *parser.Expression  // PARTITION BY expression AST
	PrimaryKey    *parser.Expression  // PRIMARY KEY expression AST
	SampleBy      *parser.Expression  // SAMPLE BY expression AST
	TTL           *parser.Expression  // Table-level TTL expression AST
	Settings      map[string]string   // Table settings
	Columns       []ColumnInfo        // Column definitions
	OrReplace     bool                // Whether CREATE OR REPLACE was used
	IfNotExists   bool                // Whether IF NOT EXISTS was used
	AsSourceTable *string             // If this table uses AS, the source table name (qualified)
	AsDependents  map[string]bool     // Tables that use AS to reference this table
}

TableInfo represents parsed table information extracted from DDL statements. This structure contains all the properties needed for table comparison and migration generation, including columns, engine, and other table options.

func FlattenNestedColumns added in v0.1.6

func FlattenNestedColumns(table *TableInfo) *TableInfo

FlattenNestedColumns creates a copy of TableInfo with Nested columns converted to dotted Array columns. This is used for accurate schema comparison since ClickHouse internally represents Nested columns as separate Array columns with dotted names.

Example transformation:

profile Nested(name String, age UInt8)
becomes:
profile.name Array(String), profile.age Array(UInt8)

The original TableInfo is not modified; a new copy is returned. Properties like DEFAULT, TTL, CODEC, and COMMENT from the original Nested column are preserved on each flattened Array column.

func (*TableInfo) Equal added in v0.1.3

func (t *TableInfo) Equal(other *TableInfo) bool

Equal compares two TableInfo instances for equality using AST comparison

func (*TableInfo) GetCluster added in v0.1.9

func (t *TableInfo) GetCluster() string

GetCluster implements SchemaObject interface.

func (*TableInfo) GetName added in v0.1.9

func (t *TableInfo) GetName() string

GetName implements SchemaObject interface. Returns the full table name (database.name or just name).

func (*TableInfo) PropertiesMatch added in v0.1.9

func (t *TableInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two tables have identical properties (excluding name).

type ViewDiff

type ViewDiff struct {
	DiffBase                 // Embeds Type, Name, NewName, Description, UpSQL, DownSQL
	Current        *ViewInfo // Current state (nil if view doesn't exist)
	Target         *ViewInfo // Target state (nil if view should be dropped)
	IsMaterialized bool      // True if this is a materialized view
}

ViewDiff represents a difference between current and target view states. It handles both regular views and materialized views, with special handling for materialized views which can only be altered using ALTER TABLE MODIFY QUERY.

type ViewDiffType

type ViewDiffType string

ViewDiffType represents the type of view difference

const (
	// ViewDiffCreate indicates a view needs to be created
	ViewDiffCreate ViewDiffType = "CREATE"
	// ViewDiffDrop indicates a view needs to be dropped
	ViewDiffDrop ViewDiffType = "DROP"
	// ViewDiffAlter indicates a view needs to be altered (only for materialized views using ALTER TABLE MODIFY QUERY)
	ViewDiffAlter ViewDiffType = "ALTER"
	// ViewDiffRename indicates a view needs to be renamed (uses RENAME TABLE for both regular and materialized views)
	ViewDiffRename ViewDiffType = "RENAME"
)

type ViewInfo

type ViewInfo struct {
	Name           string                 // View name
	Database       string                 // Database name (empty for default database)
	Cluster        string                 // Cluster name if specified (empty if not clustered)
	IsMaterialized bool                   // True if this is a materialized view
	OrReplace      bool                   // True if created with OR REPLACE
	Query          string                 // Query string for validation compatibility
	Statement      *parser.CreateViewStmt // Full parsed CREATE VIEW statement for deep comparison
}

ViewInfo represents parsed view information extracted from DDL statements. This structure contains all the properties needed for view comparison and migration generation, including whether it's a materialized view.

func (*ViewInfo) GetCluster added in v0.1.9

func (v *ViewInfo) GetCluster() string

GetCluster implements SchemaObject interface.

func (*ViewInfo) GetName added in v0.1.9

func (v *ViewInfo) GetName() string

GetName implements SchemaObject interface. Returns the full view name (database.name or just name).

func (*ViewInfo) PropertiesMatch added in v0.1.9

func (v *ViewInfo) PropertiesMatch(other SchemaObject) bool

PropertiesMatch implements SchemaObject interface. Returns true if the two views have identical properties (excluding name).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL