Deveel.Data.Sql.Statements.AlterTableStatement.ExecuteStatement C# (CSharp) Méthode

ExecuteStatement() protected méthode

protected ExecuteStatement ( ExecutionContext context ) : void
context ExecutionContext
Résultat void
        protected override void ExecuteStatement(ExecutionContext context)
        {
            //if (!context.User.CanAlterTable(TableName))
            //	throw new InvalidAccessException(context.Request.UserName(), TableName);

            var table = context.Request.Access().GetTable(TableName);
            if (table == null)
                throw new ObjectNotFoundException(TableName);

            var tableInfo = table.TableInfo;
            var newTableInfo = new TableInfo(tableInfo.TableName);

            var checker = ColumnChecker.Default(context.Request, TableName);

            bool tableAltered = false;
            bool markDropped = false;

            for (int n = 0; n < tableInfo.ColumnCount; ++n) {
                var column = tableInfo[n];

                string columnName = column.ColumnName;
                var columnType = column.ColumnType;
                var defaultExpression = column.DefaultExpression;

                if (Action.ActionType == AlterTableActionType.SetDefault &&
                    CheckColumnNamesMatch(context.Request, ((SetDefaultAction)Action).ColumnName, columnName)) {
                    var exp = ((SetDefaultAction)Action).DefaultExpression;
                    exp = checker.CheckExpression(exp);
                    defaultExpression = exp;
                    tableAltered = true;
                } else if (Action.ActionType == AlterTableActionType.DropDefault &&
                           CheckColumnNamesMatch(context.Request, ((DropDefaultAction)Action).ColumnName, columnName)) {
                    defaultExpression = null;
                    tableAltered = true;
                } else if (Action.ActionType == AlterTableActionType.DropColumn &&
                           CheckColumnNamesMatch(context.Request, ((DropColumnAction)Action).ColumnName, columnName)) {
                    // Check there are no referential links to this column
                    var refs = context.Request.Access().QueryTableImportedForeignKeys(TableName);
                    foreach (var reference in refs) {
                        CheckColumnConstraint(columnName, reference.ForeignColumnNames, reference.ForeignTable, reference.ConstraintName);
                    }

                    // Or from it
                    refs = context.Request.Access().QueryTableForeignKeys(TableName);
                    foreach (var reference in refs) {
                        CheckColumnConstraint(columnName, reference.ColumnNames, reference.TableName, reference.ConstraintName);
                    }

                    // Or that it's part of a primary key
                    var primaryKey = context.Request.Access().QueryTablePrimaryKey(TableName);
                    if (primaryKey != null)
                        CheckColumnConstraint(columnName, primaryKey.ColumnNames, TableName, primaryKey.ConstraintName);

                    // Or that it's part of a unique set
                    var uniques = context.Request.Access().QueryTableUniqueKeys(TableName);
                    foreach (var unique in uniques) {
                        CheckColumnConstraint(columnName, unique.ColumnNames, TableName, unique.ConstraintName);
                    }

                    markDropped = true;
                    tableAltered = true;
                }

                var newColumn = new ColumnInfo(columnName, columnType);
                if (defaultExpression != null)
                    newColumn.DefaultExpression = defaultExpression;

                newColumn.IndexType = column.IndexType;
                newColumn.IsNotNull = column.IsNotNull;

                // If not dropped then add to the new table definition.
                if (!markDropped) {
                    newTableInfo.AddColumn(newColumn);
                }
            }

            if (Action.ActionType == AlterTableActionType.AddColumn) {
                var col = ((AddColumnAction)Action).Column;

                checker.CheckExpression(col.DefaultExpression);
                var columnName = col.ColumnName;
                var columnType = col.ColumnType;

                // If column name starts with [table_name]. then strip it off
                columnName = checker.StripTableName(TableName.Name, columnName);
                if (tableInfo.IndexOfColumn(col.ColumnName) != -1)
                    throw new InvalidOperationException("The column '" + col.ColumnName + "' is already in the table '" + tableInfo.TableName + "'.");

                var newColumn = new ColumnInfo(columnName, columnType) {
                    IsNotNull = col.IsNotNull,
                    DefaultExpression = col.DefaultExpression
                };

                newTableInfo.AddColumn(newColumn);
                tableAltered = true;
            }

            if (Action.ActionType == AlterTableActionType.DropConstraint) {
                string constraintName = ((DropConstraintAction)Action).ConstraintName;
                int dropCount = context.Request.Access().DropTableConstraint(TableName, constraintName);
                if (dropCount == 0)
                    throw new InvalidOperationException("Named constraint to drop on table " + TableName + " was not found: " + constraintName);
            } else if (Action.ActionType == AlterTableActionType.DropPrimaryKey) {
                if (!context.Request.Access().DropTablePrimaryKey(TableName, null))
                    throw new InvalidOperationException("No primary key to delete on table " + TableName);
            }

            if (Action.ActionType == AlterTableActionType.AddConstraint) {
                var constraint = ((AddConstraintAction)Action).Constraint;
                bool foreignConstraint = (constraint.ConstraintType == ConstraintType.ForeignKey);

                ObjectName refTname = null;
                if (foreignConstraint) {
                    refTname = context.Request.Access().ResolveTableName(constraint.ReferenceTable);
                }

                var columnNames = checker.StripColumnList(TableName.FullName, constraint.Columns);
                columnNames = checker.StripColumnList(constraint.ReferenceTable, columnNames);
                var expression = checker.CheckExpression(constraint.CheckExpression);
                columnNames = checker.CheckColumns(columnNames);

                IEnumerable<string> refCols = null;
                if (foreignConstraint && constraint.ReferenceColumns != null) {
                    var referencedChecker = ColumnChecker.Default(context.Request, refTname);
                    refCols = referencedChecker.CheckColumns(constraint.ReferenceColumns);
                }

                var newConstraint = new ConstraintInfo(constraint.ConstraintName, constraint.ConstraintType, TableName, columnNames.ToArray());
                if (foreignConstraint) {
                    if (refCols == null)
                        throw new InvalidOperationException("Could not create a Foreign Key constraint with no reference columns");

                    newConstraint.ForeignTable = refTname;
                    newConstraint.ForeignColumnNames = refCols.ToArray();
                    newConstraint.OnDelete = constraint.OnDelete;
                    newConstraint.OnUpdate = constraint.OnUpdate;
                }

                if (constraint.ConstraintType == ConstraintType.Check)
                    newConstraint.CheckExpression = expression;

                context.Request.Access().AddConstraint(TableName, newConstraint);
            }

            // Alter the existing table to the new format...
            if (tableAltered) {
                if (newTableInfo.ColumnCount == 0)
                    throw new InvalidOperationException("Can not ALTER table to have 0 columns.");

                context.DirectAccess.AlterObject(newTableInfo);
            } else {
                // If the table wasn't physically altered, check the constraints.
                // Calling this method will also make the transaction check all
                // deferred constraints during the next commit.
                context.Request.Access().CheckConstraintViolations(TableName);
            }
        }