public object PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder) { try { // prepare and execute the insert IDbCommand insert = session.Batcher.PrepareCommand(insertSQL.CommandType, insertSQL.Text, insertSQL.ParameterTypes); try { binder.BindValues(insert); session.Batcher.ExecuteNonQuery(insert); } finally { session.Batcher.CloseCommand(insert, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not insert: " + persister.GetInfoString(), insertSQL.Text); } SqlString selectSQL = SelectSQL; using (new SessionIdLoggingContext(session.SessionId)) try { //fetch the generated id in a separate query IDbCommand idSelect = session.Batcher.PrepareCommand(CommandType.Text, selectSQL, ParametersTypes); try { BindParameters(session, idSelect, binder.Entity); IDataReader rs = session.Batcher.ExecuteReader(idSelect); try { return GetResult(session, rs, binder.Entity); } finally { session.Batcher.CloseReader(rs); } } finally { session.Batcher.CloseCommand(idSelect, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not retrieve generated id after insert: " + persister.GetInfoString(), insertSQL.Text); } }
protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session) { IDbCommand command = session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes); //Add the output parameter IDbDataParameter idParameter = factory.ConnectionProvider.Driver.GenerateParameter(command, ReturnParameterName, paramType); driveGeneratedParamName = idParameter.ParameterName; idParameter.Direction = ParameterDirection.ReturnValue; command.Parameters.Add(idParameter); return command; }
protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session) { IDbCommand command = session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes); //Add the output parameter IDbDataParameter idParameter = factory.ConnectionProvider.Driver.GenerateParameter(command, ReturnParameterName, paramType); driveGeneratedParamName = idParameter.ParameterName; if (factory.Dialect.InsertGeneratedIdentifierRetrievalMethod == InsertGeneratedIdentifierRetrievalMethod.OutputParameter) idParameter.Direction = ParameterDirection.Output; else if (factory.Dialect.InsertGeneratedIdentifierRetrievalMethod == InsertGeneratedIdentifierRetrievalMethod.ReturnValueParameter) idParameter.Direction = ParameterDirection.ReturnValue; else throw new System.NotImplementedException("Unsupported InsertGeneratedIdentifierRetrievalMethod: " + factory.Dialect.InsertGeneratedIdentifierRetrievalMethod); command.Parameters.Add(idParameter); return command; }
public object PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder) { try { // prepare and execute the insert IDbCommand insert = Prepare(insertSQL, session); try { binder.BindValues(insert); return ExecuteAndExtract(insert, session); } finally { ReleaseStatement(insert, session); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not insert: " + MessageHelper.InfoString(persister), insertSQL.Text); } }
protected internal abstract IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session);
protected SqlCommandInfo[] GenerateSQLDeleteStrings(object[] loadedState) { int span = TableSpan; SqlCommandInfo[] deleteStrings = new SqlCommandInfo[span]; for (int j = span - 1; j >= 0; j--) { SqlDeleteBuilder delete = new SqlDeleteBuilder(Factory.Dialect, Factory) .SetTableName(GetTableName(j)) .SetIdentityColumn(GetKeyColumns(j), IdentifierType); if (Factory.Settings.IsCommentsEnabled) { delete.SetComment("delete " + EntityName + " [" + j + "]"); } bool[] versionability = PropertyVersionability; IType[] types = PropertyTypes; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { bool include = versionability[i] && IsPropertyOfTable(i, j); if (include) { // this property belongs to the table and it is not specifically // excluded from optimistic locking by optimistic-lock="false" string[] _propertyColumnNames = GetPropertyColumnNames(i); bool[] propertyNullness = types[i].ToColumnNullness(loadedState[i], Factory); SqlType[] sqlt = types[i].SqlTypes(Factory); for (int k = 0; k < propertyNullness.Length; k++) { if (propertyNullness[k]) { delete.AddWhereFragment(_propertyColumnNames[k], sqlt[k], " = "); } else { delete.AddWhereFragment(_propertyColumnNames[k] + " is null"); } } } } deleteStrings[j] = delete.ToSqlCommandInfo(); } return deleteStrings; }
/// <summary> /// Perform an SQL DELETE /// </summary> public void Delete(object id, object version, int j, object obj, SqlCommandInfo sql, ISessionImplementor session, object[] loadedState) { if (IsInverseTable(j)) { return; } // NH : Only use version if lock mode is Version bool useVersion = j == 0 && IsVersioned && Versioning.OptimisticLock.Version == entityMetamodel.OptimisticLockMode; //bool callable = IsDeleteCallable(j); IExpectation expectation = Expectations.AppropriateExpectation(deleteResultCheckStyles[j]); bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable; if (log.IsDebugEnabled) { log.Debug("Deleting entity: " + MessageHelper.InfoString(this, id, Factory)); if (useVersion) { log.Debug("Version: " + version); } } if (IsTableCascadeDeleteEnabled(j)) { if (log.IsDebugEnabled) { log.Debug("delete handled by foreign key constraint: " + GetTableName(j)); } return; //EARLY EXIT! } try { int index = 0; IDbCommand statement; if (useBatch) { statement = session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes); } else { statement = session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); } try { //index += expectation.Prepare(statement, factory.ConnectionProvider.Driver); // Do the key. The key is immutable so we can use the _current_ object state - not necessarily // the state at the time the delete was issued IdentifierType.NullSafeSet(statement, id, index, session); index += IdentifierColumnSpan; // We should use the _current_ object state (ie. after any updates that occurred during flush) if (useVersion) { VersionType.NullSafeSet(statement, version, index, session); } else if (entityMetamodel.OptimisticLockMode > Versioning.OptimisticLock.Version && loadedState != null) { bool[] versionability = PropertyVersionability; IType[] types = PropertyTypes; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { if (IsPropertyOfTable(i, j) && versionability[i]) { // this property belongs to the table and it is not specifically // excluded from optimistic locking by optimistic-lock="false" bool[] settable = types[i].ToColumnNullness(loadedState[i], Factory); types[i].NullSafeSet(statement, loadedState[i], index, settable, session); index += ArrayHelper.CountTrue(settable); } } } if (useBatch) { session.Batcher.AddToBatch(expectation); } else { Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement); } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(statement, null); } } } catch (DbException sqle) { var exceptionContext = new AdoExceptionContextInfo { SqlException = sqle, Message = "could not delete: " + MessageHelper.InfoString(this, id, Factory), Sql = sql.Text.ToString(), EntityName = EntityName, EntityId = id }; throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext); } }
/// <summary> Perform an SQL UPDATE or SQL INSERT</summary> protected internal virtual void UpdateOrInsert(object id, object[] fields, object[] oldFields, object rowId, bool[] includeProperty, int j, object oldVersion, object obj, SqlCommandInfo sql, ISessionImplementor session) { if (!IsInverseTable(j)) { bool isRowToUpdate; if (IsNullableTable(j) && oldFields != null && IsAllNull(oldFields, j)) { //don't bother trying to update, we know there is no row there yet isRowToUpdate = false; } else if (IsNullableTable(j) && IsAllNull(fields, j)) { //if all fields are null, we might need to delete existing row isRowToUpdate = true; Delete(id, oldVersion, j, obj, SqlDeleteStrings[j], session, null); } else { //there is probably a row there, so try to update //if no rows were updated, we will find out isRowToUpdate = Update(id, fields, oldFields, rowId, includeProperty, j, oldVersion, obj, sql, session); } if (!isRowToUpdate && !IsAllNull(fields, j)) { // assume that the row was not there since it previously had only null // values, so do an INSERT instead //TODO: does not respect dynamic-insert Insert(id, fields, PropertyInsertability, j, SqlInsertStrings[j], obj, session); } } }
/// <summary> /// Perform an SQL INSERT, and then retrieve a generated identifier. /// </summary> /// <remarks> /// This form is used for PostInsertIdentifierGenerator-style ids (IDENTITY, select, etc). /// </remarks> protected object Insert(object[] fields, bool[] notNull, SqlCommandInfo sql, object obj, ISessionImplementor session) { if (log.IsDebugEnabled) { log.Debug("Inserting entity: " + EntityName + " (native id)"); if (IsVersioned) { log.Debug("Version: " + Versioning.GetVersion(fields, this)); } } IBinder binder = new GeneratedIdentifierBinder(fields, notNull, session, obj, this); return identityDelegate.PerformInsert(sql, session, binder); }
/// <summary> /// Persist an object, using a natively generated identifier /// </summary> protected object Insert(object[] fields, bool[] notNull, SqlCommandInfo sql, object obj, ISessionImplementor session) { if (log.IsDebugEnabled) { log.Debug("Inserting entity: " + ClassName + " (native id)"); if (IsVersioned) { log.Debug("Version: " + Versioning.GetVersion(fields, this)); } } try { SqlString insertSelectSQL = null; if (sql.CommandType == CommandType.Text) { insertSelectSQL = Dialect.AddIdentitySelectToInsert(sql.Text, GetKeyColumns(0)[0], GetTableName(0)); } if (insertSelectSQL != null) { // Use one statement to insert the row and get the generated id IDbCommand insertSelect = session.Batcher.PrepareCommand(CommandType.Text, insertSelectSQL, sql.ParameterTypes); IDataReader rs = null; try { // Well, it's always the first table to dehydrate, so pass 0 as the position Dehydrate(null, fields, notNull, propertyColumnInsertable, 0, insertSelect, session, 0); rs = session.Batcher.ExecuteReader(insertSelect); return GetGeneratedIdentity(obj, session, rs); } finally { session.Batcher.CloseCommand(insertSelect, rs); } } else { // Do the insert IDbCommand statement = session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); try { // Well, it's always the first table to dehydrate, so pass 0 as the position Dehydrate(null, fields, notNull, propertyColumnInsertable, 0, statement, session, 0); session.Batcher.ExecuteNonQuery(statement); // Fetch the generated id in a separate query. This is done inside the first try/finally block // to keep the insert command open, so that the batcher does not close the connection. // // It's possible that some ADO.NET provider will not allow two open IDbCommands for the same connection, // in that case we'll have to rewrite the code to use some sort of lock on IBatcher. SqlString idselectSql = new SqlString(SqlIdentitySelect(IdentifierColumnNames[0], GetTableName(0))); IDbCommand idselect = session.Batcher.PrepareCommand(CommandType.Text, idselectSql, SqlTypeFactory.NoTypes); IDataReader rs = null; try { rs = session.Batcher.ExecuteReader(idselect); return GetGeneratedIdentity(obj, session, rs); } finally { session.Batcher.CloseCommand(idselect, rs); } } finally { session.Batcher.CloseCommand(statement, null); } } } catch (HibernateException) { // Do not call Convert on HibernateExceptions throw; } catch (Exception sqle) { throw Convert(sqle, "could not insert: " + MessageHelper.InfoString(this), sql.Text); } }
protected void Update( object id, object[] fields, object[] oldFields, bool[] includeProperty, int j, object oldVersion, object obj, SqlCommandInfo sql, ISessionImplementor session) { bool useVersion = j == 0 && IsVersioned; IExpectation expectation = Expectations.AppropriateExpectation(updateResultCheckStyles[j]); bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable; //note: updates to joined tables can't be batched... if (log.IsDebugEnabled) { log.Debug("Updating entity: " + MessageHelper.InfoString(this, id)); if (useVersion) { log.Debug("Existing version: " + oldVersion + " -> New Version: " + fields[VersionProperty]); } } try { IDbCommand statement = useBatch ? session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes) : session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); try { int index = 0; //index += expectation.Prepare(statement, factory.ConnectionProvider.Driver); index = Dehydrate(id, fields, includeProperty, propertyColumnUpdateable, j, statement, session, index); // Write any appropriate versioning conditional parameters if (useVersion && OptimisticLockMode == OptimisticLockMode.Version) { VersionType.NullSafeSet(statement, oldVersion, index, session); } else if (OptimisticLockMode.Version < OptimisticLockMode && null != oldFields) { bool[] versionability = PropertyVersionability; bool[] includeOldField = OptimisticLockMode == OptimisticLockMode.All ? PropertyUpdateability : includeProperty; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { bool include = includeOldField[i] && IsPropertyOfTable(i, j) && versionability[i]; if (include) { if (!PropertyTypes[i].IsDatabaseNull(oldFields[i])) { PropertyTypes[i].NullSafeSet(statement, oldFields[i], index, session); index += GetPropertyColumnSpan(i); } } } } if (useBatch) { session.Batcher.AddToBatch(expectation); } else { Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement); } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(statement, null); } } } catch (HibernateException) { // Do not call Convert on HibernateExceptions throw; } catch (Exception sqle) { throw Convert(sqle, "could not update: " + MessageHelper.InfoString(this, id), sql.Text); } }
public void Update( object id, object[] fields, int[] dirtyFields, bool hasDirtyCollection, object[] oldFields, object oldVersion, object obj, ISessionImplementor session) { bool[] tableUpdateNeeded = GetTableUpdateNeeded(dirtyFields, hasDirtyCollection); int span = TableSpan; bool[] propsToUpdate; SqlCommandInfo[] updateStrings; if (entityMetamodel.IsDynamicUpdate && dirtyFields != null) { // For the case of dynamic-update="true", we need to generate the UPDATE SQL propsToUpdate = GetPropertiesToUpdate(dirtyFields, hasDirtyCollection); updateStrings = new SqlCommandInfo[span]; for (int j = 0; j < span; j++) { updateStrings[j] = tableUpdateNeeded[j] ? GenerateUpdateString(propsToUpdate, j, oldFields) : null; } } else { // For the case of dynamic-update="false", or no snapshot, we use the static SQL updateStrings = SqlUpdateStrings; propsToUpdate = PropertyUpdateability; } for (int j = 0; j < span; j++) { // Now update only the tables with dirty properties (and the table with the version number) if (tableUpdateNeeded[j]) { Update(id, fields, oldFields, propsToUpdate, j, oldVersion, obj, updateStrings[j], session); } } }
public virtual void Append(SqlCommandInfo commandInfo) { resultSetsCount++; sqlString = sqlString.Append(commandInfo.Text).Append(";").Append(Environment.NewLine); types.AddRange(commandInfo.ParameterTypes); }
protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session) { return session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes); }
public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) { this.factory = factory; this.cache = cache; if (factory.Settings.IsStructuredCacheEntriesEnabled) { cacheEntryStructure = collection.IsMap ? (ICacheEntryStructure) new StructuredMapCacheEntry() : (ICacheEntryStructure) new StructuredCollectionCacheEntry(); } else { cacheEntryStructure = new UnstructuredCacheEntry(); } dialect = factory.Dialect; sqlExceptionConverter = factory.SQLExceptionConverter; collectionType = collection.CollectionType; role = collection.Role; entityName = collection.OwnerEntityName; ownerPersister = factory.GetEntityPersister(entityName); queryLoaderName = collection.LoaderName; nodeName = collection.NodeName; isMutable = collection.IsMutable; Table table = collection.CollectionTable; fetchMode = collection.Element.FetchMode; elementType = collection.Element.Type; isPrimitiveArray = collection.IsPrimitiveArray; isArray = collection.IsArray; subselectLoadable = collection.IsSubselectLoadable; qualifiedTableName = table.GetQualifiedName(dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); int spacesSize = 1 + collection.SynchronizedTables.Count; spaces = new string[spacesSize]; int ispa = 0; spaces[ispa++] = qualifiedTableName; foreach (string s in collection.SynchronizedTables) { spaces[ispa++] = s; } sqlOrderByString = collection.OrderBy; hasOrder = sqlOrderByString != null; sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect, factory.SQLFunctionRegistry) : null; sqlWhereString = !string.IsNullOrEmpty(collection.Where) ? '(' + collection.Where + ')' : null; hasWhere = sqlWhereString != null; sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry) : null; hasOrphanDelete = collection.HasOrphanDelete; int batch = collection.BatchSize; if (batch == -1) { batch = factory.Settings.DefaultBatchFetchSize; } batchSize = batch; isVersioned = collection.IsOptimisticLocked; keyType = collection.Key.Type; int keySpan = collection.Key.ColumnSpan; keyColumnNames = new string[keySpan]; keyColumnAliases = new string[keySpan]; int k = 0; foreach (Column col in collection.Key.ColumnIterator) { keyColumnNames[k] = col.GetQuotedName(dialect); keyColumnAliases[k] = col.GetAlias(dialect); k++; } ISet distinctColumns = new HashedSet(); CheckColumnDuplication(distinctColumns, collection.Key.ColumnIterator); #region Element IValue element = collection.Element; if (!collection.IsOneToMany) { CheckColumnDuplication(distinctColumns, element.ColumnIterator); } string elemNode = collection.ElementNodeName; if (elementType.IsEntityType) { string _entityName = ((EntityType) elementType).GetAssociatedEntityName(); elementPersister = factory.GetEntityPersister(_entityName); if (elemNode == null) { elemNode = cfg.GetClassMapping(_entityName).NodeName; } // NativeSQL: collect element column and auto-aliases } else { elementPersister = null; } elementNodeName = elemNode; int elementSpan = element.ColumnSpan; elementColumnAliases = new string[elementSpan]; elementColumnNames = new string[elementSpan]; elementFormulaTemplates = new string[elementSpan]; elementFormulas = new string[elementSpan]; elementColumnIsSettable = new bool[elementSpan]; elementColumnIsInPrimaryKey = new bool[elementSpan]; bool isPureFormula = true; bool hasNotNullableColumns = false; int j = 0; foreach (ISelectable selectable in element.ColumnIterator) { elementColumnAliases[j] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula form = (Formula) selectable; elementFormulaTemplates[j] = form.GetTemplate(dialect, factory.SQLFunctionRegistry); elementFormulas[j] = form.FormulaString; } else { Column col = (Column) selectable; elementColumnNames[j] = col.GetQuotedName(dialect); elementColumnIsSettable[j] = true; elementColumnIsInPrimaryKey[j] = !col.IsNullable; if (!col.IsNullable) { hasNotNullableColumns = true; } isPureFormula = false; } j++; } elementIsPureFormula = isPureFormula; //workaround, for backward compatibility of sets with no //not-null columns, assume all columns are used in the //row locator SQL if (!hasNotNullableColumns) { ArrayHelper.Fill(elementColumnIsInPrimaryKey, true); } #endregion #region INDEX AND ROW SELECT hasIndex = collection.IsIndexed; if (hasIndex) { // NativeSQL: collect index column and auto-aliases IndexedCollection indexedCollection = (IndexedCollection) collection; indexType = indexedCollection.Index.Type; int indexSpan = indexedCollection.Index.ColumnSpan; indexColumnNames = new string[indexSpan]; indexFormulaTemplates = new string[indexSpan]; indexFormulas = new string[indexSpan]; indexColumnIsSettable = new bool[indexSpan]; indexColumnAliases = new string[indexSpan]; bool hasFormula = false; int i = 0; foreach (ISelectable selectable in indexedCollection.Index.ColumnIterator) { indexColumnAliases[i] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula indexForm = (Formula) selectable; indexFormulaTemplates[i] = indexForm.GetTemplate(dialect, factory.SQLFunctionRegistry); indexFormulas[i] = indexForm.FormulaString; hasFormula = true; } else { Column indexCol = (Column) selectable; indexColumnNames[i] = indexCol.GetQuotedName(dialect); indexColumnIsSettable[i] = true; } i++; } indexContainsFormula = hasFormula; baseIndex = indexedCollection.IsList ? ((List) indexedCollection).BaseIndex : 0; indexNodeName = indexedCollection.IndexNodeName; CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnIterator); } else { indexContainsFormula = false; indexColumnIsSettable = null; indexFormulaTemplates = null; indexFormulas = null; indexType = null; indexColumnNames = null; indexColumnAliases = null; baseIndex = 0; indexNodeName = null; } hasIdentifier = collection.IsIdentified; if (hasIdentifier) { if (collection.IsOneToMany) { throw new MappingException("one-to-many collections with identifiers are not supported."); } IdentifierCollection idColl = (IdentifierCollection) collection; identifierType = idColl.Identifier.Type; Column col = null; foreach (Column column in idColl.Identifier.ColumnIterator) { col = column; break; } identifierColumnName = col.GetQuotedName(dialect); identifierColumnAlias = col.GetAlias(dialect); identifierGenerator = idColl.Identifier.CreateIdentifierGenerator(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName, null); // NH see : identityDelegate declaration IPostInsertIdentifierGenerator pig = (identifierGenerator as IPostInsertIdentifierGenerator); if (pig != null) { identityDelegate = pig.GetInsertGeneratedIdentifierDelegate(this, Factory, UseGetGeneratedKeys()); } else { identityDelegate = null; } CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnIterator); } else { identifierType = null; identifierColumnName = null; identifierColumnAlias = null; identifierGenerator = null; identityDelegate = null; } #endregion #region GENERATE THE SQL // NH Different behavior : for the Insert SQL we are managing isPostInsertIdentifier (not supported in H3.2.5) if (collection.CustomSQLInsert == null) { if (!IsIdentifierAssignedByInsert) { sqlInsertRowString = GenerateInsertRowString(); } else { sqlInsertRowString = GenerateIdentityInsertRowString(); } insertCallable = false; insertCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { SqlType[] parmsTypes = GenerateInsertRowString().ParameterTypes; sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, parmsTypes); insertCallable = collection.IsCustomInsertCallable; insertCheckStyle = collection.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable); } sqlUpdateRowString = GenerateUpdateRowString(); if (collection.CustomSQLUpdate == null) { updateCallable = false; updateCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes); updateCallable = collection.IsCustomUpdateCallable; updateCheckStyle = collection.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable); } sqlDeleteRowString = GenerateDeleteRowString(); if (collection.CustomSQLDelete == null) { deleteCallable = false; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes); deleteCallable = collection.IsCustomDeleteCallable; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } sqlDeleteString = GenerateDeleteString(); if (collection.CustomSQLDeleteAll == null) { deleteAllCallable = false; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteString = new SqlCommandInfo(collection.CustomSQLDeleteAll, sqlDeleteString.ParameterTypes); deleteAllCallable = collection.IsCustomDeleteAllCallable; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } isCollectionIntegerIndex = collection.IsIndexed && !collection.IsMap; sqlDetectRowByIndexString = GenerateDetectRowByIndexString(); sqlDetectRowByElementString = GenerateDetectRowByElementString(); sqlSelectRowByIndexString = GenerateSelectRowByIndexString(); LogStaticSQL(); #endregion isLazy = collection.IsLazy; isExtraLazy = collection.ExtraLazy; isInverse = collection.IsInverse; if (collection.IsArray) { elementClass = ((Array) collection).ElementClass; } else { // for non-arrays, we don't need to know the element class elementClass = null; } if (elementType.IsComponentType) { elementPropertyMapping = new CompositeElementPropertyMapping(elementColumnNames, elementFormulaTemplates, (IAbstractComponentType) elementType, factory); } else if (!elementType.IsEntityType) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } else { elementPropertyMapping = elementPersister as IPropertyMapping; if (elementPropertyMapping == null) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } } // Handle any filters applied to this collection filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry); // Handle any filters applied to this collection for many-to-many manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry); manyToManyWhereString = !string.IsNullOrEmpty(collection.ManyToManyWhere) ? "( " + collection.ManyToManyWhere + " )" : null; manyToManyWhereTemplate = manyToManyWhereString == null ? null : Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect, factory.SQLFunctionRegistry); manyToManyOrderByString = collection.ManyToManyOrdering; manyToManyOrderByTemplate = manyToManyOrderByString == null ? null : Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect, factory.SQLFunctionRegistry); InitCollectionPropertyMap(); }
public void Update(object id, object[] fields, int[] dirtyFields, bool hasDirtyCollection, object[] oldFields, object oldVersion, object obj, object rowId, ISessionImplementor session) { //note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-before-update // oldFields==null just means we had no snapshot to begin with (we might have used select-before-update to get the dirtyFields) bool[] tableUpdateNeeded = GetTableUpdateNeeded(dirtyFields, hasDirtyCollection); int span = TableSpan; bool[] propsToUpdate; SqlCommandInfo[] updateStrings; if (entityMetamodel.IsDynamicUpdate && dirtyFields != null) { // For the case of dynamic-update="true", we need to generate the UPDATE SQL propsToUpdate = GetPropertiesToUpdate(dirtyFields, hasDirtyCollection); // don't need to check laziness (dirty checking algorithm handles that) updateStrings = new SqlCommandInfo[span]; for (int j = 0; j < span; j++) { updateStrings[j] = tableUpdateNeeded[j] ? GenerateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null) : null; } } else { // For the case of dynamic-update="false", or no snapshot, we use the static SQL updateStrings = GetUpdateStrings(rowId != null, HasUninitializedLazyProperties(obj, session.EntityMode)); propsToUpdate = GetPropertyUpdateability(obj, session.EntityMode); } for (int j = 0; j < span; j++) { // Now update only the tables with dirty properties (and the table with the version number) if (tableUpdateNeeded[j]) { UpdateOrInsert(id, fields, oldFields, j == 0 ? rowId : null, propsToUpdate, j, oldVersion, obj, updateStrings[j], session); } } }
public virtual void PostInstantiate() { int tableSpan = TableSpan; sqlInsertStrings = new SqlCommandInfo[tableSpan]; sqlDeleteStrings = new SqlCommandInfo[tableSpan]; sqlUpdateStrings = new SqlCommandInfo[tableSpan]; for (int j = 0; j < tableSpan; j++) { SqlCommandInfo defaultInsert = GenerateInsertString(false, PropertyInsertability, j); sqlInsertStrings[j] = customSQLInsert[j] == null ? defaultInsert : new SqlCommandInfo(customSQLInsert[j], defaultInsert.ParameterTypes); SqlCommandInfo defaultUpdate = GenerateUpdateString(PropertyUpdateability, j, null); sqlUpdateStrings[j] = customSQLUpdate[j] == null ? defaultUpdate : new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes); SqlCommandInfo defaultDelete = GenerateDeleteString(j); sqlDeleteStrings[j] = customSQLDelete[j] == null ? defaultDelete : new SqlCommandInfo(customSQLDelete[j], defaultDelete.ParameterTypes); } sqlIdentityInsertString = IsIdentifierAssignedByInsert ? GenerateIdentityInsertString(PropertyInsertability) : null; sqlSnapshotSelectString = GenerateSnapshotSelectString(); sqlVersionSelectString = GenerateSelectVersionString(); if (HasInsertGeneratedProperties) { sqlInsertGeneratedValuesSelectString = GenerateInsertGeneratedValuesSelectString(); } if (HasUpdateGeneratedProperties) { sqlUpdateGeneratedValuesSelectString = GenerateUpdateGeneratedValuesSelectString(); } // This is used to determine updates for objects that came in via update() tableHasColumns = new bool[sqlUpdateStrings.Length]; for (int j = 0; j < sqlUpdateStrings.Length; j++) { tableHasColumns[j] = sqlUpdateStrings[j] != null; } CreateLoaders(); CreateUniqueKeyLoaders(); CreateQueryLoader(); InitLockers(); }
/// <summary> /// Perform an SQL INSERT. /// </summary> /// <remarks> /// This for is used for all non-root tables as well as the root table /// in cases where the identifier value is known before the insert occurs. /// </remarks> protected void Insert(object id, object[] fields, bool[] notNull, int j, SqlCommandInfo sql, object obj, ISessionImplementor session) { if (IsInverseTable(j)) { return; } //note: it is conceptually possible that a UserType could map null to // a non-null value, so the following is arguable: if (IsNullableTable(j) && IsAllNull(fields, j)) { return; } if (log.IsDebugEnabled) { log.Debug("Inserting entity: " + MessageHelper.InfoString(this, id, Factory)); if (j == 0 && IsVersioned) { log.Debug("Version: " + Versioning.GetVersion(fields, this)); } } IExpectation expectation = Expectations.AppropriateExpectation(insertResultCheckStyles[j]); //bool callable = IsInsertCallable(j); // we can't batch joined inserts, *especially* not if it is an identity insert; // nor can we batch statements where the expectation is based on an output param bool useBatch = j == 0 && expectation.CanBeBatched; try { // Render the SQL query IDbCommand insertCmd = useBatch ? session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes) : session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); try { int index = 0; //index += expectation.Prepare(insertCmd, factory.ConnectionProvider.Driver); // Write the values of the field onto the prepared statement - we MUST use the // state at the time the insert was issued (cos of foreign key constraints). // Not necessarily the obect's current state Dehydrate(id, fields, null, notNull, propertyColumnInsertable, j, insertCmd, session, index); if (useBatch) { session.Batcher.AddToBatch(expectation); } else { expectation.VerifyOutcomeNonBatched(session.Batcher.ExecuteNonQuery(insertCmd), insertCmd); } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(insertCmd, null); } } } catch (DbException sqle) { var exceptionContext = new AdoExceptionContextInfo { SqlException = sqle, Message = "could not insert: " + MessageHelper.InfoString(this, id), Sql = sql.ToString(), EntityName = EntityName, EntityId = id }; throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext); } }
/// <summary> /// Delete an object. /// </summary> public void Delete(object id, object version, int j, object obj, SqlCommandInfo sql, ISessionImplementor session, object[] loadedState) { bool useVersion = j == 0 && IsVersioned; IExpectation expectation = Expectations.AppropriateExpectation(deleteResultCheckStyles[j]); bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable; if (log.IsDebugEnabled) { log.Debug("Deleting entity: " + MessageHelper.InfoString(this, id)); if (useVersion) { log.Debug("Version: " + version); } } try { IDbCommand statement; if (useBatch) { statement = session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes); } else { statement = session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); } try { int index = 0; //index += expectation.Prepare(statement, factory.ConnectionProvider.Driver); // Do the key. The key is immutable so we can use the _current_ object state IdentifierType.NullSafeSet(statement, id, index, session); index += IdentifierColumnSpan; if (useVersion) { VersionType.NullSafeSet(statement, version, index, session); } else if (entityMetamodel.OptimisticLockMode > OptimisticLockMode.Version && loadedState != null) { IType[] types = PropertyTypes; bool[] versionability = PropertyVersionability; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { if (IsPropertyOfTable(i, j) && versionability[i] && !types[i].IsDatabaseNull(loadedState[i])) { types[i].NullSafeSet(statement, loadedState[i], index, session); index += GetPropertyColumnSpan(i); } } } if (useBatch) { session.Batcher.AddToBatch(expectation); } else { Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement); } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(statement, null); } } } catch (HibernateException) { // Do not call Convert on HibernateExceptions throw; } catch (Exception sqle) { throw Convert(sqle, "could not delete: " + MessageHelper.InfoString(this, id), sql.Text); } }
protected bool Update(object id, object[] fields, object[] oldFields, object rowId, bool[] includeProperty, int j, object oldVersion, object obj, SqlCommandInfo sql, ISessionImplementor session) { bool useVersion = j == 0 && IsVersioned; IExpectation expectation = Expectations.AppropriateExpectation(updateResultCheckStyles[j]); //bool callable = IsUpdateCallable(j); bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable; //note: updates to joined tables can't be batched... if (log.IsDebugEnabled) { log.Debug("Updating entity: " + MessageHelper.InfoString(this, id, Factory)); if (useVersion) { log.Debug("Existing version: " + oldVersion + " -> New Version: " + fields[VersionProperty]); } } try { int index = 0; IDbCommand statement = useBatch ? session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes) : session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); try { //index += expectation.Prepare(statement, factory.ConnectionProvider.Driver); //Now write the values of fields onto the prepared statement index = Dehydrate(id, fields, rowId, includeProperty, propertyColumnUpdateable, j, statement, session, index); // Write any appropriate versioning conditional parameters if (useVersion && Versioning.OptimisticLock.Version == entityMetamodel.OptimisticLockMode) { if (CheckVersion(includeProperty)) VersionType.NullSafeSet(statement, oldVersion, index, session); } else if (entityMetamodel.OptimisticLockMode > Versioning.OptimisticLock.Version && oldFields != null) { bool[] versionability = PropertyVersionability; bool[] includeOldField = OptimisticLockMode == Versioning.OptimisticLock.All ? PropertyUpdateability : includeProperty; IType[] types = PropertyTypes; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { bool include = includeOldField[i] && IsPropertyOfTable(i, j) && versionability[i]; if (include) { bool[] settable = types[i].ToColumnNullness(oldFields[i], Factory); types[i].NullSafeSet(statement, oldFields[i], index, settable, session); index += ArrayHelper.CountTrue(settable); } } } if (useBatch) { session.Batcher.AddToBatch(expectation); return true; } else { return Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement); } } catch (StaleStateException e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw new StaleObjectStateException(EntityName, id); } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(statement, null); } } } catch (DbException sqle) { var exceptionContext = new AdoExceptionContextInfo { SqlException = sqle, Message = "could not update: " + MessageHelper.InfoString(this, id, Factory), Sql = sql.Text.ToString(), EntityName = EntityName, EntityId = id }; throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext); } }
protected SqlCommandInfo[] GenerateDeleteStrings(object[] loadedState) { int span = TableSpan; SqlCommandInfo[] deleteStrings = new SqlCommandInfo[span]; for (int j = span - 1; j >= 0; j--) { SqlDeleteBuilder delete = new SqlDeleteBuilder(Factory) .SetTableName(GetTableName(j)) .SetIdentityColumn(GetKeyColumns(j), IdentifierType); IType[] types = PropertyTypes; bool[] versionability = PropertyVersionability; //bool[] includeInWhere = PropertyUpdateability; for (int i = 0; i < entityMetamodel.PropertySpan; i++) { bool include = versionability[i] && IsPropertyOfTable(i, j); if (include) { // this property belongs to the table and it is not specifically // excluded from optimistic locking by optimistic-lock="false" string[] propertyColumnNames = GetPropertyColumnNames(i); if (types[i].IsDatabaseNull(loadedState[i])) { for (int k = 0; k < propertyColumnNames.Length; k++) { delete.AddWhereFragment(propertyColumnNames[k] + " is null"); } } else { delete.AddWhereFragment(propertyColumnNames, PropertyTypes[i], " = "); } } } deleteStrings[j] = delete.ToSqlCommandInfo(); } return deleteStrings; }
public void Update(object id, object[] fields, int[] dirtyFields, bool hasDirtyCollection, object[] oldFields, object oldVersion, object obj, object rowId, ISessionImplementor session) { //note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-before-update // oldFields==null just means we had no snapshot to begin with (we might have used select-before-update to get the dirtyFields) bool[] tableUpdateNeeded = GetTableUpdateNeeded(dirtyFields, hasDirtyCollection); int span = TableSpan; bool[] propsToUpdate; SqlCommandInfo[] updateStrings; EntityEntry entry = session.PersistenceContext.GetEntry(obj); // Ensure that an immutable or non-modifiable entity is not being updated unless it is // in the process of being deleted. if (entry == null && !IsMutable) throw new InvalidOperationException("Updating immutable entity that is not in session yet!"); if (entityMetamodel.IsDynamicUpdate && dirtyFields != null) { // For the case of dynamic-update="true", we need to generate the UPDATE SQL propsToUpdate = GetPropertiesToUpdate(dirtyFields, hasDirtyCollection); // don't need to check laziness (dirty checking algorithm handles that) updateStrings = new SqlCommandInfo[span]; for (int j = 0; j < span; j++) { updateStrings[j] = tableUpdateNeeded[j] ? GenerateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null) : null; } } else if (!IsModifiableEntity(entry)) { // We need to generate UPDATE SQL when a non-modifiable entity (e.g., read-only or immutable) // needs: // - to have references to transient entities set to null before being deleted // - to have version incremented do to a "dirty" association // If dirtyFields == null, then that means that there are no dirty properties to // to be updated; an empty array for the dirty fields needs to be passed to // getPropertiesToUpdate() instead of null. propsToUpdate = this.GetPropertiesToUpdate( (dirtyFields == null ? ArrayHelper.EmptyIntArray : dirtyFields), hasDirtyCollection); // don't need to check laziness (dirty checking algorithm handles that) updateStrings = new SqlCommandInfo[span]; for (int j = 0; j < span; j++) { updateStrings[j] = tableUpdateNeeded[j] ? GenerateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null) : null; } } else { // For the case of dynamic-update="false", or no snapshot, we use the static SQL updateStrings = GetUpdateStrings(rowId != null, HasUninitializedLazyProperties(obj, session.EntityMode)); propsToUpdate = GetPropertyUpdateability(obj, session.EntityMode); } for (int j = 0; j < span; j++) { // Now update only the tables with dirty properties (and the table with the version number) if (tableUpdateNeeded[j]) { UpdateOrInsert(id, fields, oldFields, j == 0 ? rowId : null, propsToUpdate, j, oldVersion, obj, updateStrings[j], session); } } }
/// <summary> /// Persist an object /// </summary> protected void Insert( object id, object[] fields, bool[] notNull, int j, SqlCommandInfo sql, object obj, ISessionImplementor session) { if (log.IsDebugEnabled) { log.Debug("Inserting entity: " + MessageHelper.InfoString(this, id)); if (IsVersioned) { log.Debug("Version: " + Versioning.GetVersion(fields, this)); } } IExpectation expectation = Expectations.AppropriateExpectation(insertResultCheckStyles[j]); bool useBatch = j == 0 && expectation.CanBeBatched; try { // Render the SQL query IDbCommand insertCmd = useBatch ? session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes) : session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes); try { // Write the values of the field onto the prepared statement - we MUST use the // state at the time the insert was issued (cos of foreign key constraints) // not necessarily the obect's current state int index = 0; //index += expectation.Prepare(insertCmd, factory.ConnectionProvider.Driver); Dehydrate(id, fields, notNull, propertyColumnInsertable, j, insertCmd, session, index); if (useBatch) { session.Batcher.AddToBatch(expectation); } else { Check(session.Batcher.ExecuteNonQuery(insertCmd), id, j, expectation, insertCmd); } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch) { session.Batcher.CloseCommand(insertCmd, null); } } } catch (HibernateException) { // Do not call Convert on HibernateExceptions throw; } catch (Exception sqle) { throw Convert(sqle, "could not insert: " + MessageHelper.InfoString(this, id), sql.Text); } }
public virtual void PostInstantiate() { #region insert/update/delete SQLs // this section was moved from PostConstruct() method (know difference in NH) int joinSpan = TableSpan; sqlDeleteStrings = new SqlCommandInfo[joinSpan]; sqlInsertStrings = new SqlCommandInfo[joinSpan]; sqlUpdateStrings = new SqlCommandInfo[joinSpan]; sqlLazyUpdateStrings = new SqlCommandInfo[joinSpan]; sqlUpdateByRowIdString = rowIdName == null ? null : GenerateUpdateString(PropertyUpdateability, 0, true); sqlLazyUpdateByRowIdString = rowIdName == null ? null : GenerateUpdateString(NonLazyPropertyUpdateability, 0, true); for (int j = 0; j < joinSpan; j++) { SqlCommandInfo defaultInsert = GenerateInsertString(PropertyInsertability, j); SqlCommandInfo defaultUpdate = GenerateUpdateString(PropertyUpdateability, j, false); SqlCommandInfo defaultDelete = GenerateDeleteString(j); sqlInsertStrings[j] = customSQLInsert[j] != null ? new SqlCommandInfo(customSQLInsert[j], defaultInsert.ParameterTypes) : defaultInsert; sqlUpdateStrings[j] = customSQLUpdate[j] != null ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) : defaultUpdate; // NH: in practice for lazy update de update sql is the same any way. sqlLazyUpdateStrings[j] = customSQLUpdate[j] != null ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) : GenerateUpdateString(NonLazyPropertyUpdateability, j, false); sqlDeleteStrings[j] = customSQLDelete[j] != null ? new SqlCommandInfo(customSQLDelete[j], defaultDelete.ParameterTypes) : defaultDelete; } tableHasColumns = new bool[joinSpan]; for (int j = 0; j < joinSpan; j++) { tableHasColumns[j] = sqlUpdateStrings[j] != null; } //select SQL sqlSnapshotSelectString = GenerateSnapshotSelectString(); sqlLazySelectString = GenerateLazySelectString(); sqlVersionSelectString = GenerateSelectVersionString(); if (HasInsertGeneratedProperties) { sqlInsertGeneratedValuesSelectString = GenerateInsertGeneratedValuesSelectString(); } if (HasUpdateGeneratedProperties) { sqlUpdateGeneratedValuesSelectString = GenerateUpdateGeneratedValuesSelectString(); } if (IsIdentifierAssignedByInsert) { identityDelegate = ((IPostInsertIdentifierGenerator)IdentifierGenerator).GetInsertGeneratedIdentifierDelegate(this, Factory, UseGetGeneratedKeys()); SqlCommandInfo defaultInsert = GenerateIdentityInsertString(PropertyInsertability); sqlIdentityInsertString = customSQLInsert[0] != null ? new SqlCommandInfo(customSQLInsert[0], defaultInsert.ParameterTypes) : defaultInsert; } else { sqlIdentityInsertString = null; } LogStaticSQL(); #endregion CreateLoaders(); CreateUniqueKeyLoaders(); CreateQueryLoader(); }
public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { this.factory = factory; dialect = factory.Dialect; this.cache = cache; //sqlExceptionConverter = factory.SQLExceptionConverter; collectionType = collection.CollectionType; role = collection.Role; ownerClass = collection.OwnerClass; ownerPersister = factory.GetEntityPersister(ownerClass); queryLoaderName = collection.LoaderName; Alias alias = new Alias("__"); sqlOrderByString = collection.OrderBy; hasOrder = sqlOrderByString != null; sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect, factory.SQLFunctionRegistry) : null; sqlWhereString = collection.Where; hasWhere = sqlWhereString != null; sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry) : null; hasOrphanDelete = collection.OrphanDelete; batchSize = collection.BatchSize; isVersioned = collection.IsOptimisticLocked; keyType = collection.Key.Type; int keySpan = collection.Key.ColumnSpan; keyColumnNames = new string[keySpan]; string[] keyAliases = new string[keySpan]; int k = 0; foreach (Column col in collection.Key.ColumnCollection) { keyColumnNames[k] = col.GetQuotedName(dialect); keyAliases[k] = col.GetAlias(dialect); k++; } keyColumnAliases = alias.ToAliasStrings(keyAliases, dialect); //unquotedKeyColumnNames = StringHelper.Unquote( keyColumnAliases ); ISet distinctColumns = new HashedSet(); CheckColumnDuplication(distinctColumns, collection.Key.ColumnCollection); //isSet = collection.IsSet; //isSorted = collection.IsSorted; primitiveArray = collection.IsPrimitiveArray; array = collection.IsArray; subselectLoadable = collection.IsSubselectLoadable; IValue element = collection.Element; int elementSpan = element.ColumnSpan; Table table = collection.CollectionTable; fetchMode = element.FetchMode; elementType = element.Type; if (!collection.IsOneToMany) { CheckColumnDuplication(distinctColumns, element.ColumnCollection); } if (elementType.IsEntityType) { elementPersister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass); } else { elementPersister = null; } qualifiedTableName = table.GetQualifiedName(dialect, factory.DefaultSchema); elementColumnAliases = new string[elementSpan]; elementColumnNames = new string[elementSpan]; elementFormulaTemplates = new string[elementSpan]; elementFormulas = new string[elementSpan]; elementColumnIsSettable = new bool[elementSpan]; elementColumnIsInPrimaryKey = new bool[elementSpan]; int j = 0; foreach (ISelectable selectable in element.ColumnCollection) { elementColumnAliases[j] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula form = (Formula) selectable; elementFormulaTemplates[j] = form.GetTemplate(dialect, factory.SQLFunctionRegistry); elementFormulas[j] = form.FormulaString; } else { Column col = (Column) selectable; elementColumnNames[j] = col.GetQuotedName(dialect); elementColumnIsSettable[j] = true; elementColumnIsInPrimaryKey[j] = !col.IsNullable; } j++; } hasIndex = collection.IsIndexed; if (hasIndex) { IndexedCollection indexedCollection = (IndexedCollection) collection; indexType = indexedCollection.Index.Type; int indexSpan = indexedCollection.Index.ColumnSpan; indexColumnNames = new string[indexSpan]; string[] indexAliases = new string[indexSpan]; int i = 0; foreach (Column indexCol in indexedCollection.Index.ColumnCollection) { indexAliases[i] = indexCol.GetAlias(dialect); indexColumnNames[i] = indexCol.GetQuotedName(dialect); i++; } indexColumnAliases = alias.ToAliasStrings(indexAliases, dialect); CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnCollection); } else { indexType = null; indexColumnNames = null; indexColumnAliases = null; } hasIdentifier = collection.IsIdentified; if (hasIdentifier) { if (collection.IsOneToMany) { throw new MappingException("one-to-many collections with identifiers are not supported."); } IdentifierCollection idColl = (IdentifierCollection) collection; identifierType = idColl.Identifier.Type; Column col = null; foreach (Column column in idColl.Identifier.ColumnCollection) { col = column; break; } identifierColumnName = col.GetQuotedName(dialect); identifierColumnAlias = alias.ToAliasString(col.GetAlias(dialect), dialect); identifierGenerator = idColl.Identifier.CreateIdentifierGenerator(dialect); CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnCollection); } else { identifierType = null; identifierColumnName = null; identifierColumnAlias = null; identifierGenerator = null; } sqlInsertRowString = GenerateInsertRowString(); if (collection.CustomSQLInsert == null) { insertCallable = false; insertCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, sqlInsertRowString.ParameterTypes); insertCallable = collection.IsCustomInsertCallable; insertCheckStyle = collection.CustomSQLInsertCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable) : collection.CustomSQLInsertCheckStyle; } sqlUpdateRowString = GenerateUpdateRowString(); if (collection.CustomSQLUpdate == null) { updateCallable = false; updateCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes); updateCallable = collection.IsCustomUpdateCallable; updateCheckStyle = collection.CustomSQLUpdateCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable) : collection.CustomSQLUpdateCheckStyle; } sqlDeleteRowString = GenerateDeleteRowString(); if (collection.CustomSQLDelete == null) { deleteCallable = false; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes); deleteCallable = collection.IsCustomDeleteCallable; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } sqlDeleteString = GenerateDeleteString(); if (collection.CustomSQLDeleteAll == null) { deleteAllCallable = false; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteString = new SqlCommandInfo(collection.CustomSQLDeleteAll, sqlDeleteString.ParameterTypes); deleteAllCallable = collection.IsCustomDeleteAllCallable; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } isLazy = collection.IsLazy; isInverse = collection.IsInverse; if (collection.IsArray) { elementClass = ((Array) collection).ElementClass; } else { // for non-arrays, we don't need to know the element class elementClass = null; } if (elementType.IsComponentType) { elementPropertyMapping = new CompositeElementPropertyMapping( elementColumnNames, elementFormulaTemplates, (IAbstractComponentType) elementType, factory); } else if (!elementType.IsEntityType) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } else { IEntityPersister persister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass); // Not all classpersisters implement IPropertyMapping! if (persister is IPropertyMapping) { elementPropertyMapping = (IPropertyMapping) persister; } else { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } } // Handle any filters applied to this collection filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry); // Handle any filters applied to this collection for many-to-many manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry); manyToManyWhereString = StringHelper.IsNotEmpty(collection.ManyToManyWhere) ? "( " + collection.ManyToManyWhere + " )" : null; manyToManyWhereTemplate = manyToManyWhereString == null ? null : Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect, factory.SQLFunctionRegistry); // , factory.getSqlFunctionRegistry() ); manyToManyOrderByString = collection.ManyToManyOrdering; manyToManyOrderByTemplate = manyToManyOrderByString == null ? null : Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect, factory.SQLFunctionRegistry); // , factory.getSqlFunctionRegistry() ); InitCollectionPropertyMap(); }