public DocumentMappingExpression <T> UniqueIndex(UniqueIndexType indexType, string indexName, TenancyScope tenancyScope = TenancyScope.Global, params Expression <Func <T, object> >[] expressions) { _builder.Alter = m => m.UniqueIndex(indexType, indexName, tenancyScope, expressions); return(this); }
public IEnumerable <ObjectState> GetDesiredState(SchemaConnection connection, IOutput output) { var schemaDriver = connection.SchemaDriver; var stateTable = TableType.Create("dbo.nrdo_object"); var stateTypeField = FieldType.Create(stateTable.Identifier, "type", 0, "nvarchar(100)", false); var stateNameField = FieldType.Create(stateTable.Identifier, "name", 1, "nvarchar(500)", false); var statePk = UniqueIndexType.CreatePrimaryKey(stateTable.Identifier, "nrdo_object_pk", new[] { stateTypeField.Identifier, stateNameField.Identifier }, schemaDriver.DefaultPrimaryKeyCustomState); var subTable = TableType.Create("dbo.nrdo_object_sub"); var subParentTypeField = FieldType.Create(subTable.Identifier, "parent_type", 0, "nvarchar(100)", false); var subParentNameField = FieldType.Create(subTable.Identifier, "parent_name", 1, "nvarchar(500)", false); var subTypeField = FieldType.Create(subTable.Identifier, "type", 2, "nvarchar(100)", false); var subNameField = FieldType.Create(subTable.Identifier, "name", 3, "nvarchar(500)", false); var subPk = UniqueIndexType.CreatePrimaryKey(subTable.Identifier, "nrdo_object_sub_pk", new[] { subParentTypeField.Identifier, subParentNameField.Identifier, subTypeField.Identifier, subNameField.Identifier }, schemaDriver.DefaultPrimaryKeyCustomState); var subFk = FkeyType.Create(subTable.Identifier, stateTable.Identifier, "nrdo_object_sub_parent_fk", true, new[] { new FieldPair(subParentTypeField.Name, stateTypeField.Name), new FieldPair(subParentNameField.Name, stateNameField.Name), }); return(new ObjectState[] { stateTable, stateTypeField, stateNameField, statePk, subTable, subParentTypeField, subParentNameField, subTypeField, subNameField, subPk, subFk }); }
public DocumentMappingExpression <T> UniqueIndex(UniqueIndexType indexType, params Expression <Func <T, object> >[] expressions) { _builder.Alter = m => m.UniqueIndex(indexType, null, expressions); return(this); }
public static bool FkeyHasChanged(SchemaChanges changes, SubObjectState <FkeyType, FkeyType.State> current) { if (current == null) { return(true); } var desired = changes.Desired.Get(current); // The foreign key doesn't exist in the desired schema at all if (desired == null) { return(true); } // The destination table has changed if (desired.State.ToTable != current.State.ToTable) { return(true); } // Either the from or to table might need to be dropped entirely to reorder fields if (FieldType.IsFieldReorderPossiblyNeeded(changes, current.ParentIdentifier) || FieldType.IsFieldReorderPossiblyNeeded(changes, current.State.ToTable)) { return(true); } // It's changed from cascading to not or vice versa if (desired.State.IsCascadeDelete != current.State.IsCascadeDelete) { return(true); } // The sequence of field name pairs don't match if (!Enumerable.SequenceEqual(desired.State.Joins, current.State.Joins, FieldPair.GetComparer(changes.DbDriver))) { return(true); } // Any of the fields in either table are changing if (current.State.Joins.Any(field => FieldType.FieldHasChanged(changes, current.ParentIdentifier, FieldType.Identifier(field.FromFieldName)) || FieldType.FieldHasChanged(changes, current.State.ToTable, FieldType.Identifier(field.ToFieldName)))) { return(true); } // The unique index on the destination table that corresponds to the destination fields is changing var ukey = UniqueIndexType.ChildrenFrom(changes.Current, current.State.ToTable) .SingleOrDefault(key => new HashSet <Identifier>(key.State.IndexState.Fields).SetEquals(from field in current.State.Joins select FieldType.Identifier(field.ToFieldName))); if (ukey != null && UniqueIndexType.IndexHasChanged(changes, ukey)) { return(true); } return(false); }
public void UniqueIndex(UniqueIndexType indexType, string indexName, TenancyScope tenancyScope = TenancyScope.Global, params Expression <Func <T, object> >[] expressions) { var members = expressions .Select(e => { var visitor = new FindMembers(); visitor.Visit(e); return(visitor.Members.ToArray()); }) .ToArray(); if (members.Length == 0) { throw new InvalidOperationException( $"Unique index on {typeof(T)} requires at least one property/field"); } AddUniqueIndex( members, indexType, indexName, IndexMethod.btree, tenancyScope); }
public void UniqueIndex(UniqueIndexType indexType, string indexName, TenancyScope tenancyScope = TenancyScope.Global, params Expression <Func <T, object> >[] expressions) { AddUniqueIndex( expressions .Select(FindMembers.Determine) .ToArray(), indexType, indexName, IndexMethod.btree, tenancyScope); }
internal static bool FulltextIndexHasChanged(SchemaChanges changes, SubObjectState <FulltextIndexType, State> current) { if (current == null) { return(true); } var desired = changes.Desired.Get(current); // The fulltext index doesn't exist in the desired schema at all if (desired == null) { return(true); } // The key index name has changed if (desired.State.KeyName != current.State.KeyName) { return(true); } // The set of affected columns has changed (in some way other than just the ordering) if (!ImmutableHashSet.CreateRange(changes.DbDriver.DbStringComparer, desired.State.Columns).SetEquals(current.State.Columns)) { return(true); } var table = TableType.Identifier(desired.Name); // Any of the columns in the fulltext index have changed if (desired.State.Columns.Any(col => FieldType.FieldHasChanged(changes, table, FieldType.Identifier(col)))) { return(true); } // The key index is to be dropped // This includes the case where the table itself may be dropped for reordering if (UniqueIndexType.IndexHasChanged(changes, UniqueIndexType.GetFrom(changes.Current, table, UniqueIndexType.Identifier(current.State.KeyName)))) { return(true); } return(false); }
public void UniqueIndex(UniqueIndexType indexType, string indexName, params Expression <Func <T, object> >[] expressions) { UniqueIndex(indexType, indexName, TenancyScope.Global, expressions); }
/// <summary> /// Creates a unique index on this data member within the JSON data storage /// </summary> /// <param name="indexType">Type of the index</param> /// <param name="indexName">Name of the index</param> /// <param name="expressions"></param> /// <returns></returns> public DocumentMappingExpression <T> UniqueIndex(UniqueIndexType indexType, string indexName, params Expression <Func <T, object> >[] expressions) { alter = m => m.UniqueIndex(indexType, indexName, expressions); return(this); }
public IEnumerable <ObjectState> GetDesiredState(SchemaConnection connection, IOutput output) { var schemaDriver = connection.SchemaDriver; var sqlTranslator = new SqlTranslator(schemaDriver, null); HashSet <string> catalogs = new HashSet <string>(schemaDriver.DbDriver.DbStringComparer); foreach (var nrdoTable in codeBase.AllTables) { if (nrdoTable.ExistingName != null) { if (nrdoTable.BeforeStatements.Any()) { throw new ApplicationException("Table " + nrdoTable.Name + " is 'existing' but has before statements, which is no longer supported"); } continue; } output.Verbose("Loading table " + nrdoTable.DatabaseName + " from " + nrdoTable.Type.Name); var table = TableType.Create(schemaName + "." + nrdoTable.DatabaseName); yield return(table); if (preserveColumnOrder) { yield return(FieldOrderSensitivityType.Create(table.Identifier)); } string sequencedPkeyFieldName = null; string sequenceName = null; if (nrdoTable.IsPkeySequenced) { sequencedPkeyFieldName = nrdoTable.PkeyGet.Fields.Single().Name; var sequenceNameBase = getNameHashString(nrdoTable.Name) + "_" + sequencedPkeyFieldName; if (schemaDriver.IsSequenceUsed) { sequenceName = "sq_" + sequenceNameBase; yield return(SequenceType.Create(schemaName + "." + sequenceName)); } if (schemaDriver.IsTriggerUsedForSequence) { var triggerName = "sqt_" + sequenceNameBase; yield return(TriggerType.Create(table.Identifier, triggerName, schemaDriver.GetSequencedFieldTriggerTiming(), TriggerEvents.Insert, schemaDriver.GetSequencedFieldTriggerBody(table.Name, sequencedPkeyFieldName, sequenceName))); } } var fieldIndex = 0; foreach (var nrdoField in nrdoTable.Fields) { if (nrdoField.Name == sequencedPkeyFieldName) { yield return(FieldType.CreateSequencedPkey(table.Identifier, nrdoField.Name, fieldIndex++, nrdoField.DbType, nrdoField.IsNullable, sequenceName)); } else { yield return(FieldType.Create(table.Identifier, nrdoField.Name, fieldIndex++, nrdoField.DbType, nrdoField.IsNullable)); } } foreach (var nrdoIndex in nrdoTable.Indexes) { if (nrdoIndex.IsPrimary) { yield return(UniqueIndexType.CreatePrimaryKey(table.Identifier, nrdoIndex.Name, from field in nrdoIndex.Fields select FieldType.Identifier(field), schemaDriver.DefaultPrimaryKeyCustomState)); } else if (nrdoIndex.IsUnique) { yield return(UniqueIndexType.CreateUnique(table.Identifier, nrdoIndex.Name, from field in nrdoIndex.Fields select FieldType.Identifier(field), schemaDriver.DefaultUniqueConstraintCustomState)); } else { yield return(NonUniqueIndexType.Create(table.Identifier, nrdoIndex.Name, from field in nrdoIndex.Fields select FieldType.Identifier(field), schemaDriver.DefaultIndexCustomState)); } } if (nrdoTable.FulltextFields.Any() && connection.SchemaDriver.IsFulltextSupported(connection)) { var catalog = nrdoTable.FulltextCatalog ?? "NrdoFulltext"; if (!catalogs.Contains(catalog)) { yield return(FulltextCatalogType.Create(catalog)); catalogs.Add(catalog); } var pkey = nrdoTable.Indexes.Where(index => index.IsPrimary).Single(); yield return(FulltextIndexType.Create(table.Identifier, FulltextCatalogType.Identifier(catalog), pkey.Name, nrdoTable.FulltextFields)); } foreach (var nrdoFkey in nrdoTable.References) { if (nrdoFkey.IsFkey) { yield return(FkeyType.Create(table.Identifier, TableType.Identifier(schemaName + "." + nrdoFkey.TargetTable.DatabaseName), nrdoFkey.FkeyName, nrdoFkey.IsCascadingFkey, from fjoin in nrdoFkey.Joins select new FieldPair(fjoin.From.Name, fjoin.To.Name))); } } var beforeIndex = 0; foreach (var nrdoBefore in nrdoTable.BeforeStatements) { yield return(BeforeStatementType.Create(table.Identifier, "0" + nrdoTable.Name, beforeIndex++, nrdoBefore.Name, nrdoBefore.Step, nrdoBefore.Initial, nrdoBefore.Upgrade, sqlTranslator.Translate(nrdoBefore.Statement))); } foreach (var oldName in nrdoTable.RenamedFrom) { var oldDbName = schemaName + "." + oldName.Replace(':', '_'); yield return(TableRenameType.Create(oldDbName, table.Name)); } } foreach (var nrdoQuery in codeBase.AllQueries) { output.Verbose("Loading query " + nrdoQuery.DatabaseName + " from " + nrdoQuery.Type.Name); var queryName = schemaName + "." + nrdoQuery.DatabaseName; var parameters = from param in nrdoQuery.Params select new ProcParam(param.Name, param.DbType); if (nrdoQuery.IsStoredProc) { yield return(QueryType.CreateProc(queryName, parameters, sqlTranslator.Translate(nrdoQuery.Sql))); if (nrdoQuery.IsPreUpgradeHook) { yield return(PreUpgradeHookType.Create(queryName)); } } else if (nrdoQuery.IsStoredFunction) { var returnType = nrdoQuery.Results.Single().DbType; yield return(QueryType.CreateFunction(queryName, parameters, returnType, sqlTranslator.Translate(nrdoQuery.Sql))); } else { yield return(QueryType.CreateUnstored(queryName)); } var beforeIndex = 0; foreach (var nrdoBefore in nrdoQuery.BeforeStatements) { yield return(BeforeStatementType.Create(QueryType.Identifier(queryName), "1" + nrdoQuery.Name, beforeIndex++, nrdoBefore.Name, nrdoBefore.Step, nrdoBefore.Initial, nrdoBefore.Upgrade, sqlTranslator.Translate(nrdoBefore.Statement))); } } }