예제 #1
0
        private ITable FindViewEntry(ObjectName viewName)
        {
            var table = Transaction.GetTable(SystemSchema.ViewTableName);

            var schemav = table.GetResolvedColumnName(0);
            var namev   = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                using (var query = session.CreateQuery()) {
                    var t = table.SimpleSelect(query, namev, SqlExpressionType.Equal,
                                               SqlExpression.Constant(DataObject.String(viewName.Name)));
                    t = t.ExhaustiveSelect(query,
                                           SqlExpression.Equal(SqlExpression.Reference(schemav), SqlExpression.Constant(viewName.ParentName)));

                    // This should be at most 1 row in size
                    if (t.RowCount > 1)
                    {
                        throw new ArgumentException(String.Format("Multiple view entries for name '{0}' in the system.", viewName));
                    }

                    // Return the entries found.
                    return(t);
                }
            }
        }
예제 #2
0
        private ITable FindEntry(ObjectName routineName)
        {
            var table = transaction.GetTable(RoutineTableName);

            var schemav = table.GetResolvedColumnName(1);
            var namev   = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(transaction)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal,
                                               SqlExpression.Constant(Field.String(routineName.Name)));
                    t = t.ExhaustiveSelect(context,
                                           SqlExpression.Equal(SqlExpression.Reference(schemav),
                                                               SqlExpression.Constant(Field.String(routineName.ParentName))));

                    // This should be at most 1 row in size
                    if (t.RowCount > 1)
                    {
                        throw new Exception("Assert failed: multiple procedure names for " + routineName);
                    }

                    // Return the entries found.
                    return(t);
                }
            }
        }
예제 #3
0
        public bool DropTrigger(ObjectName triggerName)
        {
            if (triggerName == null)
            {
                throw new ArgumentNullException("triggerName");
            }

            var table = transaction.GetMutableTable(TriggerTableName);

            var schemaName = triggerName.ParentName;
            var name       = triggerName.Name;

            var schemaCol = table.GetResolvedColumnName(0);
            var nameCol   = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(transaction)) {
                using (var query = session.CreateQuery()) {
                    var t = table.SimpleSelect(query, nameCol, SqlExpressionType.Equal, SqlExpression.Constant(name));
                    t = t.ExhaustiveSelect(query,
                                           SqlExpression.Equal(SqlExpression.Reference(schemaCol), SqlExpression.Constant(schemaName)));

                    if (t.RowCount == 0)
                    {
                        return(false);
                    }

                    table.Delete(t);

                    transaction.OnObjectDropped(DbObjectType.Trigger, triggerName);
                    return(true);
                }
            }
        }
예제 #4
0
        public View GetView(ObjectName viewName)
        {
            var viewTable = Transaction.GetTable(SystemSchema.ViewTableName);
            var e         = viewTable.GetEnumerator();

            while (e.MoveNext())
            {
                int row = e.Current.RowId.RowNumber;

                var cSchema = viewTable.GetValue(row, 0).Value.ToString();
                var cName   = viewTable.GetValue(row, 1).Value.ToString();

                if (viewName.ParentName.Equals(cSchema) &&
                    viewName.Name.Equals(cName))
                {
                    ViewInfo viewInfo;
                    if (!viewCache.TryGetValue(row, out viewInfo))
                    {
                        var blob = (SqlBinary)viewTable.GetValue(row, 3).Value;
                        using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                            using (var context = session.CreateQuery()) {
                                viewInfo = ViewInfo.Deserialize(blob.GetInput());
                            }
                        }

                        viewCache[row] = viewInfo;
                    }

                    return(new View(viewInfo));
                }
            }

            return(null);
        }
예제 #5
0
        public bool TypeExists(ObjectName typeName)
        {
            if (typesCache.ContainsKey(typeName))
            {
                return(true);
            }

            var table = Transaction.GetTable(TypeTableName);

            var schemaName = typeName.ParentName;
            var name       = typeName.Name;

            var schemaCol = table.GetResolvedColumnName(1);
            var nameCol   = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(Transaction)) {
                using (var query = session.CreateQuery()) {
                    var t = table.SimpleSelect(query, schemaCol, SqlExpressionType.Equal, SqlExpression.Constant(schemaName));

                    t = t.ExhaustiveSelect(query, SqlExpression.Equal(SqlExpression.Reference(nameCol), SqlExpression.Constant(name)));

                    if (t.RowCount > 1)
                    {
                        throw new InvalidOperationException(String.Format("Name '{0}' resolves to multiple types.", typeName));
                    }

                    return(t.RowCount == 1);
                }
            }
        }
