using Invercargill.DataStructures; using InvercargillSql.Orm; namespace InvercargillSql.Migrations { /** * Column builder for migrations that provides a fluent API for configuring column definitions. * * This builder is used within migration operations to configure column properties. * All configuration methods return this builder for method chaining. * * Example usage within a migration: * {{{ * b.create_table("users") * .column("id", c => c.type_int().primary_key().auto_increment()) * .column("email", c => c.type_text().not_null().unique()) * .execute(); * }}} */ public class MigrationColumnBuilder : Object { private MigrationBuilder? _migration_parent; private TableBuilder? _table_parent; private AlterTableBuilder? _alter_parent; private ColumnDefinition _column; private string? _table_name; // Index support private bool _should_create_index = false; private string? _index_name = null; // Foreign key support private ForeignKeyBuilder? _fk_builder = null; /** * Protected constructor for subclasses like ForeignKeyBuilder. */ protected MigrationColumnBuilder.for_subclass() { _column = new ColumnDefinition(); } /** * Creates a new MigrationColumnBuilder with a MigrationBuilder parent. * * @param parent the parent MigrationBuilder to return to after configuration * @param table_name the name of the table this column belongs to * @param column the column definition being configured */ internal MigrationColumnBuilder(MigrationBuilder parent, string table_name, ColumnDefinition column) { _migration_parent = parent; _table_name = table_name; _column = column; } /** * Creates a new MigrationColumnBuilder with a TableBuilder parent. * * @param parent the parent TableBuilder to return to after configuration * @param column the column definition being configured */ internal MigrationColumnBuilder.for_table(TableBuilder parent, ColumnDefinition column) { _table_parent = parent; _column = column; } /** * Creates a new MigrationColumnBuilder with an AlterTableBuilder parent. * * @param parent the parent AlterTableBuilder to return to after configuration * @param table_name the name of the table this column belongs to * @param column the column definition being configured */ internal MigrationColumnBuilder.for_alter(AlterTableBuilder parent, string table_name, ColumnDefinition column) { _alter_parent = parent; _table_name = table_name; _column = column; } /** * Sets the column type to INTEGER. * * @return this builder for method chaining */ public MigrationColumnBuilder type_int() { _column.column_type = ColumnType.INT_64; return this; } /** * Sets the column type to TEXT. * * @return this builder for method chaining */ public MigrationColumnBuilder type_text() { _column.column_type = ColumnType.TEXT; return this; } /** * Sets the column type to REAL. * * @return this builder for method chaining */ public MigrationColumnBuilder type_real() { _column.column_type = ColumnType.DECIMAL; return this; } /** * Sets the column type to BLOB. * * @return this builder for method chaining */ public MigrationColumnBuilder type_blob() { _column.column_type = ColumnType.BINARY; return this; } /** * Sets the column type to DATETIME. * * @return this builder for method chaining */ public MigrationColumnBuilder type_datetime() { _column.column_type = ColumnType.DATETIME; return this; } /** * Sets the column type to BOOLEAN. * * @return this builder for method chaining */ public MigrationColumnBuilder type_boolean() { _column.column_type = ColumnType.BOOLEAN; return this; } /** * Marks this column as the primary key. * * Only one column per table should be marked as primary key. * * @return this builder for method chaining */ public MigrationColumnBuilder primary_key() { _column.is_primary_key = true; return this; } /** * Marks this column as NOT NULL. * * @return this builder for method chaining */ public MigrationColumnBuilder not_null() { _column.is_required = true; return this; } /** * Marks this column as UNIQUE. * * @return this builder for method chaining */ public MigrationColumnBuilder unique() { _column.is_unique = true; return this; } /** * Marks this column as auto-incrementing. * * Typically used for integer primary keys. * * @return this builder for method chaining */ public MigrationColumnBuilder auto_increment() { _column.auto_increment = true; return this; } /** * Sets a default value for this column. * * @param value the default value to use when inserting records * @return this builder for method chaining */ public MigrationColumnBuilder default_value(T value) { _column.default_value = new Invercargill.NativeElement(value); return this; } /** * Marks this column to use the current timestamp as default. * * Only applicable to DATETIME columns. * * @return this builder for method chaining */ public MigrationColumnBuilder default_now() { _column.default_now = true; return this; } /** * Adds a foreign key reference to another table. * * This method creates a ForeignKeyBuilder that allows configuring the FK * constraint with methods like .name(), .on_delete_cascade(), etc. * The ForeignKeyBuilder extends MigrationColumnBuilder, so column methods * can still be called after FK configuration. * * Example: * {{{ * t.column("user_id") * .not_null() * .references("users", "id") * .name("fk_orders_users") * .on_delete_cascade() * .indexed(); // Can continue with column methods * }}} * * @param table the referenced table name * @param column the referenced column name in the foreign table * @return a ForeignKeyBuilder for configuring the FK constraint */ public ForeignKeyBuilder references(string table, string column) { _fk_builder = new ForeignKeyBuilder(this, table, column); return _fk_builder; } /** * Marks this column to have an index created for it. * * The index uniqueness is automatically inferred from the column's is_unique property. * If a custom index name is needed, pass it as the name parameter. * * Example: * {{{ * // Basic index with auto-generated name (idx_{table}_{column}) * t.column("email").not_null().indexed(); * * // Unique index - uniqueness inferred from column's unique() flag * t.column("email").unique().indexed(); * * // Index with custom name * t.column("email").indexed("idx_users_email_address"); * }}} * * @param name optional custom index name; if null, auto-generated as idx_{table}_{column} * @return this builder for method chaining */ public MigrationColumnBuilder indexed(string? name = null) { _should_create_index = true; _index_name = name; return this; } /** * Whether an index should be created for this column. * TableBuilder uses this to determine if an index operation is needed. */ public bool should_create_index { get { return _should_create_index; } } /** * The custom index name, or null if auto-generation should be used. * Auto-generated format: idx_{table}_{column} */ public string? index_name { get { return _index_name; } } /** * The ForeignKeyBuilder if a foreign key was configured via references(). * TableBuilder uses this to collect FK constraints from column definitions. */ public ForeignKeyBuilder? fk_builder { get { return _fk_builder; } } /** * Returns to the parent MigrationBuilder. * * This method navigates through the parent chain to find the MigrationBuilder. * * @return the parent MigrationBuilder */ internal virtual MigrationBuilder return_to_migration() { if (_migration_parent != null) return _migration_parent; if (_table_parent != null) return _table_parent.return_to_migration(); if (_alter_parent != null) return _alter_parent.return_to_migration(); assert_not_reached(); } } }