From: Paul H. <pha...@us...> - 2005-03-14 18:53:27
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6809/nhibernate/src/NHibernate/Persister Modified Files: AbstractEntityPersister.cs AbstractPropertyMapping.cs EntityPersister.cs IClassPersister.cs ILoadable.cs IOuterJoinLoadable.cs IQueryable.cs ISqlLoadable.cs NormalizedEntityPersister.cs PersisterFactory.cs Log Message: Refactored as per 2.1 Index: AbstractPropertyMapping.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/AbstractPropertyMapping.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** AbstractPropertyMapping.cs 1 Mar 2005 16:24:50 -0000 1.1 --- AbstractPropertyMapping.cs 14 Mar 2005 18:53:15 -0000 1.2 *************** *** 24,30 **** public abstract class AbstractPropertyMapping : IPropertyMapping { ! private Hashtable typesByPropertyPath = new Hashtable(); ! private Hashtable columnsByPropertyPath = new Hashtable(); ! private Hashtable formulaTemplatesByPropertyPath = new Hashtable(); /// <summary> --- 24,30 ---- public abstract class AbstractPropertyMapping : IPropertyMapping { ! private readonly Hashtable typesByPropertyPath = new Hashtable(); ! private readonly Hashtable columnsByPropertyPath = new Hashtable(); ! private readonly Hashtable formulaTemplatesByPropertyPath = new Hashtable(); /// <summary> *************** *** 96,99 **** --- 96,100 ---- { // HACK: Test for use so we don't attempt to duplicate - differs from the java code + /* if ( !typesByPropertyPath.ContainsKey( path ) ) { *************** *** 102,105 **** --- 103,110 ---- HandlePath( path, type ); } + */ + typesByPropertyPath[ path ] = type; + columnsByPropertyPath[ path ] = columns; + HandlePath( path, type ); } *************** *** 113,116 **** --- 118,122 ---- { // HACK: Test for use so we don't attempt to duplicate - differs from the java code + /* if ( !typesByPropertyPath.ContainsKey( path ) ) { *************** *** 119,122 **** --- 125,132 ---- HandlePath( path, type ); } + */ + typesByPropertyPath[ path ] = type ; + formulaTemplatesByPropertyPath[ path ] = template ; + HandlePath( path, type ); } Index: NormalizedEntityPersister.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/NormalizedEntityPersister.cs,v retrieving revision 1.40 retrieving revision 1.41 diff -C2 -d -r1.40 -r1.41 *** NormalizedEntityPersister.cs 1 Mar 2005 16:24:50 -0000 1.40 --- NormalizedEntityPersister.cs 14 Mar 2005 18:53:15 -0000 1.41 *************** *** 31,42 **** // for the base class there is only 1 table private readonly string[ ] tableNames; - private readonly string[ ] naturalOrderTableNames; // two dimensional array that is indexed as tableKeyColumns[tableIndex][columnIndex] private readonly string[ ][ ] tableKeyColumns; - private readonly string[ ][ ] naturalOrderTableKeyColumns; - private readonly bool hasFormulaProperties; --- 31,39 ---- *************** *** 69,72 **** --- 66,70 ---- private readonly bool[ ] isClassOrSuperclassTable; + // SQL strings private SqlString[ ] sqlDeleteStrings; private SqlString[ ] sqlInsertStrings; *************** *** 85,93 **** // the array is indexed as propertyTables[propertyIndex] = tableIndex private readonly int[ ] propertyTables; - private readonly int[ ] naturalOrderPropertyTables; - - // TODO: understand this variable and its context/contents - //private readonly bool[] propertyHasColumns; private bool[ ] propertyHasColumns; --- 83,87 ---- *************** *** 99,103 **** // selecting a column. It is indexed the same as propertyColumnNames private readonly string[ ][ ] propertyColumnNameAliases; - private readonly string[ ] propertyFormulaTemplates; --- 93,96 ---- *************** *** 115,121 **** // the closure of all columns used by the entire hierarchy including // subclasses and superclasses of this class private readonly string[ ] subclassColumnClosure; private readonly string[ ] subclassColumnClosureAliases; ! private readonly int[ ] subclassColumnTableNumberClosure; // subclass discrimination works by assigning particular values to certain --- 108,117 ---- // the closure of all columns used by the entire hierarchy including // subclasses and superclasses of this class + private readonly int[ ] subclassColumnTableNumberClosure; private readonly string[ ] subclassColumnClosure; private readonly string[ ] subclassColumnClosureAliases; ! private readonly int[ ] subclassFormulaTableNumberClosure; ! private readonly string[ ] subclassFormulaTemplateClosure; ! private readonly string[ ] subclassFormulaAliasClosure; // subclass discrimination works by assigning particular values to certain *************** *** 124,137 **** // key = DiscrimatorValue, value = Subclass Type private readonly Hashtable subclassesByDiscriminatorValue = new Hashtable(); - - // the value the discrimator column will contain to indicate the type of object - // the row contains. - // the array is indexed as discriminatorValues[subclassIndex]. The subclassIndex comes - // from the field subclassClosure private readonly string[ ] discriminatorValues; - private readonly string[ ] notNullColumns; - - // TODO: figure out how this is used private readonly int[ ] tableNumbers; --- 120,125 ---- *************** *** 145,151 **** protected IUniqueEntityLoader loader; - // private static readonly string[ ] StringArray = {}; - // private static readonly IType[ ] TypeArray = {}; - private static readonly ILog log = LogManager.GetLogger( typeof( NormalizedEntityPersister ) ); --- 133,136 ---- *************** *** 227,240 **** this.naturalOrderTableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); - // convert the local ArrayList variables into arrays for the fields in the class - this.tableNames = ( string[ ] ) tables.ToArray( typeof( string ) ); - this.tableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); - // the description of these variables is the same as before ArrayList subtables = new ArrayList(); keyColumns = new ArrayList(); - subtables.Add( this.qualifiedTableName ); ! keyColumns.Add( IdentifierColumnNames ); foreach( Table tab in model.SubclassTableClosureCollection ) { --- 212,220 ---- this.naturalOrderTableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); // the description of these variables is the same as before ArrayList subtables = new ArrayList(); keyColumns = new ArrayList(); subtables.Add( this.qualifiedTableName ); ! keyColumns.Add( base.IdentifierColumnNames ); foreach( Table tab in model.SubclassTableClosureCollection ) { *************** *** 256,260 **** this.subclassTableNameClosure = ( string[ ] ) subtables.ToArray( typeof( string ) ); this.subclassTableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); - this.isClassOrSuperclassTable = new bool[this.subclassTableNameClosure.Length]; for( int j = 0; j < subclassTableNameClosure.Length; j++ ) --- 236,239 ---- *************** *** 279,324 **** this.propertyFormulaTemplates = new string[ HydrateSpan ]; ! Hashtable thisClassProperties = new Hashtable(); ! // just a dummy object for the value so I can treat Hashtable like a Set ! object thisClassPropertiesObject = new object(); ! int propertyIndex = 0; bool foundFormula = false; foreach( Mapping.Property prop in model.PropertyClosureCollection ) { ! thisClassProperties.Add( prop, thisClassPropertiesObject ); Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); ! ! this.propertyTables[ propertyIndex ] = GetTableId( tabname, this.tableNames ); ! this.naturalOrderPropertyTables[ propertyIndex ] = GetTableId( tabname, this.naturalOrderTableNames ); ! this.propertyColumnSpans[ propertyIndex ] = prop.ColumnSpan; if ( prop.IsFormula ) { ! this.propertyColumnNames[ propertyIndex ] = new string[] { prop.Formula.Alias }; ! this.propertyColumnSpans[ propertyIndex ] = 1; ! this.propertyColumnNameAliases[ propertyIndex ] = new string[] { prop.Formula.GetTemplate( Dialect ) }; foundFormula = true; } else { ! string[ ] propCols = new string[propertyColumnSpans[ propertyIndex ]]; ! string[ ] propAliases = new string[propertyColumnSpans[ propertyIndex ]]; ! int columnIndex = 0; foreach( Column col in prop.ColumnCollection ) { string colname = col.GetQuotedName( Dialect ); ! propCols[ columnIndex ] = colname; ! propAliases[ columnIndex ] = col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ); ! columnIndex++; } ! ! this.propertyColumnNames[ propertyIndex ] = propCols; ! this.propertyColumnNameAliases[ propertyIndex ] = propAliases; } ! propertyIndex++; } --- 258,300 ---- this.propertyFormulaTemplates = new string[ HydrateSpan ]; ! HashedSet thisClassProperties = new HashedSet(); ! int i = 0; bool foundFormula = false; foreach( Mapping.Property prop in model.PropertyClosureCollection ) { ! thisClassProperties.Add( prop ); Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); ! this.propertyTables[ i ] = GetTableId( tabname, this.tableNames ); ! this.naturalOrderPropertyTables[ i ] = GetTableId( tabname, this.naturalOrderTableNames ); if ( prop.IsFormula ) { ! this.propertyColumnNames[ i ] = new string[] { prop.Formula.Alias }; ! this.propertyColumnSpans[ i ] = 1; ! this.propertyFormulaTemplates[ i ] = prop.Formula.GetTemplate( Dialect ); foundFormula = true; } else { ! this.propertyColumnSpans[ i ] = prop.ColumnSpan; ! string[ ] propCols = new string[propertyColumnSpans[ i ]]; ! string[ ] propAliases = new string[propertyColumnSpans[ i ]]; ! ! int j = 0; foreach( Column col in prop.ColumnCollection ) { string colname = col.GetQuotedName( Dialect ); ! propCols[ j ] = colname; ! propAliases[ j ] = col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ); ! j++; } ! this.propertyColumnNames[ i ] = propCols; ! this.propertyColumnNameAliases[ i ] = propAliases; } ! i++; } *************** *** 339,348 **** ArrayList columns = new ArrayList(); //this.subclassColumnClosure ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure ArrayList coltables = new ArrayList(); //this.subclassColumnTableNumberClosure ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch - ArrayList aliases = new ArrayList(); //this.subclassColumnClosureAlias ArrayList propTables = new ArrayList(); // this.subclassPropertyTableNameClosure ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass --- 315,327 ---- ArrayList columns = new ArrayList(); //this.subclassColumnClosure + ArrayList aliases = new ArrayList(); + ArrayList formulaAliases = new ArrayList(); + ArrayList formulaTemplates = new ArrayList(); ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure ArrayList coltables = new ArrayList(); //this.subclassColumnTableNumberClosure + ArrayList formtables = new ArrayList(); ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch ArrayList propTables = new ArrayList(); // this.subclassPropertyTableNameClosure ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass *************** *** 354,371 **** Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); - string[ ] cols = new string[prop.ColumnSpan]; - types.Add( prop.Type ); int tabnum = GetTableId( tabname, subclassTableNameClosure ); propTables.Add( tabnum ); ! int l = 0; ! foreach( Column col in prop.ColumnCollection ) { ! columns.Add( col.GetQuotedName( Dialect ) ); ! coltables.Add( tabnum ); ! cols[ l++ ] = col.GetQuotedName( Dialect ); ! aliases.Add( col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ) ); } ! propColumns.Add( cols ); joinedFetchesList.Add( prop.Value.OuterJoinFetchSetting ); } --- 333,361 ---- Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); int tabnum = GetTableId( tabname, subclassTableNameClosure ); propTables.Add( tabnum ); + types.Add( prop.Type ); ! if ( prop.IsFormula ) { ! formulaTemplates.Add( prop.Formula.GetTemplate( Dialect ) ); ! propColumns.Add( new string [] { } ) ; ! formulaAliases.Add( prop.Formula.Alias ); ! formtables.Add( tabnum ); } ! else ! { ! string[ ] cols = new string[prop.ColumnSpan]; ! int l = 0; ! foreach( Column col in prop.ColumnCollection ) ! { ! columns.Add( col.GetQuotedName( Dialect ) ); ! coltables.Add( tabnum ); ! cols[ l++ ] = col.GetQuotedName( Dialect ); ! aliases.Add( col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ) ); ! } ! propColumns.Add( cols ); ! } ! joinedFetchesList.Add( prop.Value.OuterJoinFetchSetting ); } *************** *** 377,384 **** subclassPropertyNameClosure = ( string[ ] ) names.ToArray( typeof( string ) ); subclassPropertyTableNumberClosure = ( int[ ] ) propTables.ToArray( typeof( int ) ); ! subclassPropertyColumnNameClosure = ( string[ ][ ] ) propColumns.ToArray( typeof( string[ ] ) ); ! subclassPropertyEnableJoinedFetch = new OuterJoinFetchStrategy[joinedFetchesList.Count]; int n = 0; foreach( OuterJoinFetchStrategy ojlType in joinedFetchesList ) --- 367,376 ---- subclassPropertyNameClosure = ( string[ ] ) names.ToArray( typeof( string ) ); subclassPropertyTableNumberClosure = ( int[ ] ) propTables.ToArray( typeof( int ) ); ! subclassFormulaAliasClosure = ( string[ ] ) formulaAliases.ToArray( typeof( string ) ); ! subclassFormulaTemplateClosure = ( string[ ] ) formulaTemplates.ToArray( typeof( string ) ); ! subclassFormulaTableNumberClosure = ( int[ ] ) formtables.ToArray( typeof( int ) ); subclassPropertyColumnNameClosure = ( string[ ][ ] ) propColumns.ToArray( typeof( string[ ] ) ); ! subclassPropertyEnableJoinedFetch = new OuterJoinFetchStrategy[ joinedFetchesList.Count ]; int n = 0; foreach( OuterJoinFetchStrategy ojlType in joinedFetchesList ) *************** *** 387,391 **** } ! propertyDefinedOnSubclass = new bool[definedBySubclass.Count]; n = 0; foreach( bool pdos in definedBySubclass ) --- 379,383 ---- } ! propertyDefinedOnSubclass = new bool[ definedBySubclass.Count ]; n = 0; foreach( bool pdos in definedBySubclass ) *************** *** 394,398 **** } ! // moved the sql generation to PostIntantiate System.Type mappedClass = model.MappedClass; --- 386,390 ---- } ! // ****** Moved the sql generation to PostIntantiate ***** System.Type mappedClass = model.MappedClass; *************** *** 415,427 **** this.tableNumbers = new int[subclassSpan]; ! this.tableNumbers[ subclassSpan - 1 ] = GetTableId( model.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), this.subclassTableNameClosure ); this.notNullColumns = new string[subclassSpan]; foreach( Column col in model.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ subclassSpan - 1 ] = col.GetQuotedName( Dialect ); //only once } } else --- 407,423 ---- this.tableNumbers = new int[subclassSpan]; ! int id = GetTableId( model.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), this.subclassTableNameClosure ); + this.tableNumbers[ subclassSpan - 1 ] = id; this.notNullColumns = new string[subclassSpan]; + this.notNullColumns[ subclassSpan - 1 ] = subclassTableKeyColumns[ id ][ 0 ]; + /* foreach( Column col in model.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ subclassSpan - 1 ] = col.GetQuotedName( Dialect ); //only once } + */ } else *************** *** 443,454 **** subclassesByDiscriminatorValue.Add( disc, sc.MappedClass ); discriminatorValues[ p ] = disc.ToString(); ! tableNumbers[ p ] = GetTableId( sc.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), ! subclassTableNameClosure ! ); foreach( Column col in sc.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ p ] = col.GetQuotedName( Dialect ); //only once; } } } --- 439,453 ---- subclassesByDiscriminatorValue.Add( disc, sc.MappedClass ); discriminatorValues[ p ] = disc.ToString(); ! int id = GetTableId( sc.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), ! this.subclassTableNameClosure ); ! tableNumbers[ p ] = id; ! notNullColumns[ p ] = subclassTableKeyColumns[ id ][ 0 ]; ! /* foreach( Column col in sc.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ p ] = col.GetQuotedName( Dialect ); //only once; } + */ } } *************** *** 460,465 **** } ! // moved the propertyHasColumns into PostInstantiate } --- 459,468 ---- } ! // moved the propertyHasColumns into PostInstantiate as it needs the SQL strings + // needs identifier info so moved to PostInstatiate + //InitLockers( ); + + InitSubclassPropertyAliasesMap( model ); } *************** *** 476,479 **** --- 479,484 ---- CreateUniqueKeyLoaders( factory ); + InitLockers( ); + // initialize the Statements - these are in the PostInstantiate method because we need // to have every other IClassPersister loaded so we can resolve the IType for the *************** *** 493,500 **** sqlConcreteSelectString = GenerateConcreteSelectString(); ! InitLockers(); ! ! //TODO: find out why this was in the constructor in the spot it was... ! propertyHasColumns = new Boolean[sqlUpdateStrings.Length]; for( int m = 0; m < sqlUpdateStrings.Length; m++ ) { --- 498,503 ---- sqlConcreteSelectString = GenerateConcreteSelectString(); ! // This is used to determine updates for objects that came in via update() ! propertyHasColumns = new bool[sqlUpdateStrings.Length]; for( int m = 0; m < sqlUpdateStrings.Length; m++ ) { *************** *** 813,827 **** protected virtual SqlString[ ] GenerateUpdateStrings( bool[ ] includeProperty ) { ! SqlString[ ] updateStrings = new SqlString[naturalOrderTableNames.Length]; for( int j = 0; j < naturalOrderTableNames.Length; j++ ) { ! SqlUpdateBuilder updateBuilder = new SqlUpdateBuilder( factory ); ! updateBuilder.SetTableName( naturalOrderTableNames[ j ] ); //TODO: figure out what the hasColumns variable comes into play for?? bool hasColumns = false; - for( int i = 0; i < propertyColumnNames.Length; i++ ) { --- 816,834 ---- protected virtual SqlString[ ] GenerateUpdateStrings( bool[ ] includeProperty ) { ! SqlString[ ] results = new SqlString[naturalOrderTableNames.Length]; for( int j = 0; j < naturalOrderTableNames.Length; j++ ) { ! SqlUpdateBuilder updateBuilder = new SqlUpdateBuilder( factory ) ! .SetTableName( naturalOrderTableNames[ j ] ) ! .SetIdentityColumn( naturalOrderTableKeyColumns[ j ], IdentifierType ); ! if( j == 0 && IsVersioned ) ! { ! updateBuilder.SetVersionColumn( new string[ ] {VersionColumnName}, VersionType ); ! } //TODO: figure out what the hasColumns variable comes into play for?? bool hasColumns = false; for( int i = 0; i < propertyColumnNames.Length; i++ ) { *************** *** 832,849 **** } } ! ! updateBuilder.SetIdentityColumn( naturalOrderTableKeyColumns[ j ], IdentifierType ); ! ! if( j == 0 && IsVersioned ) ! { ! updateBuilder.SetVersionColumn( new string[ ] {VersionColumnName}, VersionType ); ! } ! ! updateStrings[ j ] = hasColumns ? ! updateBuilder.ToSqlString() : ! null; } ! return updateStrings; } --- 839,846 ---- } } ! results[ j ] = hasColumns ? updateBuilder.ToSqlString() : null; } ! return results; } *************** *** 1020,1082 **** /// <summary> - /// Do a version check - /// </summary> - /// <param name="id"></param> - /// <param name="version"></param> - /// <param name="obj"></param> - /// <param name="lockMode"></param> - /// <param name="session"></param> - public override void Lock( object id, object version, object obj, LockMode lockMode, ISessionImplementor session ) - { - if( lockMode != LockMode.None ) - { - if( log.IsDebugEnabled ) - { - log.Debug( "Locking entity: " + ClassName + '#' + id ); - if( IsVersioned ) - { - log.Debug( "Version: " + version ); - } - } - - IDbCommand st = session.Batcher.PrepareCommand( GetLockString( lockMode ) ); - IDataReader rs = null; - - try - { - IdentifierType.NullSafeSet( st, id, 0, session ); - if( IsVersioned ) - { - VersionType.NullSafeSet( st, version, IdentifierColumnNames.Length, session ); - } - - // IDataReader rs = st.ExecuteReader(); - rs = session.Batcher.ExecuteReader( st ); - // try - // { - if( !rs.Read() ) - { - throw new StaleObjectStateException( MappedClass, id ); - } - // } - // finally - // { - // rs.Close(); - // } - } - //TODO: change this to catch a Sql Exception and log it - catch( Exception e ) - { - log.Error( e.Message, e ); - throw; - } - finally - { - session.Batcher.CloseCommand( st, rs ); - } - } - } - - /// <summary> /// /// </summary> --- 1017,1020 ---- *************** *** 1336,1357 **** /// <summary> ! /// Update an object. /// </summary> - /// <param name="id"></param> - /// <param name="fields"></param> /// <param name="dirtyFields"></param> ! /// <param name="oldVersion"></param> ! /// <param name="obj"></param> ! /// <param name="session"></param> ! public override void Update( object id, object[ ] fields, int[ ] dirtyFields, object oldVersion, object obj, ISessionImplementor session ) { - bool[ ] tableUpdateNeeded; if( dirtyFields == null ) { ! tableUpdateNeeded = propertyHasColumns; //for object that came in via update() } else { ! tableUpdateNeeded = new bool[naturalOrderTableNames.Length]; for( int i = 0; i < dirtyFields.Length; i++ ) { --- 1274,1290 ---- /// <summary> ! /// Decide which tables need to be updated /// </summary> /// <param name="dirtyFields"></param> ! /// <returns></returns> ! private bool[] GetTableUpdateNeeded( int[] dirtyFields ) { if( dirtyFields == null ) { ! return propertyHasColumns; //for object that came in via update() } else { ! bool[ ] tableUpdateNeeded = new bool[naturalOrderTableNames.Length]; for( int i = 0; i < dirtyFields.Length; i++ ) { *************** *** 1362,1389 **** tableUpdateNeeded[ 0 ] = true; } } if( UseDynamicUpdate && dirtyFields != null ) { ! bool[ ] propsToUpdate = new bool[ HydrateSpan ]; ! for( int i = 0; i < HydrateSpan; i++ ) ! { ! bool dirty = false; ! for( int j = 0; j < dirtyFields.Length; j++ ) ! { ! if( dirtyFields[ j ] == i ) ! { ! dirty = true; ! } ! } ! propsToUpdate[ i ] = dirty || VersionProperty == i; ! } ! ! Update( id, fields, propsToUpdate, tableUpdateNeeded, oldVersion, obj, GenerateUpdateStrings( propsToUpdate ), session ); } else { ! Update( id, fields, PropertyUpdateability, tableUpdateNeeded, oldVersion, obj, SqlUpdateStrings, session ); } } --- 1295,1331 ---- tableUpdateNeeded[ 0 ] = true; } + return tableUpdateNeeded; } + } + /// <summary> + /// Update an object. + /// </summary> + /// <param name="id"></param> + /// <param name="fields"></param> + /// <param name="dirtyFields"></param> + /// <param name="oldFields"></param> + /// <param name="oldVersion"></param> + /// <param name="obj"></param> + /// <param name="session"></param> + public override void Update( object id, object[ ] fields, int[ ] dirtyFields, object[] oldFields, object oldVersion, object obj, ISessionImplementor session ) + { + bool[ ] tableUpdateNeeded = GetTableUpdateNeeded( dirtyFields ); + + SqlString[] updateStrings; + bool[] propsToUpdate; if( UseDynamicUpdate && dirtyFields != null ) { ! // decide which columns we really need to update ! propsToUpdate = GetPropertiesToUpdate( dirtyFields ); ! updateStrings = GenerateUpdateStrings( propsToUpdate ); } else { ! // just update them all ! propsToUpdate = PropertyUpdateability; ! updateStrings = SqlUpdateStrings; } + Update( id, fields, propsToUpdate, tableUpdateNeeded, oldVersion, obj, updateStrings, session ); } *************** *** 1485,1494 **** if ( type.IsAssociationType && ( (IAssociationType) type ).UsePrimaryKeyAsForeignKey ) { ! tableNumberByPropertyPath.Add( path, 0 ); } else { string propertyName = StringHelper.Root( path ); ! tableNumberByPropertyPath.Add( path, GetPropertyTableNumber( propertyName ) ); } } --- 1427,1436 ---- if ( type.IsAssociationType && ( (IAssociationType) type ).UsePrimaryKeyAsForeignKey ) { ! tableNumberByPropertyPath[ path ] = 0 ; } else { string propertyName = StringHelper.Root( path ); ! tableNumberByPropertyPath[ path ] = GetPropertyTableNumber( propertyName ); } } *************** *** 1521,1525 **** subclassTableNameClosure[ i ], Alias( name, i ), ! StringHelper.Prefix( IdentifierColumnNames, name + StringHelper.Dot ), subclassTableKeyColumns[ i ], innerJoin && isClassOrSuperclassTable[ i ] ? JoinType.InnerJoin : JoinType.LeftOuterJoin ); --- 1463,1467 ---- subclassTableNameClosure[ i ], Alias( name, i ), ! StringHelper.Qualify( name, IdentifierColumnNames ), subclassTableKeyColumns[ i ], innerJoin && isClassOrSuperclassTable[ i ] ? JoinType.InnerJoin : JoinType.LeftOuterJoin ); *************** *** 1546,1550 **** } ! throw new AssertionFailure( "table [" + tableName + "] not found" ); } --- 1488,1492 ---- } ! throw new AssertionFailure( string.Format( "table [{0}] not found", tableName ) ); } *************** *** 1597,1611 **** public override SqlString PropertySelectFragment( string alias, string suffix ) { - string[ ] cols = subclassColumnClosure; SelectFragment frag = new SelectFragment( factory.Dialect ) ! .SetSuffix( suffix ); ! for( int i = 0; i < cols.Length; i++ ) { ! frag.AddColumn( ! Alias( alias, subclassColumnTableNumberClosure[ i ] ), ! cols[ i ], ! subclassColumnClosureAliases[ i ] ! ); } --- 1539,1556 ---- public override SqlString PropertySelectFragment( string alias, string suffix ) { SelectFragment frag = new SelectFragment( factory.Dialect ) ! .SetSuffix( suffix ) ! .SetUsedAliases( IdentifierAliases ); ! for( int i = 0; i < subclassColumnClosure.Length; i++ ) { ! string subalias = Alias( alias, subclassColumnTableNumberClosure[ i ] ); ! frag.AddColumn( subalias, subclassColumnClosure[ i ], subclassColumnClosureAliases[ i ] ); ! } ! ! for( int i = 0; i < subclassFormulaTemplateClosure.Length; i++ ) ! { ! string subalias = Alias( alias, subclassFormulaTableNumberClosure[ i ] ); ! frag.AddColumn( subalias, subclassFormulaTemplateClosure[ i ], subclassFormulaAliasClosure[ i ] ); } *************** *** 1614,1621 **** SqlStringBuilder builder = new SqlStringBuilder( 3 ); ! builder.Add( ", " ); builder.Add( DiscriminatorFragment( alias ) ! .SetReturnColumnName( DiscriminatorColumnName, suffix ) .ToSqlStringFragment() ); --- 1559,1566 ---- SqlStringBuilder builder = new SqlStringBuilder( 3 ); ! builder.Add( StringHelper.CommaSpace ); builder.Add( DiscriminatorFragment( alias ) ! .SetReturnColumnName( DiscriminatorAlias, suffix ) .ToSqlStringFragment() ); *************** *** 1624,1628 **** return builder.ToSqlString(); - } else --- 1569,1572 ---- *************** *** 1654,1658 **** return name; } ! return Dialect.QuoteForAliasName( Dialect.UnQuote( name ) + StringHelper.Underscore + tableNumber ); } --- 1598,1602 ---- return name; } ! return Dialect.QuoteForAliasName( Dialect.UnQuote( name ) + StringHelper.Underscore + tableNumber + StringHelper.Underscore ); } *************** *** 1691,1702 **** { SqlString result = WhereJoinFragment( alias, innerJoin, includeSubclasses ); ! if( HasWhere ) { ! result = result.Append( " and " + GetSQLWhereString( alias ) ); } return result; - } --- 1635,1645 ---- { SqlString result = WhereJoinFragment( alias, innerJoin, includeSubclasses ); ! string rootAlias = Alias( alias, naturalOrderTableNames.Length - 1 ); // urgh, ugly!! if( HasWhere ) { ! result = result.Append( " and " + GetSQLWhereString( rootAlias ) ); } return result; } *************** *** 1714,1721 **** --- 1657,1676 ---- /// <summary></summary> + public override bool IsCacheInvalidationRequired + { + get { return hasFormulaProperties || ( !IsVersioned && UseDynamicUpdate ); } + } + + /// <summary></summary> protected override string VersionedTableName { get { return qualifiedTableName; } } + + /// <summary></summary> + protected override SqlString VersionSelectString + { + get { return sqlVersionSelectString; } + } } } \ No newline at end of file Index: IClassPersister.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/IClassPersister.cs,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** IClassPersister.cs 6 Mar 2005 12:44:45 -0000 1.10 --- IClassPersister.cs 14 Mar 2005 18:53:15 -0000 1.11 *************** *** 153,156 **** --- 153,166 ---- /// <summary> + /// Compare the state of an instance to the current database state + /// </summary> + /// <param name="old"></param> + /// <param name="current"></param> + /// <param name="owner"></param> + /// <param name="session"></param> + /// <returns>return <c>null</c> or the indicies of the modified properties</returns> + int[ ] FindModified( object[ ] old, object[ ] current, object owner, ISessionImplementor session ); + + /// <summary> /// Does the class have a property holding the identifier value? /// </summary> *************** *** 270,277 **** /// <param name="fields"></param> /// <param name="dirtyFields"></param> /// <param name="oldVersion"></param> /// <param name="obj"></param> /// <param name="session"></param> ! void Update( object id, object[ ] fields, int[ ] dirtyFields, object oldVersion, object obj, ISessionImplementor session ); /// <summary> --- 280,288 ---- /// <param name="fields"></param> /// <param name="dirtyFields"></param> + /// <param name="oldFields"></param> /// <param name="oldVersion"></param> /// <param name="obj"></param> /// <param name="session"></param> ! void Update( object id, object[ ] fields, int[ ] dirtyFields, object[ ] oldFields, object oldVersion, object obj, ISessionImplementor session ); /// <summary> *************** *** 326,329 **** --- 337,345 ---- /// <summary> + /// Should we always invalidate the cache instead of recaching updated state + /// </summary> + bool IsCacheInvalidationRequired { get; } + + /// <summary> /// Does this class have a cache? /// </summary> *************** *** 345,355 **** bool IsBatchLoadable { get; } - /* TODO : 2.1 features - not sure if we need for SQL loading - - /// <summary> - /// Get the proxy interface that instances of <em>this</em> concrete class will be cast to (optional operation). - /// </summary> - object ConcreteProxyClass { get; } - /// <summary> /// Get the current database state of the object, in a "hydrated" form, without resolving identifiers --- 361,364 ---- *************** *** 370,374 **** /// <returns></returns> object CurrentVersion( object id, ISessionImplementor session ); - */ } } \ No newline at end of file --- 379,382 ---- Index: EntityPersister.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/EntityPersister.cs,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -d -r1.36 -r1.37 *** EntityPersister.cs 1 Mar 2005 16:24:49 -0000 1.36 --- EntityPersister.cs 14 Mar 2005 18:53:15 -0000 1.37 *************** *** 75,81 **** private static readonly object NotNullDiscriminator = new object(); - // private readonly string[ ] StringArray = {}; - // private readonly IType[ ] TypeArray = {}; - private static readonly ILog log = LogManager.GetLogger( typeof( EntityPersister ) ); --- 75,78 ---- *************** *** 124,127 **** --- 121,125 ---- discriminatorValue = null; discriminatorSQLString = "null"; + discriminatorInsertable = false; } else *************** *** 130,133 **** --- 128,132 ---- discriminatorSQLString = discriminatorType.ObjectToSQLString( discriminatorValue ); } + discriminatorSQLValue = discriminatorSQLString; } // TODO: add a ClassCastException here to catch illegal disc types *************** *** 142,146 **** distinctColumns.Add( discriminatorColumnName ); - } else --- 141,144 ---- *************** *** 148,151 **** --- 146,150 ---- forceDiscriminator = false; discriminatorColumnName = null; + discriminatorInsertable = false; discriminatorValue = null; discriminatorType = null; *************** *** 207,211 **** } ! if( discriminatorInsertable) { distinctColumns.Add( discriminatorColumnName ); --- 206,210 ---- } ! if( discriminatorInsertable ) { distinctColumns.Add( discriminatorColumnName ); *************** *** 218,221 **** --- 217,221 ---- discriminatorInsertable = false; discriminatorColumnName = null; + discriminatorAlias = null; discriminatorValue = null; discriminatorType = null; *************** *** 384,387 **** --- 384,392 ---- } } + + // This is in PostInstatiate as it needs identifier info + //InitLockers(); + + InitSubclassPropertyAliasesMap( model ); } *************** *** 635,640 **** protected virtual SqlString GenerateInsertString( bool identityInsert, bool[ ] includeProperty ) { ! SqlInsertBuilder builder = new SqlInsertBuilder( factory ); ! builder.SetTableName( TableName ); for( int i = 0; i < HydrateSpan; i++ ) --- 640,645 ---- protected virtual SqlString GenerateInsertString( bool identityInsert, bool[ ] includeProperty ) { ! SqlInsertBuilder builder = new SqlInsertBuilder( factory ) ! .SetTableName( TableName ); for( int i = 0; i < HydrateSpan; i++ ) *************** *** 703,711 **** if( HasSubclasses ) { ! // TODO: Investigate why this breaks NewSessionLifecycle test ! // NB Seems to actually be a cascaded failure to delete a transient object which has a null key ! // then trying to rollback the existing transaction - which fails badly. ! //builder.AddColumn( DiscriminatorColumnName, DiscriminatorAlias ); ! builder.AddColumn( DiscriminatorColumnName ); } --- 708,712 ---- if( HasSubclasses ) { ! builder.AddColumn( DiscriminatorColumnName, DiscriminatorAlias ); } *************** *** 1220,1250 **** /// <param name="fields"></param> /// <param name="dirtyFields"></param> /// <param name="oldVersion"></param> /// <param name="obj"></param> /// <param name="session"></param> ! public override void Update( object id, object[ ] fields, int[ ] dirtyFields, object oldVersion, object obj, ISessionImplementor session ) { if( UseDynamicUpdate && dirtyFields != null ) { ! bool[ ] propsToUpdate = new bool[ HydrateSpan ]; ! for( int i = 0; i < HydrateSpan; i++ ) ! { ! bool dirty = false; ! for( int j = 0; j < dirtyFields.Length; j++ ) ! { ! if( dirtyFields[ j ] == i ) ! { ! dirty = true; ! } ! } ! propsToUpdate[ i ] = dirty || VersionProperty == i; ! //don't need to check property mutability (dirty checking algorithm handles that) ! } ! Update( id, fields, propsToUpdate, oldVersion, obj, GenerateUpdateString( propsToUpdate ), session ); } else { ! Update( id, fields, PropertyUpdateability, oldVersion, obj, SqlUpdateString, session ); } } --- 1221,1244 ---- /// <param name="fields"></param> /// <param name="dirtyFields"></param> + /// <param name="oldFields"></param> /// <param name="oldVersion"></param> /// <param name="obj"></param> /// <param name="session"></param> ! public override void Update( object id, object[ ] fields, int[ ] dirtyFields, object[ ] oldFields, object oldVersion, object obj, ISessionImplementor session ) { + bool[] propsToUpdate; + SqlString updateString; + if( UseDynamicUpdate && dirtyFields != null ) { ! propsToUpdate = GetPropertiesToUpdate( dirtyFields ); ! updateString = GenerateUpdateString( propsToUpdate, oldFields ); } else { ! propsToUpdate = PropertyUpdateability; ! updateString = SqlUpdateString; } + Update( id, fields, propsToUpdate, oldVersion, obj, updateString, session ); } *************** *** 1428,1437 **** public override SqlString PropertySelectFragment( string alias, string suffix ) { ! SelectFragment frag = new SelectFragment( factory.Dialect ); ! ! frag.SetSuffix( suffix ); if( HasSubclasses ) { ! frag.AddColumn( alias, DiscriminatorColumnName ); } --- 1422,1431 ---- public override SqlString PropertySelectFragment( string alias, string suffix ) { ! SelectFragment frag = new SelectFragment( factory.Dialect ) ! .SetSuffix( suffix ) ! .SetUsedAliases( IdentifierAliases ); if( HasSubclasses ) { ! frag.AddColumn( alias, DiscriminatorColumnName, DiscriminatorAlias ); } *************** *** 1472,1479 **** --- 1466,1485 ---- /// <summary></summary> + public override bool IsCacheInvalidationRequired + { + get { return hasFormulaProperties || ( !IsVersioned && UseDynamicUpdate ); } + } + + /// <summary></summary> protected override string VersionedTableName { get { return qualifiedTableName; } } + + /// <summary></summary> + protected override SqlString VersionSelectString + { + get { return sqlVersionSelectString; } + } } } \ No newline at end of file Index: ILoadable.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/ILoadable.cs,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** ILoadable.cs 1 Mar 2005 16:24:50 -0000 1.9 --- ILoadable.cs 14 Mar 2005 18:53:15 -0000 1.10 *************** *** 49,178 **** /// <returns></returns> string GetDiscriminatorAlias( string suffix ); - - // 2.03 features required currently by loader - - /// <summary> - /// How many properties are there, for this class and all subclasses? (optional operation) - /// </summary> - /// <returns></returns> - int CountSubclassProperties(); - - /// <summary> - /// The name of the column used as a discriminator - /// </summary> - string DiscriminatorColumnName { get; } - - /// <summary> - /// May this property be fetched using an SQL outerjoin? - /// </summary> - /// <param name="i"></param> - /// <returns></returns> - OuterJoinFetchStrategy EnableJoinedFetch( int i ); - - /// <summary> - /// Get the from clause part of any joins (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="innerJoin"></param> - /// <param name="includeSubclasses"></param> - /// <returns></returns> - SqlString FromJoinFragment( string alias, bool innerJoin, bool includeSubclasses ); - - /// <summary> - /// Get the column names for the numbered property of <c>this</c> class - /// </summary> - /// <param name="i"></param> - /// <returns></returns> - string[ ] GetPropertyColumnNames( int i ); - - /// <summary> - /// The names of columns used to persist the identifier - /// </summary> - string[ ] IdentifierColumnNames { get; } - - /// <summary> - /// Is this property defined on a subclass of the mapped class? - /// </summary> - /// <param name="i"></param> - /// <returns></returns> - bool IsDefinedOnSubclass( int i ); - - /// <summary> - /// Get an array of the types of all properties of all subclasses (optional operation) - /// </summary> - /// <param name="i"></param> - /// <returns></returns> - IType GetSubclassPropertyType( int i ); - - /// <summary> - /// Get the name of the numbered property of the class or a subclass - /// (optional operation) - /// </summary> - /// <param name="i"></param> - /// <returns></returns> - string GetSubclassPropertyName( int i ); - - /// <summary> - /// Return the column names used to persist all properties of all sublasses of the persistent class - /// (optional operation) - /// </summary> - string[ ] GetSubclassPropertyColumnNames( int i ); - - /// <summary> - /// Return the table name used to persist the numbered property of - /// the class or a subclass - /// (optional operation) - /// </summary> - string GetSubclassPropertyTableName( int i ); - - /// <summary> - /// Given the number of a property of a subclass, and a table alias, return the aliased column names - /// (optional operation) - /// </summary> - /// <param name="name"></param> - /// <param name="i"></param> - /// <returns></returns> - string[ ] ToColumns( string name, int i ); - - /// <summary> - /// Given a query alias and an identifying suffix, render the identifier select fragment - /// </summary> - /// <param name="name"></param> - /// <param name="suffix"></param> - /// <returns></returns> - SqlString IdentifierSelectFragment( string name, string suffix ); - - /// <summary> - /// Given a query alias and an identifying suffix, render the property select fragment - /// (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="suffix"></param> - /// <returns></returns> - SqlString PropertySelectFragment( string alias, string suffix ); - - /// <summary> - /// Get the main from table fragment, given a query alias (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <returns></returns> - SqlString FromTableFragment( string alias ); - - /// <summary> - /// Get the where clause part of any joins (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="innerJoin"></param> - /// <param name="includeSubclasses"></param> - /// <returns></returns> - SqlString WhereJoinFragment( string alias, bool innerJoin, bool includeSubclasses ); - - /* - /// These are in 2.03, but we can use IJoinables now - /// <summary> - /// The fully-qualified tablename used to persist this class - /// </summary> - string TableName { get; } - */ } } \ No newline at end of file --- 49,52 ---- Index: PersisterFactory.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/PersisterFactory.cs,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** PersisterFactory.cs 1 Mar 2005 16:24:50 -0000 1.3 --- PersisterFactory.cs 14 Mar 2005 18:53:15 -0000 1.4 *************** *** 92,98 **** public static ICollectionPersister CreateCollectionPersister( Configuration cfg, Mapping.Collection model, ISessionFactoryImplementor factory ) { return new CollectionPersister( model, cfg, factory ); - /* System.Type persisterClass = model.CollectionPersisterClass; if ( persisterClass == null ) --- 92,99 ---- public static ICollectionPersister CreateCollectionPersister( Configuration cfg, Mapping.Collection model, ISessionFactoryImplementor factory ) { + /* return new CollectionPersister( model, cfg, factory ); + */ System.Type persisterClass = model.CollectionPersisterClass; if ( persisterClass == null ) *************** *** 107,111 **** return Create( persisterClass, cfg, model, factory ); } - */ } --- 108,111 ---- Index: IOuterJoinLoadable.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/IOuterJoinLoadable.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** IOuterJoinLoadable.cs 1 Mar 2005 16:24:50 -0000 1.1 --- IOuterJoinLoadable.cs 14 Mar 2005 18:53:15 -0000 1.2 *************** *** 11,15 **** /// of a one-to-many association. /// </summary> ! public interface IOuterJoinLoadable { /// <summary> --- 11,15 ---- /// of a one-to-many association. /// </summary> ! public interface IOuterJoinLoadable : ILoadable, IJoinable { /// <summary> *************** *** 23,28 **** string DiscriminatorColumnName { get; } - //USED BY OuterJoinLoader + subclasses - /// <summary> /// How many properties are there, for this class and all subclasses? (optional operation) --- 23,26 ---- *************** *** 83,103 **** /// <summary> - /// Given a query alias and an identifying suffix, render the identifier select fragment - /// </summary> - /// <param name="name"></param> - /// <param name="suffix"></param> - /// <returns></returns> - SqlString IdentifierSelectFragment( string name, string suffix ); - - /// <summary> - /// Given a query alias and an identifying suffix, render the property select fragment - /// (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="suffix"></param> - /// <returns></returns> - SqlString PropertySelectFragment( string alias, string suffix ); - - /// <summary> /// Get the main from table fragment, given a query alias (optional operation) /// </summary> --- 81,84 ---- *************** *** 113,134 **** /// <returns></returns> SqlString SelectFragment( string alias, string suffix ); - - /// <summary> - /// Get the where clause part of any joins (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="innerJoin"></param> - /// <param name="includeSubclasses"></param> - /// <returns></returns> - SqlString WhereJoinFragment( string alias, bool innerJoin, bool includeSubclasses ); - - /// <summary> - /// Get the from clause part of any joins (optional operation) - /// </summary> - /// <param name="alias"></param> - /// <param name="innerJoin"></param> - /// <param name="includeSubclasses"></param> - /// <returns></returns> - SqlString FromJoinFragment( string alias, bool innerJoin, bool includeSubclasses ); } } --- 94,97 ---- Index: IQueryable.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/IQueryable.cs,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** IQueryable.cs 1 Mar 2005 16:24:50 -0000 1.10 --- IQueryable.cs 14 Mar 2005 18:53:15 -0000 1.11 *************** *** 39,51 **** SqlString QueryWhereFragment( string alias, bool innerJoin, bool includeSublcasses ); - /* /// <summary> ! /// Given a query alias and a property path, return the qualified column name /// </summary> /// <param name="alias"></param> ! /// <param name="property"></param> /// <returns></returns> ! string[ ] ToColumns( string alias, string property ); ! */ } } \ No newline at end of file --- 39,62 ---- SqlString QueryWhereFragment( string alias, bool innerJoin, bool includeSublcasses ); /// <summary> ! /// Given a query alias and an identifying suffix, render the intentifier select fragment. ! /// </summary> ! /// <param name="name"></param> ! /// <param name="suffix"></param> ! /// <returns></returns> ! SqlString IdentifierSelectFragment( string name, string suffix ); ! ! /// <summary> ! /// Given a query alias and an identifying suffix, render the property select fragment. /// </summary> /// <param name="alias"></param> ! /// <param name="suffix"></param> /// <returns></returns> ! SqlString PropertySelectFragment( string alias, string suffix ); ! ! /// <summary> ! /// Get the names of columns used to persist the identifier ! /// </summary> ! string[] IdentifierColumnNames { get; } } } \ No newline at end of file Index: AbstractEntityPersister.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Persister/AbstractEntityPersister.cs,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** AbstractEntityPersister.cs 6 Mar 2005 12:44:45 -0000 1.34 --- AbstractEntityPersister.cs 14 Mar 2005 18:53:15 -0000 1.35 *************** *** 1,4 **** --- 1,5 ---- using System; using System.Collections; + using System.Data; using System.Reflection; using Iesi.Collections; *************** *** 8,11 **** --- 9,13 ---- using NHibernate.Hql; using NHibernate.Id; + using NHibernate.Impl; using NHibernate.Loader; using NHibernate.Mapping; *************** *** 26,30 **** /// May be considred an immutable view of the mapping object /// </remarks> ! public abstract class AbstractEntityPersister : AbstractPropertyMapping, IQueryable, IClassMetadata { private static readonly ILog log = LogManager.GetLogger( typeof( AbstractEntityPersister ) ); --- 28,32 ---- /// May be considred an immutable view of the mapping object /// </remarks> ! public abstract class AbstractEntityPersister : AbstractPropertyMapping, IOuterJoinLoadable, IQueryable, IClassMetadata, IUniqueKeyLoadable, ISqlLoadable { private static readonly ILog log = LogManager.GetLogger( typeof( AbstractEntityPersister ) ); *************** *** 50,54 **** private readonly bool hasCascades; private readonly bool mutable; ! //private readonly bool selectBeforeUpdate; private readonly System.Type superclass; private readonly bool dynamicUpdate; --- 52,56 ---- private readonly bool hasCascades; private readonly bool mutable; ! private readonly bool selectBeforeUpdate; private readonly System.Type superclass; private readonly bool dynamicUpdate; *************** *** 59,63 **** private readonly IType entityType; private readonly ConstructorInfo constructor; ! //private readonly string rootClassName; // The optional SQL string defined in the where attribute --- 61,65 ---- private readonly IType entityType; private readonly ConstructorInfo constructor; ! private readonly string rootClassName; // The optional SQL string defined in the where attribute *************** *** 93,97 **** private readonly int versionProperty; //private Cascades.VersionValue unsavedVersionValues; ! private readonly bool jdbcBatchVersionData; // other properties (for this concrete class only, not the subclass closure) --- 95,99 ---- private readonly int versionProperty; //private Cascades.VersionValue unsavedVersionValues; ! //private readonly bool batchVersionData; // other properties (for this concrete class only, not the subclass closure) *************** *** 220,224 **** return new SelectFragment( Dialect ) .SetSuffix( suffix ) ! .AddColumns( name, IdentifierColumnNames ) .ToSqlStringFragment( false ); } --- 222,226 ---- return new SelectFragment( Dialect ) .SetSuffix( suffix ) ! .AddColumns( name, IdentifierColumnNames, IdentifierAliases ) .ToSqlStringFragment( false ); } *************** *** 227,230 **** --- 229,238 ---- /// /// </summary> + /// <returns></returns> + protected abstract SqlString VersionSelectString { get; } + + /// <summary> + /// + /// </summary> /// <param name="path"></param> /// <returns></returns> *************** *** 324,328 **** for( int i = 0; i < props.Length; i++ ) { ! log.Debug( className + StringHelper.Dot + propertyNames[ props[ i ] ] + " is dirty" ); } } --- 332,364 ---- for( int i = 0; i < props.Length; i++ ) { ! log.Debug( StringHelper.Qualify( className, propertyNames[ props[ i ] ] ) + " is dirty" ); ! } ! } ! return props; ! } ! } ! ! /// <summary> ! /// ! /// </summary> ! /// <param name="old"></param> ! /// <param name="current"></param> ! /// <param name="obj"></param> ! /// <param name="session"></param> ! /// <returns></returns> ! public virtual int[ ] FindModified( object[ ] old, object[ ] current, object obj, ISessionImplementor session ) ! { ! int[ ] props = TypeFactory.FindModified( propertyTypes, old, current, propertyUpdateability, session ); ! if( props == null ) ! { ! return null; ! } ! else ! { ! if( log.IsDebugEnabled ) ! { ! for( int i = 0; i < props.Length; i++ ) ! { ! log.Debug( StringHelper.Qualify( className, propertyNames[ props[ i ] ] ) + " is dirty" ); } } *************** *** 658,668 **** // CLASS - className = model.MappedClass.FullName; ! //rootClassName = model.RootClass.FullName; mappedClass = model.MappedClass; mutable = model.IsMutable; ! //selectBeforeUpdate = model.HasSelectBeforeUpdate; dynamicUpdate = model.DynamicUpdate; dynamicInsert = model.DynamicInsert; --- 694,703 ---- // CLASS className = model.MappedClass.FullName; ! rootClassName = model.RootClazz.Name; mappedClass = model.MappedClass; mutable = model.IsMutable; ! selectBeforeUpdate = model.SelectBeforeUpdate; dynamicUpdate = model.DynamicUpdate; dynamicInsert = model.DynamicInsert; *************** *** 685,691 **** entityType = NHibernateUtil.Entity( mappedClass ); /* optimisticLockMode = model.OptimisticLockMode; ! if ( optmisticLockMode > Versiong.OptimisticLockVersion && !dynamicUpdate ) { throw new MappingException( string.Format( "optimistic-lock setting requires dynamic-update=\'true\': {0}", className ) ); --- 720,727 ---- entityType = NHibernateUtil.Entity( mappedClass ); + // TODO : 2.1 Implement OptimisiticLockVersion /* optimisticLockMode = model.OptimisticLockMode; ! if ( optimisticLockMode > Version.OptimisticLockVersion && !dynamicUpdate ) { throw new MappingException( string.Format( "optimistic-lock setting requires dynamic-update=\'true\': {0}", className ) ); *************** *** 701,705 **** // IDENTIFIER - hasEmbeddedIdentifier = model.HasEmbeddedIdentifier; IValue idValue = model.Identifier; --- 737,740 ---- *************** *** 750,758 **** // HYDRATE SPAN - hydrateSpan = model.PropertyClosureCollection.Count; // IDENTIFIER - int idColumnSpan = model.Identifier.ColumnSpan; identifierColumnNames = new string[ idColumnSpan ]; --- 785,791 ---- *************** *** 773,777 **** // UNSAVED-VALUE: - string unsavedValue = model.Identifier.NullValue; if( unsavedValue == null || "null".Equals( unsavedValue ) ) --- 806,809 ---- *************** *** 818,822 **** } ! // TODO: Bring versioning up to 2.1 standards if( model.IsVersioned ) { --- 850,854 ---- } ! // TODO: 2.1 Bring versioning up to standards if( model.IsVersioned ) { *************** *** 957,963 **** public string[] GetIdentifierAliases( string suffix ) { ! // NOTE: this assumes something about how propertySelectFragment is implemented by the subclass! // was toUnqotedAliasStrings( getIdentiferColumnNames() ) before - now tried ! // to remove that unqoting and missing aliases.. return new Alias(suffix).ToAliasStrings( IdentifierAliases, dialect ); } --- 989,995 ---- public string[] GetIdentifierAliases( string suffix ) { ! // NOTE: this assumes something about how PropertySelectFragment is implemented by the subclass! // was toUnqotedAliasStrings( getIdentiferColumnNames() ) before - now tried ! // to remove that unquoting and missing aliases.. return new Alias(suffix).ToAliasStrings( IdentifierAliases, dialect ); } *************** *** 971,975 **** public string[] GetPropertyAliases( string suffix, int i ) { ! // NOTE: this assumes something about how propertySelectFragment is implemented by the subclass! return new Alias(suffix).ToUnquotedAliasStrings( GetPropertyColumnNames( i ), dialect ); } --- 1003,1007 ---- public string[] GetPropertyAliases( string suffix, int i ) { ! // NOTE: this assumes something about how pPropertySelectFragment is implemented by the subclass! return new Alias(suffix).ToUnquotedAliasStrings( GetPropertyColumnNames( i ), dialect ); } *************** *** 982,988 **** public string GetDiscriminatorAlias( string suffix ) { ! // NOTE: this assumes something about how propertySelectFragment is implemented by the subclass! // was toUnqotedAliasStrings( getdiscriminatorColumnName() ) before - now tried ! // to remove that unqoting and missing aliases.. return hasSubclasses ? new Alias(suffix).ToAliasString( DiscriminatorAlias, dialect ) : --- 1014,1020 ---- public string GetDiscriminatorAlias( string suffix ) { ! // NOTE: this assumes something about how PropertySelectFragment is implemented by the subclass! // was toUnqotedAliasStrings( getdiscriminatorColumnName() ) before - now tried ! // to remove that unquoting and missing aliases.. return hasSubclasses ? new Alias(suffix).ToAliasString( DiscriminatorAlias, dialect ) : *************** *** 1002,1007 **** if ( HasIdentifierProperty ) { ! subclassPropertyAliases.Add( IdentifierPropertyName, identifierAliases ); ! subclassPropertyAliases.Add( PathExpressionParser.EntityID, identifierAliases ) ; } --- 1034,1039 ---- if ( HasIdentifierProperty ) ... [truncated message content] |