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)))); } }
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 } } } } }
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; } }
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"); }
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; } }
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; }
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); } }