Example #1
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 context = new SystemQueryContext(transaction, SystemSchema.Name)) {
                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))));
            }
        }
Example #2
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 context = new SystemQueryContext(transaction, SystemSchema.Name)) {
                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();
        }
        public static void CheckAddConstraintViolations(this ITransaction transaction, ITable table, int[] rowIndices, ConstraintDeferrability deferred)
        {
            string curSchema = table.TableInfo.TableName.Parent.Name;
            IQueryContext queryContext = new SystemQueryContext(transaction, curSchema);

            // 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 ConstraintViolationException(
                          SqlModelErrorCodes.PrimaryKeyViolation,
                          deferred.AsDebugString() + " primary Key constraint violation (" +
                          primaryKey.ConstraintName + ") Columns = ( " +
                          String.Join(", ", primaryKey.ColumnNames) +
                          " ) Table = ( " + tableName + " )");
                    }
                } // 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 ConstraintViolationException(
                              SqlModelErrorCodes.UniqueViolation,
                              deferred.AsDebugString() + " unique constraint violation (" +
                              unique.ConstraintName + ") Columns = ( " +
                              String.Join(", ", unique.ColumnNames) + " ) Table = ( " +
                              tableName + " )");
                        }
                    } // 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 ConstraintViolationException(
                              SqlModelErrorCodes.ForeignKeyViolation,
                              deferred.AsDebugString() + " foreign key constraint violation (" +
                              reference.ConstraintName + ") Columns = " +
                              reference.TableName + "( " +
                              String.Join(", ", reference.ColumnNames) + " ) -> " +
                              reference.ForeignTable + "( " +
                              String.Join(", ", reference.ForeignColumnNames) + " )");
                        }
                    } // 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) {

                    // TODO: var exp = tableInfo.ResolveColumns(transaction.IgnoreIdentifierCase(), check.CheckExpression);
                    var exp = tableInfo.ResolveColumns(true, 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 (b) {
                                // Evaluated to false so don't allow this row to be added.
                                throw new ConstraintViolationException(
                                   SqlModelErrorCodes.CheckViolation,
                                   deferred.AsDebugString() + " check constraint violation (" +
                                   check.ConstraintName + ") - '" + exp +
                                   "' evaluated to false for inserted/updated row.");
                            }
                        } else {
                            // NOTE: This error will pass the row by default
                            // TODO: emit a warning
                        }
                    }
                }
            }
        }
Example #4
0
        private ITable FindEntry(Table table, ObjectName routineName)
        {
            var schemav = table.GetResolvedColumnName(0);
            var namev = table.GetResolvedColumnName(1);

            using (var context = new SystemQueryContext(transaction, transaction.CurrentSchema())) {
                var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal,
                    SqlExpression.Constant(DataObject.String(routineName.Name)));
                t = t.ExhaustiveSelect(context,
                    SqlExpression.Equal(SqlExpression.Reference(schemav),
                        SqlExpression.Constant(DataObject.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;
            }
        }
Example #5
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 context = new SystemQueryContext(Transaction, SystemSchema.Name)) {
                            viewInfo = ViewInfo.Deserialize(binary.GetInput(), context.TypeResolver());
                        }

                        viewCache[row] = viewInfo;
                    }

                    return new View(viewInfo);
                }

                ++i;
            }

            throw new ArgumentOutOfRangeException("offset");
        }
Example #6
0
        private ITable FindViewEntry(ObjectName viewName)
        {
            var table = Transaction.GetTable(SystemSchema.ViewTableName);

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

            using (var context = new SystemQueryContext(Transaction, SystemSchema.Name)) {
                var t = table.SimpleSelect(context, namev, SqlExpressionType.Equal, SqlExpression.Constant(DataObject.String(viewName.Name)));
                t = t.ExhaustiveSelect(context, 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;
            }
        }
Example #7
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 context = new SystemQueryContext(Transaction, SystemSchema.Name)) {
                            viewInfo = ViewInfo.Deserialize(blob.GetInput(), context.TypeResolver());
                        }

                        viewCache[row] = viewInfo;

                    }

                    return new View(viewInfo);
                }

            }

            return null;
        }
Example #8
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;
            var context = new SystemQueryContext(Transaction, currentSchema);

            // 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;
        }
        public static void CreateTable(this IQueryContext context, TableInfo tableInfo, bool onlyIfNotExists, bool temporary)
        {
            if (tableInfo == null)
                throw new ArgumentNullException("tableInfo");

            var tableName = tableInfo.TableName;

            if (!context.UserCanCreateTable(tableName))
                throw new MissingPrivilegesException(context.User().Name, tableName, Privileges.Create);

            if (context.TableExists(tableName)) {
                if (!onlyIfNotExists)
                    throw new InvalidOperationException(
                        String.Format("The table {0} already exists and the IF NOT EXISTS clause was not specified.", tableName));

                return;
            }

            context.Session.CreateTable(tableInfo, temporary);

            using (var systemContext = new SystemQueryContext(context.Session.Transaction, context.CurrentSchema)) {
                systemContext.GrantToUserOnTable(tableInfo.TableName, context.User(), Privileges.TableAll);
            }
        }