private KeyValuePair <Filter, IConcreteIndex> TryGetFilterWithIndex(ICollection <Filter> sameTableFilters) { var indexFactory = new IndexFactory(KeyValue.GetDatabaseFileName(database.Name), repository); var table = database.Tables.Single(t => t.Name == sameTableFilters.First().Table); foreach (var filter in sameTableFilters) { var associations = database.Associations.Where(a => a.Child == table.Name && a.ColumnMappings.Values.Contains(filter.Column) && a.ColumnMappings.Count == 1); if (associations.Any()) { var association = associations.First(); var parentTable = database.Tables.Single(t => t.Name == association.Parent); var indexMeta = parentTable.Indexes.Where(i => i.Name.Equals(association.Name)).Single(); var index = indexFactory.GetIndex(indexMeta); return(new KeyValuePair <Filter, IConcreteIndex>(filter, index)); } } return(new KeyValuePair <Filter, IConcreteIndex>(filters.First(), null)); }
public ReturnStatus Insert(Database database, Table table, ICollection <string> keyMembers, ICollection <string> values) { string databaseFileName = KeyValue.GetDatabaseFileName(database.Name); string key = KeyValue.Concatenate(keyMembers); string value = KeyValue.Concatenate(values); ReturnStatus status = new ReturnStatus(); // Check primary key constraints. if (repository.Exists(databaseFileName, table.Name, key)) { status.ReturnCode = ReturnCode.PrimaryKeyConstraintFailed; status.Message = string.Format("Primary key constraint check failed for primary key: {0}", key); return(status); } // Check unique index constraints. var uniqueIndexes = new IConcreteIndex[table.Indexes.Where(i => i.Unique).Count()]; var uniqueIndexKeys = new string[table.Indexes.Where(i => i.Unique).Count()]; var indexFactory = new IndexFactory(databaseFileName, repository); var counter = 0; var nonKeyColumnNames = table.Columns.Where(c => !table.PrimaryKey.Contains(c.Name)).Select(c => c.Name).ToList(); foreach (var uniqueIndex in table.Indexes.Where(i => i.Unique)) { var index = indexFactory.GetIndex(uniqueIndex); uniqueIndexes[counter] = index; var columnValues = new List <string>(); foreach (var column in uniqueIndex.IndexMembers) { columnValues.Add(values.ElementAt(nonKeyColumnNames.IndexOf(column))); } var uniqueKey = KeyValue.Concatenate(columnValues); uniqueIndexKeys[counter] = uniqueKey; if (index.Exists(uniqueKey)) { status.ReturnCode = ReturnCode.UniqueConstraintFailed; status.Message = string.Format("Unique constraint check failed for key: {0}", uniqueKey); return(status); } counter++; } // Check foreign key constraints (the key is simple). // Check if the key exists in the parent table. var foreignKeyIndexes = new IConcreteIndex[database.GetAssociationsWhereTableIsChild(table.Name).Count()]; var foreignKeyIndexKeys = new string[database.GetAssociationsWhereTableIsChild(table.Name).Count()]; counter = 0; foreach (var association in database.GetAssociationsWhereTableIsChild(table.Name)) { var parentTable = database.GetTable(association.Parent); var indexMeta = parentTable.Indexes.Where(i => i.Name.Equals(association.Name)).Single(); var index = indexFactory.GetIndex(indexMeta); var foreignKey = string.Empty; if (table.PrimaryKey.Contains(association.ColumnMappings.Values.First())) { foreignKey = keyMembers.ElementAt(table.PrimaryKey.IndexOf(association.ColumnMappings.Values.First())); } else { foreignKey = values.ElementAt(nonKeyColumnNames.IndexOf(association.ColumnMappings.Values.First())); } foreignKeyIndexes[counter] = index; foreignKeyIndexKeys[counter] = foreignKey; if (!repository.Exists(databaseFileName, parentTable.Name, foreignKey)) { status.ReturnCode = ReturnCode.ForeignKeyConstraintFailed; status.Message = string.Format("Foreign key constraint check failed, key is missing from the parent table ({0} [{1}]): {2}", parentTable.Name, association.ColumnMappings.Keys.First(), foreignKey); return(status); } counter++; } // Insert unique indexes. for (int k = 0; k < uniqueIndexes.Length; k++) { uniqueIndexes[k].Put(uniqueIndexKeys[k], key); } // Insert foreign key indexes. for (int k = 0; k < foreignKeyIndexes.Length; k++) { foreignKeyIndexes[k].Put(foreignKeyIndexKeys[k], key); } // Insert row if there is no errors. repository.Put(databaseFileName, table.Name, key, value); status.ReturnCode = ReturnCode.Success; status.Message = string.Format("({0} row(s) affected)", 1); return(status); }
public ReturnStatus Delete(Database database, Table table, ICollection <Filter> filters) { string databaseFileName = KeyValue.GetDatabaseFileName(database.Name); var planner = new SimpleExecutionPlanner(database, repository, new List <Selection>(), new List <Join>(), filters); var rootOperation = planner.GetRootOperation(); var nonKeyColumnNames = table.Columns.Where(c => !table.PrimaryKey.Contains(c.Name)).Select(c => c.Name).ToList(); var metadata = rootOperation.GetMetadata(); var rows = rootOperation.Execute(); ReturnStatus status = new ReturnStatus(); var indexFactory = new IndexFactory(databaseFileName, repository); var rowsToDelete = new List <string>(); var rowData = new List <KeyValuePair <string, string> >(); foreach (var row in rows) { rowsToDelete.Add(row.Key); rowData.Add(row); } foreach (var row in rowsToDelete) { // Check foreign key constraints. foreach (var association in database.GetAssociationsWhereTableIsParent(table.Name)) { var indexMeta = table.Indexes.Where(i => i.Name.Equals(association.Name)).Single(); var index = indexFactory.GetIndex(indexMeta); var foreignKey = string.Empty; if (index.Exists(row)) { status.ReturnCode = ReturnCode.ForeignKeyConstraintFailed; status.Message = string.Format("Foreign key constraint check failed, the key [{0}] is referenced in {1}.", row, association.Child); return(status); } } } foreach (var row in rowData) { // Delete unique indexes. foreach (var uniqueIndex in table.Indexes.Where(i => i.Unique)) { var index = indexFactory.GetIndex(uniqueIndex); var columnValues = new List <string>(); foreach (var column in uniqueIndex.IndexMembers) { columnValues.Add(KeyValue.Split(row.Value).ElementAt(KeyValue.Split(metadata.Value).ToList().IndexOf(column))); } var uniqueKey = KeyValue.Concatenate(columnValues); index.Delete(uniqueKey); } // Delete foreign key indexes. foreach (var association in database.GetAssociationsWhereTableIsChild(table.Name)) { var parentTable = database.GetTable(association.Parent); var indexMeta = parentTable.Indexes.Where(i => i.Name.Equals(association.Name)).Single(); var index = indexFactory.GetIndex(indexMeta); var foreignKey = string.Empty; if (table.PrimaryKey.Contains(association.ColumnMappings.Values.First())) { foreignKey = KeyValue.Split(row.Key).ElementAt(table.PrimaryKey.IndexOf(association.ColumnMappings.Values.First())); } else { foreignKey = KeyValue.Split(row.Value).ElementAt(nonKeyColumnNames.IndexOf(association.ColumnMappings.Values.First())); } index.Delete(foreignKey, row.Key); } } foreach (var rowToDelete in rowsToDelete) { // Delete primary key and data. repository.Delete(databaseFileName, table.Name, rowToDelete); } status.ReturnCode = ReturnCode.Success; status.Message = string.Format("({0} row(s) affected)", rowsToDelete.Count); return(status); }