protected virtual void CreateTemporaryTableIfNecessary(IQueryable persister, ISessionImplementor session) { // Don't really know all the codes required to adequately decipher returned ADO exceptions here. // simply allow the failure to be eaten and the subsequent insert-selects/deletes should fail IIsolatedWork work = new TmpIdTableCreationIsolatedWork(persister, log, session); if (ShouldIsolateTemporaryTableDDL()) { if (Factory.Settings.IsDataDefinitionInTransactionSupported) { Isolater.DoIsolatedWork(work, session); } else { Isolater.DoNonTransactedWork(work, session); } } else { using (var dummyCommand = session.ConnectionManager.CreateCommand()) { work.DoWork(dummyCommand.Connection, dummyCommand.Transaction); session.ConnectionManager.AfterStatement(); } } }
protected virtual void DropTemporaryTableIfNecessary(IQueryable persister, ISessionImplementor session) { if (Factory.Dialect.DropTemporaryTableAfterUse()) { IIsolatedWork work = new TmpIdTableDropIsolatedWork(persister, log, session); if (ShouldIsolateTemporaryTableDDL()) { session.ConnectionManager.Transaction.RegisterSynchronization(new AfterTransactionCompletes((success) => { if (Factory.Settings.IsDataDefinitionInTransactionSupported) { Isolater.DoIsolatedWork(work, session); } else { Isolater.DoNonTransactedWork(work, session); } })); } else { using (var dummyCommand = session.ConnectionManager.CreateCommand()) { work.DoWork(dummyCommand.Connection, dummyCommand.Transaction); session.ConnectionManager.AfterStatement(); } } } else { // at the very least cleanup the data :) IDbCommand ps = null; try { var commandText = new SqlString("delete from " + persister.TemporaryIdTableName); ps = session.Batcher.PrepareCommand(CommandType.Text, commandText, new SqlType[0]); session.Batcher.ExecuteNonQuery(ps); } catch (Exception t) { log.Warn("unable to cleanup temporary id table after use [" + t + "]"); } finally { if (ps != null) { try { session.Batcher.CloseCommand(ps, null); } catch (Exception) { // ignore } } } } }
public MultiTableUpdateExecutor(IStatement statement) : base(statement, log) { if (!Factory.Dialect.SupportsTemporaryTables) { throw new HibernateException("cannot perform multi-table updates using dialect not supporting temp tables"); } var updateStatement = (UpdateStatement)statement; FromElement fromElement = updateStatement.FromClause.GetFromElement(); string bulkTargetAlias = fromElement.TableAlias; persister = fromElement.Queryable; idInsertSelect = GenerateIdInsertSelect(persister, bulkTargetAlias, updateStatement.WhereClause); log.Debug("Generated ID-INSERT-SELECT SQL (multi-table update) : " + idInsertSelect); string[] tableNames = persister.ConstraintOrderedTableNameClosure; string[][] columnNames = persister.ConstraintOrderedTableKeyColumnClosure; string idSubselect = GenerateIdSubselect(persister); IList <AssignmentSpecification> assignmentSpecifications = Walker.AssignmentSpecifications; updates = new SqlString[tableNames.Length]; hqlParameters = new IParameterSpecification[tableNames.Length][]; for (int tableIndex = 0; tableIndex < tableNames.Length; tableIndex++) { bool affected = false; var parameterList = new List <IParameterSpecification>(); SqlUpdateBuilder update = new SqlUpdateBuilder(Factory.Dialect, Factory).SetTableName(tableNames[tableIndex]) .SetWhere( string.Format("({0}) IN ({1})", StringHelper.Join(", ", columnNames[tableIndex]), idSubselect)); if (Factory.Settings.IsCommentsEnabled) { update.SetComment("bulk update"); } foreach (var specification in assignmentSpecifications) { if (specification.AffectsTable(tableNames[tableIndex])) { affected = true; update.AppendAssignmentFragment(specification.SqlAssignmentFragment); if (specification.Parameters != null) { for (int paramIndex = 0; paramIndex < specification.Parameters.Length; paramIndex++) { parameterList.Add(specification.Parameters[paramIndex]); } } } } if (affected) { updates[tableIndex] = update.ToSqlString(); hqlParameters[tableIndex] = parameterList.ToArray(); } } }
public MultiTableUpdateExecutor(IStatement statement) : base(statement, log) { if (!Factory.Dialect.SupportsTemporaryTables) { throw new HibernateException("cannot perform multi-table updates using dialect not supporting temp tables"); } var updateStatement = (UpdateStatement) statement; FromElement fromElement = updateStatement.FromClause.GetFromElement(); string bulkTargetAlias = fromElement.TableAlias; persister = fromElement.Queryable; idInsertSelect = GenerateIdInsertSelect(persister, bulkTargetAlias, updateStatement.WhereClause); log.Debug("Generated ID-INSERT-SELECT SQL (multi-table update) : " + idInsertSelect); string[] tableNames = persister.ConstraintOrderedTableNameClosure; string[][] columnNames = persister.ConstraintOrderedTableKeyColumnClosure; string idSubselect = GenerateIdSubselect(persister); IList<AssignmentSpecification> assignmentSpecifications = Walker.AssignmentSpecifications; updates = new SqlString[tableNames.Length]; hqlParameters = new IParameterSpecification[tableNames.Length][]; for (int tableIndex = 0; tableIndex < tableNames.Length; tableIndex++) { bool affected = false; var parameterList = new List<IParameterSpecification>(); SqlUpdateBuilder update = new SqlUpdateBuilder(Factory.Dialect, Factory).SetTableName(tableNames[tableIndex]) .SetWhere( string.Format("({0}) IN ({1})", StringHelper.Join(", ", columnNames[tableIndex]), idSubselect)); if (Factory.Settings.IsCommentsEnabled) { update.SetComment("bulk update"); } foreach (var specification in assignmentSpecifications) { if (specification.AffectsTable(tableNames[tableIndex])) { affected = true; update.AppendAssignmentFragment(specification.SqlAssignmentFragment); if (specification.Parameters != null) { for (int paramIndex = 0; paramIndex < specification.Parameters.Length; paramIndex++) { parameterList.Add(specification.Parameters[paramIndex]); } } } } if (affected) { updates[tableIndex] = update.ToSqlString(); hqlParameters[tableIndex] = parameterList.ToArray(); } } }
protected SqlString GenerateIdInsertSelect(IQueryable persister, string tableAlias, IASTNode whereClause) { var select = new SqlSelectBuilder(Factory); SelectFragment selectFragment = new SelectFragment(Factory.Dialect) .AddColumns(tableAlias, persister.IdentifierColumnNames, persister.IdentifierColumnNames); select.SetSelectClause(selectFragment.ToFragmentString().Substring(2)); string rootTableName = persister.TableName; SqlString fromJoinFragment = persister.FromJoinFragment(tableAlias, true, false); select.SetFromClause(rootTableName + " " + tableAlias + fromJoinFragment); var whereJoinFragment = GetWhereJoinFragment(persister, tableAlias); SqlString userWhereClause = SqlString.Empty; if (whereClause.ChildCount != 0) { // If a where clause was specified in the update/delete query, use it to limit the // returned ids here... try { var nodes = new CommonTreeNodeStream(whereClause); var gen = new SqlGenerator(Factory, nodes); gen.whereClause(); userWhereClause = gen.GetSQL().Substring(7); } catch (RecognitionException e) { throw new HibernateException("Unable to generate id select for DML operation", e); } if (whereJoinFragment.Length > 0) { whereJoinFragment.Append(" and "); } } select.SetWhereClause(whereJoinFragment + userWhereClause); var insert = new InsertSelect(); if (Factory.Settings.IsCommentsEnabled) { insert.SetComment("insert-select for " + persister.EntityName + " ids"); } insert.SetTableName(persister.TemporaryIdTableName); insert.SetSelect(select); return(insert.ToSqlString()); }
/// <summary> /// Does the given persister define a physical discriminator column /// for the purpose of inheritance discrimination? /// </summary> /// <param name="persister">The persister to be checked.</param> /// <returns>True if the persister does define an actual discriminator column.</returns> public bool HasPhysicalDiscriminatorColumn(IQueryable persister) { if (persister.DiscriminatorType != null) { string discrimColumnName = persister.DiscriminatorColumnName; // Needed the "clazz_" check to work around union-subclasses // TODO : is there a way to tell whether a persister is truly discrim-column based inheritence? if (discrimColumnName != null && "clazz_" != discrimColumnName) { return(true); } } return(false); }
/// <summary> /// Get the a typed value for the given property value. /// </summary> public TypedValue GetTypedValue(ICriteria subcriteria, string propertyName, object value) { // Detect discriminator values... var entityClass = value as System.Type; if (entityClass != null) { NHibernate_Persister_Entity.IQueryable q = helper.FindQueryableUsingImports(entityClass.FullName); if (q != null && q.DiscriminatorValue != null) { // NH Different implementation : We are using strongly typed parameter for SQL query (see DiscriminatorValue comment) return(new TypedValue(q.DiscriminatorType, q.DiscriminatorValue, EntityMode.Poco)); } } // Otherwise, this is an ordinary value. return(new TypedValue(GetTypeUsingProjection(subcriteria, propertyName), value, EntityMode.Poco)); }
public void HandlePropertyBeingDereferenced(IType propertySource, string propertyName) { if (QueryableCollection != null && CollectionProperties.IsCollectionProperty(propertyName)) { // propertyName refers to something like collection.size... return; } if (propertySource.IsComponentType) { // property name is a sub-path of a component... return; } IQueryable persister = Queryable; if (persister != null) { try { Declarer propertyDeclarer = persister.GetSubclassPropertyDeclarer(propertyName); if (Log.IsInfoEnabled()) { Log.Info("handling property dereference [{0} ({1}) -> {2} ({3})]", persister.EntityName, ClassAlias, propertyName, propertyDeclarer); } if (propertyDeclarer == Declarer.SubClass) { _dereferencedBySubclassProperty = true; _includeSubclasses = true; } else if (propertyDeclarer == Declarer.SuperClass) { _dereferencedBySuperclassProperty = true; } } catch (QueryException ex) { // ignore it; the incoming property could not be found so we // cannot be sure what to do here. At the very least, the // safest is to simply not apply any dereference toggling... Log.Debug(ex, "Unable to find property {0}, no dereference will be handled for it.", propertyName); } } }
private IQueryable DetermineAppropriateOwnerPersister(NonScalarReturn ownerDescriptor) { string entityName = null; RootReturn odrr = ownerDescriptor as RootReturn; if (odrr != null) { entityName = odrr.EntityName; } else if (ownerDescriptor is CollectionReturn) { CollectionReturn collRtn = (CollectionReturn)ownerDescriptor; string role = collRtn.OwnerEntityName + "." + collRtn.OwnerProperty; ICollectionPersister persister = Factory.GetCollectionPersister(role); EntityType ownerType = (EntityType)persister.ElementType; entityName = ownerType.GetAssociatedEntityName(Factory); } else if (ownerDescriptor is FetchReturn) { FetchReturn fetchRtn = (FetchReturn)ownerDescriptor; IQueryable persister = DetermineAppropriateOwnerPersister(fetchRtn.Owner); IType ownerType = persister.GetPropertyType(fetchRtn.OwnerProperty); if (ownerType.IsEntityType) { entityName = ((EntityType)ownerType).GetAssociatedEntityName(Factory); } else if (ownerType.IsCollectionType) { IType ownerCollectionElementType = ((CollectionType)ownerType).GetElementType(Factory); if (ownerCollectionElementType.IsEntityType) { entityName = ((EntityType)ownerCollectionElementType).GetAssociatedEntityName(Factory); } } } if (entityName == null) { throw new HibernateException("Could not determine fetch owner : " + ownerDescriptor); } return((IQueryable)Factory.GetEntityPersister(entityName)); }
private static IStatementExecutor BuildAppropriateStatementExecutor(IStatement statement) { HqlSqlWalker walker = statement.Walker; if (walker.StatementType == HqlSqlWalker.DELETE) { FromElement fromElement = walker.GetFinalFromClause().GetFromElement(); IQueryable persister = fromElement.Queryable; if (persister.IsMultiTable) { return(new MultiTableDeleteExecutor(statement)); } else { return(new BasicExecutor(statement, persister)); } } else if (walker.StatementType == HqlSqlWalker.UPDATE) { FromElement fromElement = walker.GetFinalFromClause().GetFromElement(); IQueryable persister = fromElement.Queryable; if (persister.IsMultiTable) { // even here, if only properties mapped to the "base table" are referenced // in the set and where clauses, this could be handled by the BasicDelegate. // TODO : decide if it is better performance-wise to perform that check, or to simply use the MultiTableUpdateDelegate return(new MultiTableUpdateExecutor(statement)); } else { return(new BasicExecutor(statement, persister)); } } else if (walker.StatementType == HqlSqlWalker.INSERT) { return(new BasicExecutor(statement, ((InsertStatement)statement).IntoClause.Queryable)); } else { throw new QueryException("Unexpected statement type"); } }
public CriteriaQueryTranslator(ISessionFactoryImplementor factory, CriteriaImpl criteria, string rootEntityName, string rootSQLAlias) { rootCriteria = criteria; sessionFactory = factory; rootPersister = GetQueryablePersister(rootEntityName); this.rootSQLAlias = rootSQLAlias; helper = new SessionFactoryHelper(factory); collectedParameterSpecifications = new List <IParameterSpecification>(); namedParameters = new List <NamedParameter>(); CreateAliasCriteriaMap(); CreateAssociationPathCriteriaMap(); CreateEntityJoinMap(); CreateCriteriaEntityNameMap(); CreateCriteriaCollectionPersisters(); CreateCriteriaSQLAliasMap(); CreateSubQuerySpaces(); }
private static bool IsMatchingImplementor(string entityOrClassName, System.Type entityClass, IQueryable implementor) { var implementorClass = implementor.GetMappedClass(EntityMode.Poco); if (implementorClass == null) { return(false); } if (entityClass == implementorClass) { // It is possible to have multiple mappings for the same entity class, but with different entity names. // When querying for a specific entity name, we should only return entities for the requested entity name // and not return entities for any other entity names that may map to the same entity class. bool isEntityName = !entityOrClassName.Equals(entityClass.FullName); return(!isEntityName || entityOrClassName.Equals(implementor.EntityName)); } return(entityClass.IsAssignableFrom(implementorClass)); }
public CustomLoader(ICustomQuery customQuery, ISessionFactoryImplementor factory) : base(factory) { sql = customQuery.SQL; querySpaces.UnionWith(customQuery.QuerySpaces); parametersSpecifications = customQuery.CollectedParametersSpecifications.ToList(); List <IQueryable> entitypersisters = new List <IQueryable>(); List <int> entityowners = new List <int>(); List <IEntityAliases> entityaliases = new List <IEntityAliases>(); List <IQueryableCollection> collectionpersisters = new List <IQueryableCollection>(); List <int> collectionowners = new List <int>(); List <ICollectionAliases> collectionaliases = new List <ICollectionAliases>(); List <LockMode> lockmodes = new List <LockMode>(); List <IResultColumnProcessor> resultColumnProcessors = new List <IResultColumnProcessor>(); List <IReturn> nonScalarReturnList = new List <IReturn>(); List <IType> resulttypes = new List <IType>(); List <string> specifiedAliases = new List <string>(); List <bool> includeInResultRowList = new List <bool>(); int returnableCounter = 0; bool hasScalars = false; foreach (IReturn rtn in customQuery.CustomQueryReturns) { if (rtn is ScalarReturn) { ScalarReturn scalarRtn = (ScalarReturn)rtn; resulttypes.Add(scalarRtn.Type); specifiedAliases.Add(scalarRtn.ColumnAlias); resultColumnProcessors.Add(new ScalarResultColumnProcessor(scalarRtn.ColumnAlias, scalarRtn.Type)); includeInResultRowList.Add(true); hasScalars = true; } else if (rtn is RootReturn) { RootReturn rootRtn = (RootReturn)rtn; IQueryable persister = (IQueryable)factory.GetEntityPersister(rootRtn.EntityName); entitypersisters.Add(persister); lockmodes.Add(rootRtn.LockMode); resultColumnProcessors.Add(new NonScalarResultColumnProcessor(returnableCounter++)); nonScalarReturnList.Add(rtn); entityowners.Add(-1); resulttypes.Add(persister.Type); specifiedAliases.Add(rootRtn.Alias); entityaliases.Add(rootRtn.EntityAliases); querySpaces.UnionWith(persister.QuerySpaces); includeInResultRowList.Add(true); } else if (rtn is CollectionReturn) { CollectionReturn collRtn = (CollectionReturn)rtn; string role = collRtn.OwnerEntityName + "." + collRtn.OwnerProperty; IQueryableCollection persister = (IQueryableCollection)factory.GetCollectionPersister(role); collectionpersisters.Add(persister); lockmodes.Add(collRtn.LockMode); resultColumnProcessors.Add(new NonScalarResultColumnProcessor(returnableCounter++)); nonScalarReturnList.Add(rtn); collectionowners.Add(-1); resulttypes.Add(persister.Type); specifiedAliases.Add(collRtn.Alias); collectionaliases.Add(collRtn.CollectionAliases); // determine if the collection elements are entities... IType elementType = persister.ElementType; if (elementType.IsEntityType) { IQueryable elementPersister = (IQueryable)((EntityType)elementType).GetAssociatedJoinable(factory); entitypersisters.Add(elementPersister); entityowners.Add(-1); entityaliases.Add(collRtn.ElementEntityAliases); querySpaces.UnionWith(elementPersister.QuerySpaces); } includeInResultRowList.Add(true); } else if (rtn is EntityFetchReturn) { EntityFetchReturn fetchRtn = (EntityFetchReturn)rtn; NonScalarReturn ownerDescriptor = fetchRtn.Owner; int ownerIndex = nonScalarReturnList.IndexOf(ownerDescriptor); entityowners.Add(ownerIndex); lockmodes.Add(fetchRtn.LockMode); IQueryable ownerPersister = DetermineAppropriateOwnerPersister(ownerDescriptor); EntityType fetchedType = (EntityType)ownerPersister.GetPropertyType(fetchRtn.OwnerProperty); string entityName = fetchedType.GetAssociatedEntityName(Factory); IQueryable persister = (IQueryable)factory.GetEntityPersister(entityName); entitypersisters.Add(persister); nonScalarReturnList.Add(rtn); specifiedAliases.Add(fetchRtn.Alias); entityaliases.Add(fetchRtn.EntityAliases); querySpaces.UnionWith(persister.QuerySpaces); includeInResultRowList.Add(false); } else if (rtn is CollectionFetchReturn) { CollectionFetchReturn fetchRtn = (CollectionFetchReturn)rtn; NonScalarReturn ownerDescriptor = fetchRtn.Owner; int ownerIndex = nonScalarReturnList.IndexOf(ownerDescriptor); collectionowners.Add(ownerIndex); lockmodes.Add(fetchRtn.LockMode); IQueryable ownerPersister = DetermineAppropriateOwnerPersister(ownerDescriptor); string role = ownerPersister.EntityName + '.' + fetchRtn.OwnerProperty; IQueryableCollection persister = (IQueryableCollection)factory.GetCollectionPersister(role); collectionpersisters.Add(persister); nonScalarReturnList.Add(rtn); specifiedAliases.Add(fetchRtn.Alias); collectionaliases.Add(fetchRtn.CollectionAliases); // determine if the collection elements are entities... IType elementType = persister.ElementType; if (elementType.IsEntityType) { IQueryable elementPersister = (IQueryable)((EntityType)elementType).GetAssociatedJoinable(factory); entitypersisters.Add(elementPersister); entityowners.Add(ownerIndex); entityaliases.Add(fetchRtn.ElementEntityAliases); querySpaces.UnionWith(elementPersister.QuerySpaces); } includeInResultRowList.Add(false); } else { throw new HibernateException("unexpected custom query return type : " + rtn.GetType().FullName); } } entityPersisters = entitypersisters.ToArray(); entityOwners = entityowners.ToArray(); entityAliases = entityaliases.ToArray(); collectionPersisters = collectionpersisters.ToArray(); collectionOwners = collectionowners.ToArray(); collectionAliases = collectionaliases.ToArray(); lockModes = lockmodes.ToArray(); resultTypes = resulttypes.ToArray(); transformerAliases = specifiedAliases.ToArray(); rowProcessor = new ResultRowProcessor(hasScalars, resultColumnProcessors.ToArray()); includeInResultRow = includeInResultRowList.ToArray(); }
internal void AddFromClass(string name, IQueryable classPersister) { JoinSequence joinSequence = new JoinSequence(Factory) .SetRoot(classPersister, name); AddFrom(name, classPersister.EntityName, joinSequence); }
private static bool IsMatchingImplementor(string entityOrClassName, System.Type entityClass, IQueryable implementor) { var implementorClass = implementor.GetMappedClass(EntityMode.Poco); if (implementorClass == null) { return false; } if (entityClass.Equals(implementorClass)) { // It is possible to have multiple mappings for the same entity class, but with different entity names. // When querying for a specific entity name, we should only return entities for the requested entity name // and not return entities for any other entity names that may map to the same entity class. bool isEntityName = !entityOrClassName.Equals(entityClass.FullName); return !isEntityName || entityOrClassName.Equals(implementor.EntityName); } return entityClass.IsAssignableFrom(implementorClass); }
public TmpIdTableDropIsolatedWork(IQueryable persister, IInternalLogger log, ISessionImplementor session) { this.persister = persister; this.log = log; this.session = session; }
protected string GenerateIdSubselect(IQueryable persister) { return("select " + StringHelper.Join(", ", persister.IdentifierColumnNames) + " from " + persister.TemporaryIdTableName); }