예제 #6
0
        private ITable FindTrigger(ITable table, string schema, string name)
        {
            // Find all the trigger entries with this name
            var schemaColumn = table.GetResolvedColumnName(0);
            var nameColumn   = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(transaction, SystemSchema.Name)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, nameColumn, SqlExpressionType.Equal,
                                               SqlExpression.Constant(DataObject.String(name)));
                    return(t.ExhaustiveSelect(context,
                                              SqlExpression.Equal(SqlExpression.Reference(schemaColumn), SqlExpression.Constant(DataObject.String(schema)))));
                }
            }
        }
예제 #7
0
        private IEnumerable <TriggerInfo> FindTriggers(ObjectName tableName, TriggerEventType eventType)
        {
            var fullTableName = tableName.FullName;
            var eventTypeCode = (int)eventType;

            var table = transaction.GetTable(SystemSchema.TriggerTableName);

            if (table == null)
            {
                return(new TriggerInfo[0]);
            }

            var tableColumn     = table.GetResolvedColumnName(3);
            var eventTypeColumn = table.GetResolvedColumnName(4);

            ITable result;

            using (var session = new SystemSession(transaction, SystemSchema.Name)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, tableColumn, SqlExpressionType.Equal,
                                               SqlExpression.Constant(DataObject.String(fullTableName)));

                    result = t.ExhaustiveSelect(context,
                                                SqlExpression.Equal(SqlExpression.Reference(eventTypeColumn), SqlExpression.Constant(eventTypeCode)));
                }
            }

            if (result.RowCount == 0)
            {
                return(new TriggerInfo[0]);
            }

            var list = new List <TriggerInfo>();

            foreach (var row in result)
            {
                var triggerInfo = FormTrigger(row);

                //TODO: get the other information such has the body, the external method or the procedure
                //      if this is a non-callback

                list.Add(triggerInfo);
            }

            return(list.AsEnumerable());
        }
예제 #8
0
        private View GetViewAt(int offset)
        {
            var table = Transaction.GetTable(SystemSchema.ViewTableName);

            if (table == null)
            {
                throw new DatabaseSystemException(String.Format("System table '{0}' was not defined.", SystemSchema.ViewTableName));
            }

            var e = table.GetEnumerator();
            int i = 0;

            while (e.MoveNext())
            {
                var row = e.Current.RowId.RowNumber;

                if (i == offset)
                {
                    ViewInfo viewInfo;
                    if (!viewCache.TryGetValue(row, out viewInfo))
                    {
                        var binary = (ISqlBinary)table.GetValue(row, 3).Value;

                        using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                            using (var context = session.CreateQuery()) {
                                viewInfo = ViewInfo.Deserialize(binary.GetInput());
                            }
                        }

                        viewCache[row] = viewInfo;
                    }

                    return(new View(viewInfo));
                }

                ++i;
            }

            throw new ArgumentOutOfRangeException("offset");
        }
예제 #9
0
        public bool RoutineExists(ObjectName routineName)
        {
            if (routinesCache.ContainsKey(routineName))
            {
                return(true);
            }

            var table   = transaction.GetTable(RoutineTableName);
            var schemav = table.GetResolvedColumnName(1);
            var namev   = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(transaction)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal,
                                               SqlExpression.Constant(Field.String(routineName.Name)));
                    t = t.ExhaustiveSelect(context,
                                           SqlExpression.Equal(SqlExpression.Reference(schemav),
                                                               SqlExpression.Constant(Field.String(routineName.ParentName))));

                    return(t.RowCount == 1);
                }
            }
        }
예제 #10
0
        public View GetView(ObjectName viewName)
        {
            var viewTable = Transaction.GetTable(SystemSchema.ViewTableName);
            var e = viewTable.GetEnumerator();
            while (e.MoveNext()) {
                int row = e.Current.RowId.RowNumber;

                var cSchema = viewTable.GetValue(row, 0).Value.ToString();
                var cName = viewTable.GetValue(row, 1).Value.ToString();

                if (viewName.ParentName.Equals(cSchema) &&
                    viewName.Name.Equals(cName)) {

                    ViewInfo viewInfo;
                    if (!viewCache.TryGetValue(row, out viewInfo)) {
                        var blob = (SqlBinary)viewTable.GetValue(row, 3).Value;
                        using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                            using (var context = session.CreateQuery()) {

                                viewInfo = ViewInfo.Deserialize(blob.GetInput());
                            }
                        }

                        viewCache[row] = viewInfo;

                    }

                    return new View(viewInfo);
                }

            }

            return null;
        }
예제 #11
0
        public bool TypeExists(ObjectName typeName)
        {
            if (typesCache.ContainsKey(typeName))
                return true;

            var table = Transaction.GetTable(TypeTableName);

            var schemaName = typeName.ParentName;
            var name = typeName.Name;

            var schemaCol = table.GetResolvedColumnName(1);
            var nameCol = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(Transaction)) {
                using (var query = session.CreateQuery()) {
                    var t = table.SimpleSelect(query, schemaCol, SqlExpressionType.Equal, SqlExpression.Constant(schemaName));

                    t = t.ExhaustiveSelect(query, SqlExpression.Equal(SqlExpression.Reference(nameCol), SqlExpression.Constant(name)));

                    if (t.RowCount > 1)
                        throw new InvalidOperationException(String.Format("Name '{0}' resolves to multiple types.", typeName));

                    return t.RowCount == 1;
                }
            }
        }
예제 #12
0
        public UserType GetUserType(ObjectName typeName)
        {
            UserType userType;
            if (!typesCache.TryGetValue(typeName, out userType)) {
                var typeTable = Transaction.GetTable(TypeTableName);
                var membersTable = Transaction.GetTable(TypeMemberTableName);

                var schemaName = typeName.ParentName;
                var name = typeName.Name;

                var schemaColumn = typeTable.GetResolvedColumnName(1);
                var nameColumn = typeTable.GetResolvedColumnName(2);

                var idColumn = membersTable.GetResolvedColumnName(0);

                UserTypeInfo typeInfo;

                using (var session = new SystemSession(Transaction)) {
                    using (var query = session.CreateQuery()) {
                        var t = typeTable.SimpleSelect(query, schemaColumn, SqlExpressionType.Equal, SqlExpression.Constant(schemaName));

                        t = t.ExhaustiveSelect(query,
                            SqlExpression.Equal(SqlExpression.Reference(nameColumn), SqlExpression.Constant(name)));

                        if (t.RowCount == 0)
                            return null;

                        var id = t.GetValue(0, 0);

                        var parentField = t.GetValue(0, 3);
                        ObjectName parentType = null;
                        if (!Field.IsNullField(parentField)) {
                            parentType = ObjectName.Parse(parentField.Value.ToString());
                        }

                        typeInfo = new UserTypeInfo(typeName, parentType);

                        var isSealedField = t.GetValue(0, 4);
                        var isAbstractField = t.GetValue(0, 5);

                        if (!Field.IsNullField(isSealedField)) {
                            typeInfo.IsSealed = (SqlBoolean) isSealedField.AsBoolean().Value;
                        }

                        if (!Field.IsNullField(isAbstractField)) {
                            typeInfo.IsAbstract = (SqlBoolean) isAbstractField.AsBoolean().Value;
                        }

                        var owner = t.GetValue(0, 6).Value.ToString();

                        typeInfo.Owner = owner;

                        var t2 = membersTable.SimpleSelect(query, idColumn, SqlExpressionType.Equal, SqlExpression.Constant(id));

                        foreach (var row in t2) {
                            var memberName = row.GetValue(1).Value.ToString();
                            var memberTypeString = row.GetValue(2).Value.ToString();

                            var memberType = SqlType.Parse(Transaction.Context, memberTypeString);

                            if (memberType == null)
                                throw new InvalidOperationException(String.Format("Cannot find the type '{0}' for member '{1}' of type '{2}'.",
                                    memberTypeString, memberName, typeName));

                            typeInfo.AddMember(memberName, memberType);
                        }
                    }
                }

                userType = new UserType(typeInfo);

                typesCache[typeName] = userType;
            }

            return userType;
        }
예제 #13
0
        private ITable FindEntry(ObjectName routineName)
        {
            var table = transaction.GetTable(RoutineTableName);

            var schemav = table.GetResolvedColumnName(1);
            var namev = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(transaction)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal,
                        SqlExpression.Constant(Field.String(routineName.Name)));
                    t = t.ExhaustiveSelect(context,
                        SqlExpression.Equal(SqlExpression.Reference(schemav),
                            SqlExpression.Constant(Field.String(routineName.ParentName))));

                    // This should be at most 1 row in size
                    if (t.RowCount > 1)
                        throw new Exception("Assert failed: multiple procedure names for " + routineName);

                    // Return the entries found.
                    return t;
                }
            }
        }
예제 #14
0
        public bool RoutineExists(ObjectName routineName)
        {
            if (routinesCache.ContainsKey(routineName))
                return true;

            var table = transaction.GetTable(RoutineTableName);
            var schemav = table.GetResolvedColumnName(1);
            var namev = table.GetResolvedColumnName(2);

            using (var session = new SystemSession(transaction)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal,
                        SqlExpression.Constant(Field.String(routineName.Name)));
                    t = t.ExhaustiveSelect(context,
                        SqlExpression.Equal(SqlExpression.Reference(schemav),
                            SqlExpression.Constant(Field.String(routineName.ParentName))));

                    return t.RowCount == 1;
                }
            }
        }
예제 #15
0
        public bool AlterTable(TableInfo tableInfo)
        {
            tableInfo = tableInfo.AsReadOnly();

            var tableName = tableInfo.TableName;

            // The current schema context is the schema of the table name
            string currentSchema = tableName.Parent.Name;

            using (var session = new SystemSession(Transaction, currentSchema)) {
                using (var context = session.CreateQuery()) {
                    // Get the next unique id of the unaltered table.
                    var nextId = NextUniqueId(tableName);

                    // Drop the current table
                    var cTable         = GetTable(tableName);
                    var droppedTableId = cTable.TableInfo.Id;

                    DropTable(tableName);

                    // And create the table
                    CreateTable(tableInfo);

                    var          alteredTable = GetMutableTable(tableName);
                    ITableSource source;
                    if (!visibleTables.TryGet(tableName, out source))
                    {
                        throw new InvalidOperationException();
                    }

                    int alteredTableId = source.TableId;

                    // Set the sequence id of the table
                    source.SetUniqueId(nextId.ToInt64());

                    // Work out which columns we have to copy to where
                    int[] colMap = new int[tableInfo.ColumnCount];
                    var   origTd = cTable.TableInfo;
                    for (int i = 0; i < colMap.Length; ++i)
                    {
                        string colName = tableInfo[i].ColumnName;
                        colMap[i] = origTd.IndexOfColumn(colName);
                    }

                    // First move all the rows from the old table to the new table,
                    // This does NOT update the indexes.
                    var e = cTable.GetEnumerator();
                    while (e.MoveNext())
                    {
                        int rowIndex = e.Current.RowId.RowNumber;
                        var dataRow  = alteredTable.NewRow();
                        for (int i = 0; i < colMap.Length; ++i)
                        {
                            int col = colMap[i];
                            if (col != -1)
                            {
                                dataRow.SetValue(i, cTable.GetValue(rowIndex, col));
                            }
                        }

                        dataRow.SetDefault(context);

                        // Note we use a low level 'AddRow' method on the master table
                        // here.  This does not touch the table indexes.  The indexes are
                        // built later.
                        int newRowNumber = source.AddRow(dataRow);

                        // Set the record as committed added
                        source.WriteRecordState(newRowNumber, RecordState.CommittedAdded);
                    }

                    // TODO: We need to copy any existing index definitions that might
                    //   have been set on the table being altered.

                    // Rebuild the indexes in the new master table,
                    source.BuildIndexes();

                    // Get the snapshot index set on the new table and set it here
                    SetIndexSetForTable(source, source.CreateIndexSet());

                    // Flush this out of the table cache
                    FlushTableCache(tableName);

                    // Ensure the native sequence generator exists...
                    Transaction.RemoveNativeSequence(tableName);
                    Transaction.CreateNativeSequence(tableName);

                    // Notify that this database object has been successfully dropped and
                    // created.
                    Transaction.OnTableDropped(droppedTableId, tableName);
                    Transaction.OnTableCreated(alteredTableId, tableName);

                    return(true);
                }
            }
        }
예제 #16
0
        public bool DropTrigger(ObjectName triggerName)
        {
            if (triggerName == null)
                throw new ArgumentNullException("triggerName");

            var table = transaction.GetMutableTable(TriggerTableName);

            var schemaName = triggerName.ParentName;
            var name = triggerName.Name;

            var schemaCol = table.GetResolvedColumnName(0);
            var nameCol = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(transaction)) {
                using (var query = session.CreateQuery()) {
                    var t = table.SimpleSelect(query, nameCol, SqlExpressionType.Equal, SqlExpression.Constant(name));
                    t = t.ExhaustiveSelect(query,
                        SqlExpression.Equal(SqlExpression.Reference(schemaCol), SqlExpression.Constant(schemaName)));

                    if (t.RowCount == 0)
                        return false;

                    table.Delete(t);

                    transaction.OnObjectDropped(DbObjectType.Trigger, triggerName);
                    return true;
                }
            }
        }
예제 #17
0
        private ITable FindViewEntry(ObjectName viewName)
        {
            var table = Transaction.GetTable(SystemSchema.ViewTableName);

            var schemav = table.GetResolvedColumnName(0);
            var namev = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                using (var query =session.CreateQuery()) {
                    var t = table.SimpleSelect(query, namev, SqlExpressionType.Equal,
                        SqlExpression.Constant(DataObject.String(viewName.Name)));
                    t = t.ExhaustiveSelect(query,
                        SqlExpression.Equal(SqlExpression.Reference(schemav), SqlExpression.Constant(viewName.ParentName)));

                    // This should be at most 1 row in size
                    if (t.RowCount > 1)
                        throw new ArgumentException(String.Format("Multiple view entries for name '{0}' in the system.", viewName));

                    // Return the entries found.
                    return t;
                }
            }
        }
예제 #18
0
        public UserType GetUserType(ObjectName typeName)
        {
            UserType userType;

            if (!typesCache.TryGetValue(typeName, out userType))
            {
                var typeTable    = Transaction.GetTable(TypeTableName);
                var membersTable = Transaction.GetTable(TypeMemberTableName);

                var schemaName = typeName.ParentName;
                var name       = typeName.Name;

                var schemaColumn = typeTable.GetResolvedColumnName(1);
                var nameColumn   = typeTable.GetResolvedColumnName(2);

                var idColumn = membersTable.GetResolvedColumnName(0);

                UserTypeInfo typeInfo;

                using (var session = new SystemSession(Transaction)) {
                    using (var query = session.CreateQuery()) {
                        var t = typeTable.SimpleSelect(query, schemaColumn, SqlExpressionType.Equal, SqlExpression.Constant(schemaName));

                        t = t.ExhaustiveSelect(query,
                                               SqlExpression.Equal(SqlExpression.Reference(nameColumn), SqlExpression.Constant(name)));

                        if (t.RowCount == 0)
                        {
                            return(null);
                        }

                        var id = t.GetValue(0, 0);

                        var        parentField = t.GetValue(0, 3);
                        ObjectName parentType  = null;
                        if (!Field.IsNullField(parentField))
                        {
                            parentType = ObjectName.Parse(parentField.Value.ToString());
                        }

                        typeInfo = new UserTypeInfo(typeName, parentType);


                        var isSealedField   = t.GetValue(0, 4);
                        var isAbstractField = t.GetValue(0, 5);

                        if (!Field.IsNullField(isSealedField))
                        {
                            typeInfo.IsSealed = (SqlBoolean)isSealedField.AsBoolean().Value;
                        }

                        if (!Field.IsNullField(isAbstractField))
                        {
                            typeInfo.IsAbstract = (SqlBoolean)isAbstractField.AsBoolean().Value;
                        }

                        var owner = t.GetValue(0, 6).Value.ToString();

                        typeInfo.Owner = owner;

                        var t2 = membersTable.SimpleSelect(query, idColumn, SqlExpressionType.Equal, SqlExpression.Constant(id));

                        foreach (var row in t2)
                        {
                            var memberName       = row.GetValue(1).Value.ToString();
                            var memberTypeString = row.GetValue(2).Value.ToString();

                            var memberType = SqlType.Parse(Transaction.Context, memberTypeString);

                            if (memberType == null)
                            {
                                throw new InvalidOperationException(String.Format("Cannot find the type '{0}' for member '{1}' of type '{2}'.",
                                                                                  memberTypeString, memberName, typeName));
                            }

                            typeInfo.AddMember(memberName, memberType);
                        }
                    }
                }

                userType = new UserType(typeInfo);

                typesCache[typeName] = userType;
            }

            return(userType);
        }
예제 #19
0
        private View GetViewAt(int offset)
        {
            var table = Transaction.GetTable(SystemSchema.ViewTableName);
            if (table == null)
                throw new DatabaseSystemException(String.Format("System table '{0}' was not defined.", SystemSchema.ViewTableName));

            var e = table.GetEnumerator();
            int i = 0;
            while (e.MoveNext()) {
                var row = e.Current.RowId.RowNumber;

                if (i == offset) {
                    ViewInfo viewInfo;
                    if (!viewCache.TryGetValue(row, out viewInfo)) {
                        var binary = (ISqlBinary)table.GetValue(row, 3).Value;

                        using (var session = new SystemSession(Transaction, SystemSchema.Name)) {
                            using (var context = session.CreateQuery()) {
                                viewInfo = ViewInfo.Deserialize(binary.GetInput());
                            }
                        }

                        viewCache[row] = viewInfo;
                    }

                    return new View(viewInfo);
                }

                ++i;
            }

            throw new ArgumentOutOfRangeException("offset");
        }
예제 #20
0
        public bool AlterTable(TableInfo tableInfo)
        {
            tableInfo = tableInfo.AsReadOnly();

            var tableName = tableInfo.TableName;

            // The current schema context is the schema of the table name
            string currentSchema = tableName.Parent.Name;
            using (var session = new SystemSession(Transaction, currentSchema)) {
                using (var context = session.CreateQuery()) {

                    // Get the next unique id of the unaltered table.
                    var nextId = NextUniqueId(tableName);

                    // Drop the current table
                    var cTable = GetTable(tableName);
                    var droppedTableId = cTable.TableInfo.Id;

                    DropTable(tableName);

                    // And create the table table
                    CreateTable(tableInfo);

                    var alteredTable = GetMutableTable(tableName);
                    var source = FindVisibleTable(tableName, false);
                    int alteredTableId = source.TableId;

                    // Set the sequence id of the table
                    source.SetUniqueId(nextId.ToInt64());

                    // Work out which columns we have to copy to where
                    int[] colMap = new int[tableInfo.ColumnCount];
                    var origTd = cTable.TableInfo;
                    for (int i = 0; i < colMap.Length; ++i) {
                        string colName = tableInfo[i].ColumnName;
                        colMap[i] = origTd.IndexOfColumn(colName);
                    }

                    // First move all the rows from the old table to the new table,
                    // This does NOT update the indexes.
                    var e = cTable.GetEnumerator();
                    while (e.MoveNext()) {
                        int rowIndex = e.Current.RowId.RowNumber;
                        var dataRow = alteredTable.NewRow();
                        for (int i = 0; i < colMap.Length; ++i) {
                            int col = colMap[i];
                            if (col != -1) {
                                dataRow.SetValue(i, cTable.GetValue(rowIndex, col));
                            }
                        }

                        dataRow.SetDefault(context);

                        // Note we use a low level 'AddRow' method on the master table
                        // here.  This does not touch the table indexes.  The indexes are
                        // built later.
                        int newRowNumber = source.AddRow(dataRow);

                        // Set the record as committed added
                        source.WriteRecordState(newRowNumber, RecordState.CommittedAdded);
                    }

                    // TODO: We need to copy any existing index definitions that might
                    //   have been set on the table being altered.

                    // Rebuild the indexes in the new master table,
                    source.BuildIndexes();

                    // Get the snapshot index set on the new table and set it here
                    SetIndexSetForTable(source, source.CreateIndexSet());

                    // Flush this out of the table cache
                    FlushTableCache(tableName);

                    // Ensure the native sequence generator exists...
                    Transaction.RemoveNativeSequence(tableName);
                    Transaction.CreateNativeSequence(tableName);

                    // Notify that this database object has been successfully dropped and
                    // created.
                    Transaction.Registry.RegisterEvent(new TableDroppedEvent(droppedTableId, tableName));
                    Transaction.Registry.RegisterEvent(new TableCreatedEvent(alteredTableId, tableName));

                    return true;
                }
            }
        }
예제 #21
0
        private IEnumerable<TriggerInfo> FindTriggers(ObjectName tableName, TriggerEventType eventType)
        {
            var fullTableName = tableName.FullName;
            var eventTypeCode = (int)eventType;

            var table = transaction.GetTable(SystemSchema.TriggerTableName);
            if (table == null)
                return new TriggerInfo[0];

            var tableColumn = table.GetResolvedColumnName(3);
            var eventTypeColumn = table.GetResolvedColumnName(4);

            ITable result;
            using (var session = new SystemSession(transaction, SystemSchema.Name)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, tableColumn, SqlExpressionType.Equal,
                        SqlExpression.Constant(DataObject.String(fullTableName)));

                    result = t.ExhaustiveSelect(context,
                        SqlExpression.Equal(SqlExpression.Reference(eventTypeColumn), SqlExpression.Constant(eventTypeCode)));
                }
            }

            if (result.RowCount == 0)
                return new TriggerInfo[0];

            var list = new List<TriggerInfo>();

            foreach (var row in result) {
                var triggerInfo = FormTrigger(row);

                //TODO: get the other information such has the body, the external method or the procedure
                //      if this is a non-callback

                list.Add(triggerInfo);
            }

            return list.AsEnumerable();
        }
예제 #22
0
        public void AssertConstraints()
        {
            AssertNotDisposed();

            try {
                // Early exit condition
                if (lastEntryRICheck == EventRegistry.EventCount)
                {
                    return;
                }

                // This table name
                var tableInfo = TableInfo;
                var tName     = tableInfo.TableName;

                using (var session = new SystemSession(Transaction, tName.ParentName)) {
                    using (var context = session.CreateQuery()) {
                        // Are there any added, deleted or updated entries in the journal since
                        // we last checked?
                        List <int> rowsUpdated = new List <int>();
                        List <int> rowsDeleted = new List <int>();
                        List <int> rowsAdded   = new List <int>();

                        var events = EventRegistry.Skip(lastEntryRICheck);
                        foreach (var tableEvent in events.OfType <TableRowEvent>())
                        {
                            var rowNum = tableEvent.RowNumber;
                            if (tableEvent.EventType == TableRowEventType.Remove ||
                                tableEvent.EventType == TableRowEventType.UpdateRemove)
                            {
                                rowsDeleted.Add(rowNum);

                                var index = rowsAdded.IndexOf(rowNum);
                                if (index != -1)
                                {
                                    rowsAdded.RemoveAt(index);
                                }
                            }
                            else if (tableEvent.EventType == TableRowEventType.Add ||
                                     tableEvent.EventType == TableRowEventType.UpdateAdd)
                            {
                                rowsAdded.Add(rowNum);
                            }

                            if (tableEvent.EventType == TableRowEventType.UpdateAdd ||
                                tableEvent.EventType == TableRowEventType.UpdateRemove)
                            {
                                rowsUpdated.Add(rowNum);
                            }
                        }

                        // Were there any updates or deletes?
                        if (rowsDeleted.Count > 0)
                        {
                            // Get all references on this table
                            var foreignConstraints = Transaction.QueryTableImportedForeignKeys(tName);

                            // For each foreign constraint
                            foreach (var constraint in foreignConstraints)
                            {
                                // For each deleted/updated record in the table,
                                foreach (var rowNum in rowsDeleted)
                                {
                                    // What was the key before it was updated/deleted
                                    var cols = tableInfo.IndexOfColumns(constraint.ForeignColumnNames).ToArray();

                                    var originalKey = new DataObject[cols.Length];
                                    int nullCount   = 0;
                                    for (int p = 0; p < cols.Length; ++p)
                                    {
                                        originalKey[p] = GetValue(rowNum, cols[p]);
                                        if (originalKey[p].IsNull)
                                        {
                                            ++nullCount;
                                        }
                                    }

                                    // Check the original key isn't null
                                    if (nullCount != cols.Length)
                                    {
                                        // Is is an update?
                                        int updateIndex = rowsUpdated.IndexOf(rowNum);
                                        if (updateIndex != -1)
                                        {
                                            // Yes, this is an update
                                            int rowIndexAdd = rowsUpdated[updateIndex + 1];

                                            // It must be an update, so first see if the change caused any
                                            // of the keys to change.
                                            bool keyChanged   = false;
                                            var  keyUpdatedTo = new DataObject[cols.Length];
                                            for (int p = 0; p < cols.Length; ++p)
                                            {
                                                keyUpdatedTo[p] = GetValue(rowIndexAdd, cols[p]);
                                                if (originalKey[p].CompareTo(keyUpdatedTo[p]) != 0)
                                                {
                                                    keyChanged = true;
                                                }
                                            }
                                            if (keyChanged)
                                            {
                                                // Allow the delete, and execute the action,
                                                // What did the key update to?
                                                ExecuteUpdateReferentialAction(constraint, originalKey, keyUpdatedTo, context);
                                            }

                                            // If the key didn't change, we don't need to do anything.
                                        }
                                        else
                                        {
                                            // No, so it must be a delete,
                                            // This will look at the referencee table and if it contains
                                            // the key, work out what to do with it.
                                            ExecuteDeleteReferentialAction(constraint, originalKey, context);
                                        }
                                    }                     // If the key isn't null
                                }                         // for each deleted rows
                            }                             // for each foreign key reference to this table
                        }

                        // Were there any rows added (that weren't deleted)?
                        if (rowsAdded.Count > 0)
                        {
                            int[] rowIndices = rowsAdded.ToArray();

                            // Check for any field constraint violations in the added rows
                            Transaction.CheckFieldConstraintViolations(this, rowIndices);

                            // Check this table, adding the given row_index, immediate
                            Transaction.CheckAddConstraintViolations(this, rowIndices, ConstraintDeferrability.InitiallyImmediate);
                        }
                    }
                }
            } catch (ConstraintViolationException) {
                // If a constraint violation, roll back the changes since the last
                // check.
                int rollbackPoint = EventRegistry.EventCount - lastEntryRICheck;
                if (rowListRebuild <= rollbackPoint)
                {
                    EventRegistry.Rollback(rollbackPoint);
                }
                else
                {
                    // TODO: emit a warning
                }

                throw;
            } finally {
                // Make sure we update the 'last_entry_ri_check' variable
                lastEntryRICheck = EventRegistry.EventCount;
            }
        }
예제 #23
0
        private ITable FindTrigger(ITable table, string schema, string name)
        {
            // Find all the trigger entries with this name
            var schemaColumn = table.GetResolvedColumnName(0);
            var nameColumn = table.GetResolvedColumnName(1);

            using (var session = new SystemSession(transaction, SystemSchema.Name)) {
                using (var context = session.CreateQuery()) {
                    var t = table.SimpleSelect(context, nameColumn, SqlExpressionType.Equal,
                        SqlExpression.Constant(Field.String(name)));
                    return t.ExhaustiveSelect(context,
                        SqlExpression.Equal(SqlExpression.Reference(schemaColumn), SqlExpression.Constant(Field.String(schema))));
                }
            }
        }
예제 #24
0
        public static void CheckAddConstraintViolations(this ITransaction transaction, ITable table, int[] rowIndices,
                                                        ConstraintDeferrability deferred)
        {
            string curSchema = table.TableInfo.TableName.Parent.Name;

            using (var session = new SystemSession(transaction, curSchema)) {
                using (var queryContext = session.CreateQuery()) {
                    // Quick exit case
                    if (rowIndices == null || rowIndices.Length == 0)
                    {
                        return;
                    }

                    var tableInfo = table.TableInfo;
                    var tableName = tableInfo.TableName;

                    // ---- Constraint checking ----

                    // Check any primary key constraint.
                    var primaryKey = transaction.QueryTablePrimaryKey(tableName);
                    if (primaryKey != null &&
                        (deferred == ConstraintDeferrability.InitiallyDeferred ||
                         primaryKey.Deferred == ConstraintDeferrability.InitiallyImmediate))
                    {
                        // For each row added to this column
                        foreach (int rowIndex in rowIndices)
                        {
                            if (!IsUniqueColumns(table, rowIndex, primaryKey.ColumnNames, false))
                            {
                                throw new PrimaryKeyViolationException(tableName, primaryKey.ConstraintName, primaryKey.ColumnNames, deferred);
                            }
                        }                         // For each row being added
                    }

                    // Check any unique constraints.
                    var uniqueConstraints = transaction.QueryTableUniqueKeys(tableName);
                    foreach (var unique in uniqueConstraints)
                    {
                        if (deferred == ConstraintDeferrability.InitiallyDeferred ||
                            unique.Deferred == ConstraintDeferrability.InitiallyImmediate)
                        {
                            // For each row added to this column
                            foreach (int rowIndex in rowIndices)
                            {
                                if (!IsUniqueColumns(table, rowIndex, unique.ColumnNames, true))
                                {
                                    throw new UniqueKeyViolationException(tableName, unique.ConstraintName, unique.ColumnNames, deferred);
                                }
                            }                             // For each row being added
                        }
                    }

                    // Check any foreign key constraints.
                    // This ensures all foreign references in the table are referenced
                    // to valid records.
                    var foreignConstraints = transaction.QueryTableForeignKeys(tableName);

                    foreach (var reference in foreignConstraints)
                    {
                        if (deferred == ConstraintDeferrability.InitiallyDeferred ||
                            reference.Deferred == ConstraintDeferrability.InitiallyImmediate)
                        {
                            // For each row added to this column
                            foreach (int rowIndex in rowIndices)
                            {
                                // Make sure the referenced record exists

                                // Return the count of records where the given row of
                                //   table_name(columns, ...) IN
                                //                    ref_table_name(ref_columns, ...)
                                int rowCount = RowCountOfReferenceTable(transaction,
                                                                        rowIndex,
                                                                        reference.TableName, reference.ColumnNames,
                                                                        reference.ForeignTable, reference.ForeignColumnNames,
                                                                        false);
                                if (rowCount == -1)
                                {
                                    // foreign key is NULL
                                }

                                if (rowCount == 0)
                                {
                                    throw new ForeignKeyViolationException(tableName, reference.ConstraintName, reference.ColumnNames,
                                                                           reference.ForeignTable, reference.ForeignColumnNames, deferred);
                                }
                            }                             // For each row being added.
                        }
                    }

                    // Any general checks of the inserted data
                    var checkConstraints = transaction.QueryTableCheckExpressions(tableName);

                    // For each check constraint, check that it evaluates to true.
                    for (int i = 0; i < checkConstraints.Length; ++i)
                    {
                        var check = checkConstraints[i];
                        if (deferred == ConstraintDeferrability.InitiallyDeferred ||
                            check.Deferred == ConstraintDeferrability.InitiallyImmediate)
                        {
                            var exp = tableInfo.ResolveColumns(transaction.IgnoreIdentifiersCase(), check.CheckExpression);

                            // For each row being added to this column
                            for (int rn = 0; rn < rowIndices.Length; ++rn)
                            {
                                var resolver = new TableRowVariableResolver(table, rowIndices[rn]);
                                var evalExp  = exp.Evaluate(queryContext, resolver, null);
                                var ob       = ((SqlConstantExpression)evalExp).Value;

                                var b = ob.AsBoolean();

                                if (!b.IsNull)
                                {
                                    if (!((SqlBoolean)b.Value))
                                    {
                                        // Evaluated to false so don't allow this row to be added.
                                        throw new CheckViolationException(tableName, check.ConstraintName, check.CheckExpression, deferred);
                                    }
                                }
                                else
                                {
                                    // NOTE: This error will pass the row by default
                                    // TODO: emit a warning
                                }
                            }
                        }
                    }
                }
            }
        }