[fdo-commits] r2519 - in trunk: Providers/GenericRdbms/Src/UnitTest Providers/GenericRdbms/Src/UnitTest/Common Utilities/SchemaMgr Utilities/SchemaMgr/Inc/Sm/Ph Utilities/SchemaMgr/Inc/Sm/Ph/Rd Utilities/SchemaMgr/Nls Utilities/SchemaMgr/Src/Sm/Ph Utilities/SchemaMgr/Src/Sm/Ph/Rd

svn_fdo at osgeo.org svn_fdo at osgeo.org
Thu Feb 15 12:36:56 EST 2007


Author: brentrobinson
Date: 2007-02-15 12:36:56 -0500 (Thu, 15 Feb 2007)
New Revision: 2519

Added:
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObject.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObjectCollection.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/BaseObjectReader.h
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/BaseObject.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/BaseObjectReader.cpp
Modified:
   trunk/Providers/GenericRdbms/Src/UnitTest/Common/FdoUpdateTest.cpp
   trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.cpp
   trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.h
   trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_MySql_master.txt
   trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_Oracle_master.txt
   trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer2005_master.txt
   trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer_master.txt
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Column.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnDecimal.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnGeom.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnVarlen.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Database.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/DbObject.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Mgr.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Owner.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/ClassReader.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/PropertyReader.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Table.h
   trunk/Utilities/SchemaMgr/Inc/Sm/Ph/View.h
   trunk/Utilities/SchemaMgr/LogicalPhysical.vcproj
   trunk/Utilities/SchemaMgr/Nls/SmMessage.mc
   trunk/Utilities/SchemaMgr/Physical.vcproj
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Column.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnDecimal.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnGeom.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnVarlen.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Database.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/DbObject.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Makefile.am
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Mgr.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Owner.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/ClassReader.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/Makefile.am
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/PropertyReader.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp
   trunk/Utilities/SchemaMgr/Src/Sm/Ph/View.cpp
Log:
Reverse-engineer views by default


Modified: trunk/Providers/GenericRdbms/Src/UnitTest/Common/FdoUpdateTest.cpp
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/Common/FdoUpdateTest.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/Common/FdoUpdateTest.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -1919,7 +1919,7 @@
         table->AddPkeyCol( fkColumn->GetName() );
 
     if ( hasGeom )
-        column = table->CreateColumnGeom( phMgr->GetDcColumnName(L"GEOMETRY"), (FdoSmPhScInfo*) NULL, true, true );
+        column = table->CreateColumnGeom( phMgr->GetDcColumnName(L"GEOMETRY"), (FdoSmPhScInfo*) NULL, true, false );
 
     column = table->CreateColumnChar( phMgr->GetDcColumnName(ValueColName()), true, 20 );
 
@@ -2014,8 +2014,8 @@
     propertyValue = FdoUpdateTest::AddNewProperty( propertyValues, phMgr->GetDcColumnName(ValueColName()) );
     propertyValue->SetValue(dataValue);
     
-    double       coordsBuffer[3];
-    int          segCount = 1;
+    double       coordsBuffer[4];
+    int          segCount = 2;
     FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
 
     if ( hasGeom ) {
@@ -2023,6 +2023,8 @@
 		// Use 2D to accomodate MySql
         coordsBuffer[0] = 5;
         coordsBuffer[1] = 10;
+        coordsBuffer[2] = 15;
+        coordsBuffer[3] = 20;
 
         propertyValue = FdoUpdateTest::AddNewProperty( propertyValues, phMgr->GetDcColumnName(L"GEOMETRY") );
         FdoPtr<FdoILineString> line1 = gf->CreateLineString(FdoDimensionality_XY, segCount*2, coordsBuffer);

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.cpp
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -22,6 +22,7 @@
 #include "ConnectionUtil.h"
 #include <Sm/Ph/Rd/ConstraintReader.h>
 #include <Sm/Ph/SpatialIndex.h>
+#include "../SchemaMgr/Ph/Owner.h"
 
 FdoString* SchemaMgrTests::DB_NAME_SUFFIX =           L"_schema_mgr";
 FdoString* SchemaMgrTests::DB_NAME_COPY_SUFFIX =      L"_schema_mgr_copy";
@@ -139,6 +140,8 @@
 
         FdoSmPhViewP view1 = owner->CreateView( phMgr->GetDcDbObjectName(L"VIEW1"), L"", owner->GetName(), phMgr->GetDcDbObjectName(L"TABLE1" ));
         column = view1->CreateColumnInt32( L"ID", false, false, L"ID" );
+        if ( SupportsViewPkey() ) 
+            view1->AddPkeyCol( L"ID" );
         column = view1->CreateColumnDecimal( L"DEC_COL_RENAME", true, 10, 5, L"DECIMAL_COLUMN" );
         column = view1->CreateColumnByte( L"BYTE_COLUMN", true, L"BYTE_COLUMN" );
 
@@ -181,9 +184,18 @@
         FdoSmPhViewP view2 = owner->CreateView( phMgr->GetDcDbObjectName(L"VIEW2"), L"", owner->GetName(), phMgr->GetDcDbObjectName(L"TABLE2" ));
         column = view2->CreateColumnInt32( L"ID", false, false, L"ID" );
         column = view2->CreateColumnChar( L"STRING_COLUMN", false, 50, L"STRING_COLUMN" );
+
         column = view2->CreateColumnDouble( L"DOUBLE_COLUMN", true, L"DOUBLE_COLUMN" );
         column = view2->CreateColumnGeom( L"GEOM_COLUMN", (FdoSmPhScInfo*) NULL, true, true, false, L"GEOM_COLUMN" );
 
+        FdoSmPhViewP view3 = owner->CreateView( phMgr->GetDcDbObjectName(L"VIEW3"), L"", owner->GetName(), phMgr->GetDcDbObjectName(L"TABLE4" ));
+        column = view3->CreateColumnInt32( L"ID", false, false, L"ID" );
+        column = view3->CreateColumnChar( L"STRING_COLUMN", false, 50, L"STRING_COLUMN" );
+        if ( SupportsViewPkey() ) 
+            view3->AddPkeyCol( column->GetName() );
+        column = view3->CreateColumnInt16( L"INT16_COLUMN", true, false, L"INT16_COLUMN" );
+        column = view3->CreateColumnGeom( L"GEOM_COLUMN", (FdoSmPhScInfo*) NULL, true, true, false, L"GEOM_COLUMN" );
+
 #ifndef RDBI_DEF_SSQL
         table = owner->CreateTable( phMgr->GetDcDbObjectName(L"TABLE5" ));
         column = table->CreateColumnDecimal( L"ID", false, 10, 2 );
@@ -354,6 +366,19 @@
                     pCmd->SetPhysicalMapping( overrides );
             }
 
+            // Special case for MySQL. Classes from views do not get identity.
+            // class "view3" is a feature class since it has geometry.
+            // However, feature classes without identity are not allowed in FDO-enabled 
+            // datastores, so remove this class when it has no identity.
+
+            FdoClassesP classes = schema->GetClasses();
+            FdoClassDefinitionP view3Class = classes->FindItem( L"view3" );
+            if ( view3Class && (view3Class->GetClassType() == FdoClassType_FeatureClass) ) {
+                FdoDataPropertiesP idProps = view3Class->GetIdentityProperties();
+                if ( idProps->GetCount() == 0 )
+                    classes->Remove( view3Class );
+            }
+
             pCmd->Execute();
         }
 
@@ -743,29 +768,52 @@
         AddPkey( table );
         AddIndex( table, true, L"ALT_KEY1", L"INT16_COL1" );
 
+        FdoSmPhViewP view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX1A"), table->GetName() );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX1B"), view->GetName() );
+        FdoSmPhColumnsP columns = view->GetColumns();
+        columns->RemoveAt( columns->IndexOf(phMgr->GetDcColumnName(L"ID")) );
+
         // Tests choosing heavier index with fewer columns
         table = CreateIxTable(owner, L"TABLE_IX2", 0 );
         AddIndex( table, true, L"IX_21", L"INT16_COL1 INT16_COL2" );
         AddIndex( table, true, L"IX_22", L"STRING_COL5" );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX2A"), table->GetName() );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX2B"), view->GetName() );
+        columns = view->GetColumns();
+        columns->RemoveAt( columns->IndexOf(phMgr->GetDcColumnName(L"STRING_COL5")) );
+
+        FdoStringP createIx2cSql = FdoStringP::Format( 
+            L"create view view_ix2c ( id, int16_col1 ) as select id, int16_col1 from %ls", 
+            (FdoString*)(view->GetDbQName())
+        );
+
         // Multi-column index tests
         table = CreateIxTable(owner, L"TABLE_IX3", 0 );
         AddIndex( table, true, L"IX_31", L"INT16_COL1 INT16_COL2" );
         AddIndex( table, true, L"IX_32", L"STRING_COL1 STRING_COL2" );
         AddIndex( table, true, L"IX_33", L"INT16_COL1 STRING_COL1" );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX3A"), table->GetName() );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX3B"), view->GetName() );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX3C"), view->GetName() );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX3D"), view->GetName() );
+
         // string column tests
         table = CreateIxTable(owner, L"TABLE_IX4", 0 );
         AddIndex( table, true, L"IX_41", L"STRING_COL1" );
         AddIndex( table, true, L"IX_42", L"INT16_COL1" );
         AddIndex( table, true, L"IX_43", L"STRING_COL2" );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX4A"), table->GetName() );
+
         // Test skipping index that is too heavy.
         // This index is too long to create on MySql or SqlServer so
         // test only for Oracle.
 #ifdef RDBI_DEF_ORA
         table = CreateIxTable(owner, L"TABLE_IX5", 0 );
         AddIndex( table, true, L"IX_51", L"STRING_COL3 STRING_COL4" );
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX5A"), table->GetName() );
 #endif
 
         // Test skipping non-unique index
@@ -774,17 +822,50 @@
         AddIndex( table, true, L"IX_62", L"STRING_COL1 STRING_COL2" );
         AddIndex( table, false, L"IX_63", L"INT16_COL1 STRING_COL2" );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX6A"), table->GetName() );
+        FdoStringP createIx6bSql = FdoStringP::Format( 
+            L"create view view_ix6b ( icol1, icol2, string_col1, string_col2 ) as select int16_col1, int16_col2, string_col1, string_col2 from %ls", 
+            (FdoString*)(view->GetDbQName())
+        );
+
+        FdoStringP createIx6cSql = FdoStringP::Format( 
+            L"create view view_ix6c ( string_col1, int16_col2, int16_col1, string_col2 ) as select int16_col1, int16_col2, string_col1, string_col2 from %ls", 
+            (FdoString*)(view->GetDbQName())
+        );
+
         // Test date columns
         table = CreateIxTable(owner, L"TABLE_IX7", 0 );
         AddIndex( table, true, L"IX_71", L"DATE_COL1 STRING_COL2" );
         AddIndex( table, true, L"IX_72", L"STRING_COL5 STRING_COL2" );
         AddIndex( table, true, L"IX_73", L"STRING_COL6 STRING_COL2" );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX7A"), table->GetName() );
+
         // Test id'less table.
         table = CreateIxTable(owner, phMgr->GetDcDbObjectName(L"TABLE_IX8"), 0 );
 
+        view = CreateIxView( owner, phMgr->GetDcDbObjectName(L"VIEW_IX8A"), table->GetName() );
+
+        FdoStringP createJoinSql = L"create view view_join ( id, string_col5 ) as select a.id, b.string_col5 from table_ix1 a, table_ix2 b";
+
         database->Commit();
 
+        FdoSmPhGrdOwnerP grdOwner = owner->SmartCast<FdoSmPhGrdOwner>();
+
+        grdOwner->ActivateAndExecute( (FdoString*) createIx2cSql );
+        grdOwner->ActivateAndExecute( (FdoString*) createIx6bSql );
+        grdOwner->ActivateAndExecute( (FdoString*) createIx6cSql );
+        grdOwner->ActivateAndExecute( (FdoString*) createJoinSql );
+
+        mgr = NULL;
+        phMgr = NULL;
+        conn->disconnect();
+        delete conn;
+        conn = CreateStaticConnection();
+        conn->connect();
+        mgr = conn->CreateSchemaManager();
+        phMgr = mgr->GetPhysicalSchema()->SmartCast<FdoSmPhGrdMgr>();
+
         printf( "Autogenerating schema from datastore ...\n" );
 
         fdoConn = UnitTestUtil::CreateConnection(
@@ -799,63 +880,144 @@
         FdoClassesP classes = schema->GetClasses();
 
 #ifdef RDBI_DEF_ORA
-        CPPUNIT_ASSERT( classes->GetCount() == 8 );
+        CPPUNIT_ASSERT( classes->GetCount() == 25 );
 #else
-        CPPUNIT_ASSERT( classes->GetCount() == 7 );
+        CPPUNIT_ASSERT( classes->GetCount() == 23 );
 #endif
+        FdoInt32 pass;
+        FdoClassDefinitionP featClass;
+        FdoDataPropertiesP idProps;
+        FdoDataPropertyP prop;
 
-        FdoClassDefinitionP featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX1") );
-        FdoDataPropertiesP idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 1 );
-        FdoDataPropertyP prop = idProps->GetItem(0);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"ID")) == 0 );
+        for ( pass = 0; pass < 2; pass++ ) {
+            featClass = classes->GetItem( table2class(phMgr, (pass==0) ? L"TABLE_IX1" : L"VIEW_IX1A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 1 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"ID")) == 0 );
+            }
+            else {
+                CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+            }
 
-        featClass = classes->GetItem( table2class(phMgr,"TABLE_IX2") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 1 );
-        prop = idProps->GetItem(0);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL5")) == 0 );
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX2" : L"VIEW_IX2A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 1 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL5")) == 0 );
+            }
+            else {
+                CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+            }
 
-        featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX3") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 2 );
-        prop = idProps->GetItem(0);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
-        prop = idProps->GetItem(1);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX3" : L"VIEW_IX3A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+                prop = idProps->GetItem(1);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+            }
+            else {
+                CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+            }
 
-        featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX4") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 1 );
-        prop = idProps->GetItem(0);
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX4" : L"VIEW_IX4A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 1 );
+                prop = idProps->GetItem(0);
 #ifdef RDBI_DEF_ORA
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL2")) == 0 );
-		featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX5") );
-		idProps = featClass->GetIdentityProperties();
-		CPPUNIT_ASSERT( idProps->GetCount() == 0 );        
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL2")) == 0 );
+		        featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX5" : L"VIEW_IX5A") );
+		        idProps = featClass->GetIdentityProperties();
+		        CPPUNIT_ASSERT( idProps->GetCount() == 0 );        
 #else
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
 #endif
-        featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX6") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 2 );
-        prop = idProps->GetItem(0);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
-        prop = idProps->GetItem(1);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+            }
 
-        featClass = classes->GetItem( table2class(phMgr,"TABLE_IX7") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 2 );
-        prop = idProps->GetItem(0);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL5")) == 0 );
-        prop = idProps->GetItem(1);
-        CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL2")) == 0 );
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX6" : L"VIEW_IX6A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+                prop = idProps->GetItem(1);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+            }
+            else {
+                CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+            }
 
-        featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX8") );
-        idProps = featClass->GetIdentityProperties();
-        CPPUNIT_ASSERT( idProps->GetCount() == 0 );        
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX7" : L"VIEW_IX7A") );
+            idProps = featClass->GetIdentityProperties();
+            if ( SupportsBaseObjects() || (pass == 0) ) {
+                CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL5")) == 0 );
+                prop = idProps->GetItem(1);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL2")) == 0 );
+            }
+            else {
+                CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+            }
 
+            featClass = classes->GetItem( table2class(phMgr,(pass==0) ? L"TABLE_IX8" : L"VIEW_IX8A") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 0 );        
+        }
+
+        if ( SupportsBaseObjects() ) {
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_IX1B") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 1 );
+            prop = idProps->GetItem(0);
+            CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_IX2B") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+            prop = idProps->GetItem(0);
+            CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+            prop = idProps->GetItem(1);
+            CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_IX2C") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+
+            for ( pass = 0; pass < 3; pass++ ) {
+                FdoStringP viewName = FdoStringP::Format( L"VIEW_IX3%c", 'B' + pass );
+                featClass = classes->GetItem( table2class(phMgr, viewName) );
+                idProps = featClass->GetIdentityProperties();
+                CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+                prop = idProps->GetItem(0);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL1")) == 0 );
+                prop = idProps->GetItem(1);
+                CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"INT16_COL2")) == 0 );
+            }
+
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_IX6B") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 2 );
+            prop = idProps->GetItem(0);
+            CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL1")) == 0 );
+            prop = idProps->GetItem(1);
+            CPPUNIT_ASSERT( wcscmp(prop->GetName(), phMgr->GetDcColumnName(L"STRING_COL2")) == 0 );
+
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_IX6C") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+
+            featClass = classes->GetItem( table2class(phMgr, L"VIEW_JOIN") );
+            idProps = featClass->GetIdentityProperties();
+            CPPUNIT_ASSERT( idProps->GetCount() == 0 );
+        }
+
         UnitTestUtil::CloseConnection( fdoConn, false, L"_schema_mgr" );
 
         printf( "Updating original schema ...\n" );
@@ -906,9 +1068,9 @@
         classes = schema->GetClasses();
 
 #ifdef RDBI_DEF_ORA
-        CPPUNIT_ASSERT( classes->GetCount() == 8 );
+        CPPUNIT_ASSERT( classes->GetCount() == 25 );
 #else
-        CPPUNIT_ASSERT( classes->GetCount() == 7 );
+        CPPUNIT_ASSERT( classes->GetCount() ==  23);
 #endif
         featClass = classes->GetItem( table2class(phMgr,L"TABLE_IX2") );
         idProps = featClass->GetIdentityProperties();
@@ -1231,6 +1393,35 @@
     return table;
 }
 
+FdoSmPhViewP SchemaMgrTests::CreateIxView( FdoSmPhOwnerP owner, FdoStringP viewName, FdoStringP tableName )   
+{
+    FdoSmPhMgrP phMgr = owner->GetManager();
+
+    FdoSmPhViewP view = owner->CreateView( phMgr->GetDcDbObjectName(viewName), L"", owner->GetName(), tableName );
+    FdoStringP columnName = phMgr->GetDcColumnName(L"ID");
+    FdoSmPhColumnP column = view->CreateColumnInt32( columnName, false, false, columnName );
+    columnName = phMgr->GetDcColumnName(L"INT16_COL1");
+    column = view->CreateColumnInt16( columnName, false, false, columnName );
+    columnName = phMgr->GetDcColumnName(L"INT16_COL2");
+    column = view->CreateColumnInt16( columnName, false, false, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL1");
+    column = view->CreateColumnChar( columnName, false, 10, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL2");
+    column = view->CreateColumnChar( columnName, false, 7, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL3");
+    column = view->CreateColumnChar( columnName, false, 2500, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL4");
+    column = view->CreateColumnChar( columnName, false, 2501, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL5");
+    column = view->CreateColumnChar( columnName, false, 49, columnName );
+    columnName = phMgr->GetDcColumnName(L"STRING_COL6");
+    column = view->CreateColumnChar( columnName, false, 51, columnName );
+    columnName = phMgr->GetDcColumnName(L"DATE_COL1");
+    column = view->CreateColumnDate( columnName, false, columnName );
+
+    return view;
+}
+
 void SchemaMgrTests::AddPkey( FdoSmPhTableP table )
 {
     if ( FdoPtr<FdoSmPhColumn>(table->GetColumns()->FindItem(L"ID")) ) 
@@ -1421,3 +1612,13 @@
 
     return assocName;
 }
+
+bool SchemaMgrTests::SupportsBaseObjects()
+{
+    return false;
+}
+
+bool SchemaMgrTests::SupportsViewPkey()
+{
+    return false;
+}

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.h
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/Common/SchemaMgrTests.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -91,12 +91,16 @@
     void CreateTableGroup( FdoSmPhOwnerP owner, FdoStringP prefix, FdoInt32 count, int lt_mode );
     void CreateFkey( FdoSmPhOwnerP owner, FdoStringP fTableName, FdoStringP pTableName, FdoStringP pOwnerName = L"" );
 
+    virtual bool SupportsBaseObjects();
+    virtual bool SupportsViewPkey();
+
     static FdoString* DB_NAME_SUFFIX;
     static FdoString* DB_NAME_COPY_SUFFIX;
     static FdoString* DB_NAME_FOREIGN_SUFFIX;
 
 private:
     FdoSmPhTableP CreateIxTable( FdoSmPhOwnerP owner, FdoStringP tableName, int lt_mode );
+    FdoSmPhViewP CreateIxView( FdoSmPhOwnerP owner, FdoStringP viewName, FdoStringP tableName );
     void AddPkey( FdoSmPhTableP table );
     void AddIndex( FdoSmPhTableP table, bool unique, FdoStringP indexName, FdoStringP columns );
     void SetLtLck( FdoSmPhTableP table, int lt_mode );

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_MySql_master.txt
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_MySql_master.txt	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_MySql_master.txt	2007-02-15 17:36:56 UTC (rev 2519)
@@ -867,5 +867,39 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
+<xs:complexType name="view1Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:sequence>
+<xs:element name="BYTE_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="fdo:byte"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="DEC_COL_RENAME" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value="5"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="ID">
+<xs:simpleType>
+<xs:restriction base="fdo:int32"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+</xs:sequence>
+</xs:complexType>
 </xs:schema>
 </fdo:DataStore>

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_Oracle_master.txt
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_Oracle_master.txt	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_Oracle_master.txt	2007-02-15 17:36:56 UTC (rev 2519)
@@ -2051,5 +2051,109 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
+<xs:element name="VIEW1" type="AutoGen:VIEW1Type" abstract="false" substitutionGroup="gml:_Feature">
+<xs:key name="VIEW1Key">
+<xs:selector xpath=".//VIEW1"/>
+<xs:field xpath="ID"/>
+</xs:key>
+</xs:element>
+<xs:complexType name="VIEW1Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:complexContent>
+<xs:extension base="fdo:ClassType">
+<xs:sequence>
+<xs:element name="BYTE_COLUMN" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="3"/>
+<xs:fractionDigits value=""/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="DEC_COL_RENAME" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value="5"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="ID">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value=""/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:element name="VIEW3" type="AutoGen:VIEW3Type" abstract="false" substitutionGroup="gml:_Feature">
+<xs:key name="VIEW3Key">
+<xs:selector xpath=".//VIEW3"/>
+<xs:field xpath="STRING_COLUMN"/>
+</xs:key>
+</xs:element>
+<xs:complexType name="VIEW3Type" abstract="false" fdo:geometryName="GEOM_COLUMN">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:complexContent>
+<xs:extension base="gml:AbstractFeatureType">
+<xs:sequence>
+<xs:element name="GEOM_COLUMN" type="gml:AbstractGeometryType" fdo:hasMeasure="false" fdo:hasElevation="true" fdo:srsName="SC_1" fdo:geometricTypes="point curve surface " fdo:geometryTypes="point multipoint linestring multilinestring curvestring multicurvestring polygon multipolygon curvepolygon multicurvepolygon ">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="ID">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value=""/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="INT16_COLUMN" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="5"/>
+<xs:fractionDigits value=""/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="STRING_COLUMN">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:string">
+<xs:maxLength value="50"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
 </xs:schema>
 </fdo:DataStore>

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer2005_master.txt
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer2005_master.txt	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer2005_master.txt	2007-02-15 17:36:56 UTC (rev 2519)
@@ -677,6 +677,81 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
+<xs:complexType name="view1Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:sequence>
+<xs:element name="BYTE_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="fdo:byte"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="DEC_COL_RENAME" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value="5"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="ID">
+<xs:simpleType>
+<xs:restriction base="fdo:int32"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+</xs:sequence>
+</xs:complexType>
+<xs:complexType name="view3Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:sequence>
+<xs:element name="GEOM_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="xs:hexBinary"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="ID">
+<xs:simpleType>
+<xs:restriction base="fdo:int32"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="INT16_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="fdo:int16"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="STRING_COLUMN">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:string">
+<xs:maxLength value="50"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+</xs:sequence>
+</xs:complexType>
 </xs:schema>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://fdo.osgeo.org/schemas/feature/guest" xmlns:fdo="http://fdo.osgeo.org/schemas" xmlns:gml="http://www.opengis.net/gml" xmlns:guest="http://fdo.osgeo.org/schemas/feature/guest" elementFormDefault="qualified" attributeFormDefault="unqualified">
 <xs:annotation>

Modified: trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer_master.txt
===================================================================
--- trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer_master.txt	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Providers/GenericRdbms/Src/UnitTest/gen_default1_SqlServer_master.txt	2007-02-15 17:36:56 UTC (rev 2519)
@@ -677,6 +677,81 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
+<xs:complexType name="view1Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:sequence>
+<xs:element name="BYTE_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="fdo:byte"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="DEC_COL_RENAME" minOccurs="0">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:decimal">
+<xs:totalDigits value="10"/>
+<xs:fractionDigits value="5"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+<xs:element name="ID">
+<xs:simpleType>
+<xs:restriction base="fdo:int32"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+</xs:sequence>
+</xs:complexType>
+<xs:complexType name="view3Type" abstract="false">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:sequence>
+<xs:element name="GEOM_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="xs:hexBinary"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="ID">
+<xs:simpleType>
+<xs:restriction base="fdo:int32"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="INT16_COLUMN" minOccurs="0">
+<xs:simpleType>
+<xs:restriction base="fdo:int16"/>
+</xs:simpleType>
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+</xs:element>
+<xs:element name="STRING_COLUMN">
+<xs:annotation>
+<xs:documentation/>
+</xs:annotation>
+<xs:simpleType>
+<xs:restriction base="xs:string">
+<xs:maxLength value="50"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:element>
+</xs:sequence>
+</xs:complexType>
 </xs:schema>
 <SchemaMapping xmlns:rdb="http://fdordbms.osgeo.org/schemas" xmlns="http://www.autodesk.com/isd/fdo/SqlServerProvider" textInRow="NotInRow" provider="Autodesk.SqlServer.3.2" name="dbo">
 <complexType name="rtable1Type" identityIsGloballyUnique="false" identitySeed="0" identityIncrement="0" identityPropertyName="">

Added: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObject.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObject.h	                        (rev 0)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObject.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -0,0 +1,87 @@
+#ifndef FDOSMPHBASEOBJECT_H
+#define FDOSMPHBASEOBJECT_H		1
+/*
+ * Copyright (C) 2004-2006  Autodesk, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser
+ * General Public License as published by the Free Software Foundation.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#include <Sm/Ph/DbElement.h>
+
+class FdoSmPhDbObject;
+
+// This represents a base object reference (typically a reference from a view to 
+// a table or view that it is derived from).
+class FdoSmPhBaseObject : public FdoSmPhDbElement
+{
+public:
+    /// Constructs an instance of a base object reference, given the referenced object's name.
+    /// 
+    /// Parameters:
+    /// 	name: referenced object name
+    /// 	parent: referencing object
+    /// 	ownerName: referenced object's owner name. Defaults to referencing objects owner name.
+    /// 	databaseName: referenced object's database name. Defaults to current database.
+    FdoSmPhBaseObject(
+        FdoStringP name, 
+        FdoPtr<FdoSmPhDbObject> parent,
+        FdoStringP ownerName = L"",
+        FdoStringP databaseName = L""
+    );
+
+    /// Constructs an instance of a base object reference, given the referenced object.
+    /// 
+    /// Parameters:
+    /// 	dbObject: referenced object
+    /// 	parent: referencing object
+    FdoSmPhBaseObject(
+        FdoPtr<FdoSmPhDbObject> dbObject,
+        FdoPtr<FdoSmPhDbObject> parent
+    );
+
+    /// Get the referenced object
+    const FdoSmPhDbObject* RefDbObject() const;
+    FdoPtr<FdoSmPhDbObject> GetDbObject();
+
+    /// Get the referenced object's owner name
+    FdoStringP GetOwnerName() const;
+
+    /// Get the referenced object's database name
+    FdoStringP GetDatabaseName() const;
+
+protected:
+    /// unused constructor needed only to build on Linux
+    FdoSmPhBaseObject();
+
+	virtual ~FdoSmPhBaseObject(void);
+
+    // Base object references are not directly persisted in RDBMS.
+    virtual bool Add() {return true;}
+    virtual bool Modify() {return true;}
+    virtual bool Delete() {return true;}
+
+private:
+    FdoStringP mOwnerName;
+    FdoStringP mDatabaseName;
+
+    FdoPtr<FdoSmPhDbObject> mDbObject;
+
+};
+
+typedef FdoPtr<FdoSmPhBaseObject> FdoSmPhBaseObjectP;
+
+#endif
+
+

Added: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObjectCollection.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObjectCollection.h	                        (rev 0)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/BaseObjectCollection.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -0,0 +1,45 @@
+#ifndef FDOSMPHBASEOBJECTCOLLECTION_H
+#define FDOSMPHBASEOBJECTCOLLECTION_H		1
+//
+// Copyright (C) 2004-2006  Autodesk, Inc.
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <Sm/Ph/../NamedCollection.h>
+#include <Sm/Ph/BaseObject.h>
+
+// Represents a collection of Table Objects.
+
+class FdoSmPhBaseObjectCollection : public FdoSmNamedCollection<FdoSmPhBaseObject>
+{
+public:
+	FdoSmPhBaseObjectCollection(const FdoSmSchemaElement* pParent) :
+		FdoSmNamedCollection<FdoSmPhBaseObject>(pParent)
+	{}
+	~FdoSmPhBaseObjectCollection(void) {}
+
+protected:
+    /// unused constructor needed only to build on Linux
+    FdoSmPhBaseObjectCollection() {}
+};
+
+typedef FdoPtr<FdoSmPhBaseObjectCollection> FdoSmPhBaseObjectsP;
+
+#endif
+
+

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Column.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Column.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Column.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -185,6 +185,11 @@
     /// Returns true if this column has any not null values.
     virtual bool GetHasValues();
 
+    // Returns true if this column has the same definition (type,nullability)
+    // as the given column.
+    // Subclasses must extend this function if more definition attributes need to be checked.
+    virtual bool DefinitionEquals( FdoPtr<FdoSmPhColumn> otherColumn );
+
 // TODO:
 //    void ChangeAssociatedSpatialContext();
 

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnDecimal.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnDecimal.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnDecimal.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -68,6 +68,10 @@
         return FdoStringP::Format( L"%ls (%d, %d)", (FdoString*) GetTypeName(), GetLength(), GetScale() );
     }
 
+    // Returns true if this column has the same definition (type,length,scale,nullability)
+    // as the given column.
+    virtual bool DefinitionEquals( FdoSmPhColumnP otherColumn );
+
 protected:
     /// unused constructor needed only to build on Linux
     FdoSmPhColumnDecimal() {}

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnGeom.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnGeom.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnGeom.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -138,6 +138,11 @@
 	{
 		return 0;
 	}
+
+    // Returns true if this column has the same definition (type,dimensionality,srid,nullability)
+    // as the given column.
+    virtual bool DefinitionEquals( FdoSmPhColumnP otherColumn );
+
 protected:
 
     // unused constructor needed only to build on Linux

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnVarlen.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnVarlen.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/ColumnVarlen.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -48,6 +48,10 @@
         );
     }
 
+    // Returns true if this column has the same definition (type,length,nullability)
+    // as the given column.
+    virtual bool DefinitionEquals( FdoSmPhColumnP otherColumn );
+
 protected:
     /// unused constructor needed only to build on Linux
     FdoSmPhColumnVarlen() {}
@@ -66,6 +70,8 @@
 	int mLength;
 };
 
+typedef FdoPtr<FdoSmPhColumnVarlen> FdoSmPhColumnVarlenP;
+
 #endif
 
 

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Database.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Database.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Database.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -69,6 +69,11 @@
     /// Get a read-write smart pointer, throws FdoSchemaException if owner not in database
     FdoSmPhOwnerP GetOwner(FdoStringP owner);
 
+    // Get a currently cached owner at the given 0-based index.
+    // Returns NULL if the index is out of range.
+    // This function does not add owners to the cache.
+    FdoSmPhOwnerP GetCachedOwner(FdoInt32 idx);
+
     /// Create a new owner.
     virtual FdoSmPhOwnerP CreateOwner(FdoStringP owner, bool hasMetaSchema = true );
 

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/DbObject.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/DbObject.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/DbObject.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -21,6 +21,8 @@
 #include <Sm/Ph/DbElement.h>
 #include <Sm/Ph/DbObjType.h>
 #include <Sm/Ph/ColumnCollection.h>
+#include <Sm/Ph/BaseObjectCollection.h>
+#include <Sm/Ph/FkeyCollection.h>
 #include <Sm/Ph/ColumnBLOB.h>
 #include <Sm/Ph/ColumnChar.h>
 #include <Sm/Ph/ColumnDate.h>
@@ -37,6 +39,10 @@
 
 class FdoSmPhReader;
 class FdoSmPhTableColumnReader;
+class FdoSmPhRdBaseObjectReader;
+class FdoSmPhRdPkeyReader;
+class FdoSmPhRdFkeyReader;
+class FdoSmPhTableComponentReader;
 class FdoSmPhTableDependencyReader;
 
 // some constants
@@ -60,6 +66,14 @@
     const FdoSmPhColumnCollection* RefColumns() const;
     FdoSmPhColumnsP GetColumns();
 
+    /// Returns all the primary key columns in this database object.
+    const FdoSmPhColumnCollection* RefPkeyColumns() const;
+    FdoSmPhColumnsP GetPkeyColumns();
+
+    /// Returns all foreign keys for which this database object is the foreign "table"
+    const FdoSmPhFkeyCollection* RefFkeysUp() const;
+    FdoSmPhFkeysP GetFkeysUp();
+
     /// Returns all the attribute dependencies (from F_AttributeDependencies)
     /// where this database object is the primary key "table".	
     const FdoSmPhDependencyCollection* GetDependenciesDown() const;
@@ -68,16 +82,58 @@
     /// where this databaseobject is the foreign key "table".	
     const FdoSmPhDependencyCollection* GetDependenciesUp() const;
 
-    // Gets the lowest root object if this object is based on
-    // a root object. Returns this if not based on a root object.
+    /// Returns the database object's best identity columns.
+    /// These are the primary key columns if the database object has a primary key.
+    /// If the object has no primary key but it has a root object then the best identity
+    /// for the root object (whose columns are all present in this object) is returned. 
+    /// Typically, a view may have a table or another view as its root object.
+    /// NULL is returned if the database object has no identity and none can be derived
+    /// from its root object. 
+    FdoSmPhColumnsP GetBestIdentity();
+    
+    /// Supporting function for previous GetBestIdentity() function. 
+    /// Returns the database object's best identity columns where all columns are in the
+    /// given database object. The given database object is usually one that has this 
+    /// object as its base. 
+    /// If there is no best identity on this database object, its root object is not checked.
+    /// NULL is returned if the database object has no identity suitable for the given object.
+    virtual FdoSmPhColumnsP GetBestIdentity( FdoPtr<FdoSmPhDbObject> dbObject );
+
+    /// Returns the name of this database object's primary key
+	FdoStringP GetPkeyName() const;
+
+    /// Get the root database object. A root object is a base object for which identity 
+    /// can be derived. If this object has exactly one base object then the 
+    /// base object is returned as the root object. If this object has multiple base objects then
+    /// the root object is considered ambiguous and NULL is returned. The reason for this is 
+    /// that if we can't derive the best identity from the base objects when there are 
+    /// more than one of them. 
+    const FdoSmPhDbObject* RefRootObject() const;
+    FdoPtr<FdoSmPhDbObject> GetRootObject();
+
+    /// Get the lowest root object (The one at the top of the root object chain).
     virtual FdoPtr<FdoSmPhDbObject> GetLowestRootObject();
 
+    /// Get the root object name. Returns L"" if this object has no root object.
+    FdoStringP GetRootObjectName() const;
+
+    /// Get the root object owner name. Returns L"" if this object has no root object.
+    FdoStringP GetRootOwner() const;
+
+    /// Get the root object's database name. Returns L"" if this object has no root object.
+    FdoStringP GetRootDatabase() const;
+
     /// Returns the name of the containing database.
     FdoStringP GetDatabase() const
     {
         return GetParent()->GetParent()->GetName();
     }
 
+    /// Returns all base objects for this object. A base object is a object from which
+    /// this object is derived (e.g. a view can be based on one or more tables or other views)
+    const FdoSmPhBaseObjectCollection* RefBaseObjects() const;
+    FdoSmPhBaseObjectsP GetBaseObjects();
+
     /// Returns the name of the containing owner (physical schema).
     FdoStringP GetOwner() const
     {
@@ -121,6 +177,13 @@
     /// Returns NULL when size is 0.
 	virtual const FdoLockType* GetLockTypes(FdoInt32& size) const;
 
+    // Returns true if the given unique key has the same columns as the primary key.
+    FdoBoolean IsUkeyPkey( FdoSmPhColumnsP ukeyColumns );
+
+    // Returns true if this database object has all of the given columns. The columns
+    // must match by both name and definition.
+    FdoBoolean HasColumns( FdoSmPhColumnsP columns );
+
     /// The following create various types of columns. See the constructor
     /// declarations of these column types for parameter descriptions.
     //
@@ -236,19 +299,55 @@
         bool bAttach = true
 	);
 
+    /// Add a foreign key to this database object
+    FdoSmPhFkeyP CreateFkey(
+        FdoStringP name, 
+        FdoStringP pkeyTableName,
+        FdoStringP pkeyTableOwner = L""
+    );
+
+    /// Commit modifications
+    /// Ensures that root object is commit before this object.
+    virtual void Commit( bool fromParent = false, bool isBeforeParent = false );
+
     /// Get list of columns as references into a string collection
     virtual FdoStringsP GetRefColsSql();
 
     // Generate key column SQL clauses for the given columns.
     virtual FdoStringsP GetKeyColsSql( FdoSmPhColumnCollection* columns );
 
+    /// Get SQL for creating primary key on new database object
+    FdoStringP GetAddPkeySql();
+
+    /// Sets the primary key name for this database object.
+    /// Can only be called for new database objects.
+    virtual void SetPkeyName( FdoStringP pkeyName );
+
+    /// Add a column to the primary key.
+	void AddPkeyCol(FdoStringP columnName );
+
     // Load this object's columns from the given reader
     virtual void CacheColumns( FdoPtr<FdoSmPhRdColumnReader> rdr );
 
+    // Load this object's columns from the given reader
+    virtual void CacheBaseObjects( FdoPtr<FdoSmPhRdBaseObjectReader> rdr );
+
+    // Load this object's primary key from the given reader
+    virtual void CachePkeys( FdoPtr<FdoSmPhRdPkeyReader> rdr );
+
+    // Load this objects's foreign keys from the given reader
+    virtual void CacheFkeys( FdoPtr<FdoSmPhRdFkeyReader> rdr );
+
     // Load this object's "up" dependencies from the given reader.
     // "Up" dependencies are the ones where this object is the FK table.
     virtual void CacheDependenciesUp( FdoPtr<FdoSmPhDependencyReader> rdr );
 
+    /// Commit modifications to foreign keys.
+    virtual void CommitFkeys( bool isBeforeParent );
+
+    /// Drops this database object whether or not it has data.
+    void ForceDelete();
+
     /// Gather all errors for this element and child elements into a chain of exceptions.
     /// Adds each error as an exception, to the given exception chain and returns
     /// the chain.
@@ -285,15 +384,52 @@
 
     virtual void SetLockingMode( FdoLtLockModeType mode );
 
+    // Sets the root object for this database object.
+    // Pass in NULL to remove current root object relationship.
+    // Discards any previously set base objects.
+    void SetRootObject( FdoPtr<FdoSmPhDbObject> rootObject );
+
     /// Loads column list for existing database object
     void LoadColumns();
     void LoadColumns( FdoPtr<FdoSmPhTableColumnReader> colRdr );
-    
+
+    /// Loads objects that this object is based on, if not yet loaded. 
+    void LoadBaseObjects();
+    void LoadBaseObjects( FdoPtr<FdoSmPhTableComponentReader> baseObjRdr );
+
+    /// Load Primary Key if not yet loaded
+    void LoadPkeys();
+    void LoadPkeys( FdoPtr<FdoSmPhReader> pkeyRdr, bool isSkipAdd = false );
+
+    /// Load Foreign Keys if not yet loaded
+    void LoadFkeys();
+    void LoadFkeys( FdoPtr<FdoSmPhReader> fkeyRdr, bool isSkipAdd );
+
+    // Create new base object group reader
+    virtual FdoPtr<FdoSmPhTableComponentReader> NewTableBaseReader( FdoPtr<FdoSmPhRdBaseObjectReader> rdr );
+
     /// Create a column from a column reader and add it to this database object
     virtual FdoSmPhColumnP NewColumn(
         FdoPtr<FdoSmPhRdColumnReader> colRdr
     );
 
+    /// Create a base object reference from a base object reader
+    virtual FdoSmPhBaseObjectP NewBaseObject(
+        FdoPtr<FdoSmPhTableComponentReader> baseObjRdr
+    );
+
+    // Create a base object reference specified by qualified name
+    virtual FdoSmPhBaseObjectP NewBaseObject(
+        FdoStringP name,
+        FdoStringP ownerName,
+        FdoStringP databaseName
+    );
+
+    // Create a base object reference to the given database object.
+    virtual FdoSmPhBaseObjectP NewBaseObject(
+        FdoPtr<FdoSmPhDbObject> dbObject
+    );
+
     /// Various functions that each provider must override to customize the 
     /// creation of various types of columns.
     virtual FdoSmPhColumnP NewColumnBLOB(
@@ -420,9 +556,23 @@
         FdoSmPhRdColumnReader* colRdr = NULL
 	) = 0;
 
-    /// Create a reader to get the columns for this database object.
+    /// Foreign key object creator
+    virtual FdoSmPhFkeyP NewFkey(
+        FdoStringP name, 
+        FdoStringP pkeyTableName,
+        FdoStringP pkeyTableOwner,
+		FdoSchemaElementState elementState = FdoSchemaElementState_Added
+    );
+
+    /// Readers for Columns, Base Objects, Primary Key, and Foreign Keys
     virtual FdoPtr<FdoSmPhRdColumnReader> CreateColumnReader() = 0;
+    virtual FdoPtr<FdoSmPhRdBaseObjectReader> CreateBaseObjectReader() const;
+    virtual FdoPtr<FdoSmPhRdPkeyReader> CreatePkeyReader() const;
+    virtual FdoPtr<FdoSmPhRdFkeyReader> CreateFkeyReader() const;
 
+    /// Autogenerate a unique primary key name for this database object.
+	virtual FdoStringP GenPkeyName();
+
     /// Records this database object as having been updated so that modification 
     /// can be undone on rollback.
     virtual void UpdRollbackCache();
@@ -430,9 +580,25 @@
     /// Remove from parent Owner's collection.
     virtual void Discard();
 
+    virtual void AddPkeyColumnError(FdoStringP columnName);
+
+    FdoSmPhColumnsP mPkeyColumns;
+
 private:
     void LoadDependencies( bool up );
     void LoadDependenciesUp( FdoPtr<FdoSmPhTableDependencyReader> depRdr );
+
+    // Create new foreign key group reader
+    virtual FdoPtr<FdoSmPhTableComponentReader> NewTableFkeyReader( FdoPtr<FdoSmPhRdFkeyReader> rdr );
+    
+    // Create new primary key group reader
+    virtual FdoPtr<FdoSmPhTableComponentReader> NewTablePkeyReader( FdoPtr<FdoSmPhRdPkeyReader> rdr );
+
+    // Check for loop when walking up root objects. 
+    // Level is incremented each time this function is called. 
+    // Caller is responsible for initializing level to 1 before the first call.
+    bool CheckRootObjectLoop( FdoInt32& level );
+
 /* TODO:
     virtual void Finalize();
 
@@ -442,10 +608,15 @@
 	void AddNotNullColError(FdoStringP columnName);
     void AddColumnNoexistError( FdoStringP indexName, FdoStringP columnName  );
 */
-
+    void AddFkeyColumnError(FdoStringP columnName);
+    void AddCreateFkeyError(FdoStringP fkeyName);
+    
     /// Column list for this database object.
 	FdoSmPhColumnsP mColumns;
 
+    // Foreign key list.
+    FdoSmPhFkeysP mFkeysUp;
+
 	FdoPtr<FdoSmPhDependencyCollection> mDependenciesDown;
 	FdoPtr<FdoSmPhDependencyCollection> mDependenciesUp;
 
@@ -455,6 +626,10 @@
     /// Supported Lock types.
 	FdoInt32 mLockTypeCount;
 	FdoLockType* mLockTypes;
+
+    FdoStringP mPkeyName;
+
+    FdoPtr<FdoSmPhBaseObjectCollection> mBaseObjects;
 };
 
 typedef FdoPtr<FdoSmPhDbObject> FdoSmPhDbObjectP;

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Mgr.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Mgr.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Mgr.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -289,6 +289,10 @@
     /// Get read-write pointer to database, Throws exception if database not found
     FdoSmPhDatabaseP GetDatabase(FdoStringP database = L"");
 
+    // Get a currently cached database at the given 0-based index.
+    // Returns NULL if the index is out of range.
+    // This function does not add databases to the cache.
+    FdoSmPhDatabaseP GetCachedDatabase(FdoInt32 idx);
 
     /// Get read-write pointer to an owner, NULL if owner not found
     FdoSmPhOwnerP FindOwner(FdoStringP ownerName = L"", FdoStringP database = L"", bool caseSensitive = true);

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Owner.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Owner.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Owner.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -36,6 +36,7 @@
 class FdoSmPhRdCoordSysReader;
 class FdoSmPhRdConstraintReader;
 class FdoSmPhRdColumnReader;
+class FdoSmPhRdBaseObjectReader;
 class FdoSmPhRdTableJoin;
 class FdoSmPhRdSpatialContextReader;
 
@@ -110,6 +111,11 @@
     /// as a read-write smart pointer (exception thrown if not found)
     FdoSmPhDbObjectP GetDbObject(FdoStringP dbObject);
 
+    // Get a currently cached database object at the given 0-based index.
+    // Returns NULL if the index is out of range.
+    // This function does not add database objects to the cache.
+    FdoSmPhDbObjectP GetCachedDbObject(FdoInt32 idx);
+
     // Gets the physical spatial contexts for this owner. 
     // it contains the spatial contexts reverse-engineered from the RDBMS.
     FdoSmPhSpatialContextsP GetSpatialContexts();
@@ -179,6 +185,9 @@
     // Create a reader to get all columns for this owner and join
     virtual FdoPtr<FdoSmPhRdColumnReader> CreateColumnReader( FdoPtr<FdoSmPhRdTableJoin> join ) const;
 
+    // Create a reader to get all base object references for this owner
+    virtual FdoPtr<FdoSmPhRdBaseObjectReader> CreateBaseObjectReader() const;
+
     /// Create a new table. Table is not posted to the datastore until its Commit() function
     /// is called.
     FdoSmPhTableP CreateTable(

Added: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/BaseObjectReader.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/BaseObjectReader.h	                        (rev 0)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/BaseObjectReader.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -0,0 +1,67 @@
+#ifndef FDOSMPHRDBASEOBJECTREADER_H
+#define FDOSMPHRDBASEOBJECTREADER_H		1
+/*
+ * Copyright (C) 2004-2006  Autodesk, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser
+ * General Public License as published by the Free Software Foundation.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+#include <Sm/Ph/Reader.h>
+#include <Sm/Ph/RowCollection.h>
+#include <Sm/Ph/DbObjType.h>
+#include <Sm/Ph/Mgr.h>
+
+// This abstract class reads base objects. Each provider must 
+// provide its own implementing class.
+// A base object is a database object that another database object
+// depends on. Typically a view can be based on a table or another view.
+
+class FdoSmPhRdBaseObjectReader : public FdoSmPhReader
+{
+public:
+
+protected:
+    //Unused constructor needed only to build on Linux
+    FdoSmPhRdBaseObjectReader() {}
+
+    // Creates a reader for all base object references in the given owner
+	//
+	FdoSmPhRdBaseObjectReader(
+        FdoSmPhReaderP reader,      // inner reader created by implementing class
+        FdoSmPhOwnerP owner        // get the base objects for this owner
+    );
+
+    // Creates a reader for all base objects for a given database object
+	//
+	FdoSmPhRdBaseObjectReader(
+        FdoSmPhReaderP reader,      // inner reader created by implementing class
+        FdoSmPhDbObjectP dbObject       // get the base objects for this database object
+    );
+
+    /// Deactivates the reader.
+	virtual ~FdoSmPhRdBaseObjectReader(void);
+
+    /// Creates a set of rows describing the fields for this
+    /// reader. There is one field per base object attribute.
+    virtual FdoSmPhRowsP MakeRows( FdoSmPhMgrP mgr );
+
+    FdoSmPhOwnerP mOwner;
+    FdoSmPhDbObjectP mDbObject;
+};
+
+typedef FdoPtr<FdoSmPhRdBaseObjectReader> FdoSmPhRdBaseObjectReaderP;
+
+#endif
+
+

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/ClassReader.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/ClassReader.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/ClassReader.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -37,7 +37,8 @@
         FdoStringP schemaName,      // name of Feature Schema that will contain the classes
         FdoStringP className,      // name of Feature class 
         FdoSmPhMgrP mgr,            // Physical Schema Manager
-        FdoBoolean keyedOnly = true,// If true, skip tables without key.
+        FdoBoolean classifyDefaultTypes = true,// If true, classify only types of objects that are classified by default
+                                               // If false, classify all types of object than can be classified
         FdoStringP database = L"",  // Database where RDBMS schema resides (current connection by default)
         FdoStringP owner = L""      // the RDBMS schema (defaults to current schema)
     );
@@ -54,8 +55,24 @@
 
     bool IsOrdinate(FdoSmPhColumnP column);
 
-    virtual FdoStringP ClassifyObject( FdoStringP objectName, FdoSmPhDbObjType objectType );
+    // The following two functions control which database objects are reverse-engineered
+    // into FDO Class Definitions:
 
+    // Returns true if the type for the given object is one for which an FDO class definition
+    // can be generated. 
+    // Returns true if the object is a table or view. Sub-classes can override this function
+    // to allow RDBMS-specific types to be classified.
+    // The classifyDefaultTypes parameter has no effect in this function. However, specific 
+    // RDBMS's might have some types that can be classified but are not classified by default.
+    // When classifyDefaultTypes is true then this function must return true only for types
+    // that can be classified by default. 
+    // 
+    virtual bool ClassifyObjectType( FdoSmPhDbObjectP dbObject, FdoBoolean classifyDefaultTypes );
+
+    // Returns true if the given database object's corresponding class is in the Feature Schema
+    // for this class reader. 
+    // No checking is done against the object's type. This is performed by ClassifyObjectType()
+    virtual FdoStringP ClassifyObject( FdoSmPhDbObjectP dbObject );
     // Find the main geometric property for the class from the given column collection.
     // Returns the main geometric property, L"" if none could be determined
     // (non geometric properties, or there was a tie for best main geometry).
@@ -64,9 +81,16 @@
     virtual FdoStringP FindGeometryProperty( FdoSmPhColumnsP cols,  bool& hasGeom );
 
 private:
+    // This function is now obsolete; override or extend ClassifyObject( FdoSmPhDbObjectP ) instead.
+#ifdef _WIN32
+    virtual FdoStringP ClassifyObject( FdoStringP objectName, FdoSmPhDbObjType objectType ) sealed;
+#else
+    virtual FdoStringP ClassifyObject( FdoStringP objectName, FdoSmPhDbObjType objectType );
+#endif
 
+
     FdoStringP mSchemaName;
-    FdoBoolean mKeyedOnly;
+    FdoBoolean mClassifyDefaultTypes;
 
     FdoSmPhOwnerP mOwner;
     FdoSmPhDbObjectsP mDbObjects;

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/PropertyReader.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/PropertyReader.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Rd/PropertyReader.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -107,7 +107,6 @@
     void AddUsedName( FdoStringP propName );
 
     FdoSmPhDbObjectP mDbObject;
-    FdoSmPhTable* mpTable;
     FdoSmPhColumnsP mIdCols;
     FdoDictionaryP mUsedNames;
     int mFkeyCount;

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Table.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Table.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/Table.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -23,7 +23,6 @@
 #endif
 
 #include <Sm/Ph/DbObject.h>
-#include <Sm/Ph/FkeyCollection.h>
 #include <Sm/Ph/IndexCollection.h>
 #include <Sm/Ph/ColumnBatchCollection.h>
 #include <Sm/Ph/CheckConstraintCollection.h>
@@ -31,8 +30,6 @@
 class FdoSmPhMgr;
 class FdoSmPhOwner;
 class FdoSmPhReader;
-class FdoSmPhRdPkeyReader;
-class FdoSmPhRdFkeyReader;
 class FdoSmPhRdConstraintReader;
 class FdoSmPhRdIndexReader;
 class FdoSmPhTableComponentReader;
@@ -48,10 +45,6 @@
     /// support adding not-null columns.
     virtual bool SupportsAddNotNullColumn() const;
 
-    /// Returns all the primary key columns in this table.
-    const FdoSmPhColumnCollection* RefPkeyColumns() const;
-    FdoSmPhColumnsP GetPkeyColumns();
-
     /// Returns all the unique columns in this table.
     const FdoSmPhBatchColumnCollection* RefUkeyColumns() const;
     FdoSmPhBatchColumnsP GetUkeyColumns();
@@ -70,27 +63,18 @@
     const FdoSmPhIndexCollection* RefIndexes() const;
     FdoSmPhIndexesP GetIndexes();
 
-    /// Returns the table's best identity columns.
+    /// Returns the table's best identity columns, where all columns are in the given
+    /// database object (the given object is typically a view based on this table).
     /// These are the primary key columns if the table has a primary key.
     /// Otherwise, the columns for the table's lightest unique index are returned.
     /// NULL is returned if the table has no identity.
-    FdoSmPhColumnsP GetBestIdentity();
+    virtual FdoSmPhColumnsP GetBestIdentity( FdoSmPhDbObjectP dbObject );
     
-    /// Returns all foreign keys for which this table is the foreign table
-    const FdoSmPhFkeyCollection* RefFkeysUp() const;
-    FdoSmPhFkeysP GetFkeysUp();
-
-    /// Returns the name of this table's primary key
-	FdoStringP GetPkeyName() const;
-
     /// Returns an array of all types of locking supported on this Database Object.
     /// size is set to the size of the array.
     /// Returns NULL when size is 0.
 	virtual const FdoLockType* GetLockTypes(FdoInt32& size) const;
 
-    // Returns true if the given unique key has the same columns as the primary key.
-    FdoBoolean IsUkeyPkey( FdoSmPhColumnsP ukeyColumns );
-
     /// Get SQL "create table" statement.
     virtual FdoStringP GetAddSql();
 
@@ -115,9 +99,6 @@
 	/// Get SQL clause for adding a constraint
 	virtual FdoStringP GetAddConstraintSql(FdoStringP constraint);
 
-    /// Get SQL for creating primary key on new table
-    FdoStringP GetAddPkeySql();
-
     /// Get SQL for creating UNIQUE constraints on new table
     FdoStringP GetAddUkeysSql();
 
@@ -138,17 +119,10 @@
     /// Can only be changed on new tables.
     virtual void SetLtMode( FdoLtLockModeType mode );
 
-    /// Sets the primary key name for this table.
-    /// Can only be called for new tables.
-    virtual void SetPkeyName( FdoStringP pkeyName );
-
     /// Set the locking mode.
     /// Can only be changed on new tables.
     virtual void SetLockingMode( FdoLtLockModeType mode );
 
-    /// Add a column to the primary key.
-	void AddPkeyCol(FdoStringP columnName );
-
     /// Add a column to a collection of unique keys 
 	void AddUkeyCol(int uCollNum, FdoStringP columnName );
 
@@ -167,13 +141,6 @@
         bool isUnique
     );
 
-    /// Add a foreign key to this table
-    FdoSmPhFkeyP CreateFkey(
-        FdoStringP name, 
-        FdoStringP pkeyTableName,
-        FdoStringP pkeyTableOwner = L""
-    );
-
 	/// Return the list of constraints marked for drop
 	FdoStringsP	GetDeletedConstraints();
 
@@ -181,33 +148,21 @@
     /// deleting it from the datastore.
     void DiscardIndex( FdoSmPhIndex* index );
 
-    /// Commit modifications to foreign keys.
-    virtual void CommitFkeys( bool isBeforeParent );
-
     /// Deletes all rows from this table.
     virtual void ClearRows() = 0;
 
     /// Set the modification state of this table.
 	virtual void SetElementState(FdoSchemaElementState elementState);
 
-    /// Drops the table whether or not it has data.
-    void ForceDelete();
-
     // Load this table's unique constraints from the given reader
     virtual void CacheUkeys( FdoPtr<FdoSmPhRdConstraintReader> rdr );
 
     // Load this table's check constraints from the given reader
     virtual void CacheCkeys( FdoPtr<FdoSmPhRdConstraintReader> rdr );
 
-    // Load this table's foreign keys from the given reader
-    virtual void CacheFkeys( FdoPtr<FdoSmPhRdFkeyReader> rdr );
-
     // Load this table's indexes from the given reader
     virtual void CacheIndexes( FdoPtr<FdoSmPhRdIndexReader> rdr );
 
-    // Load this table's primary key from the given reader
-    virtual void CachePkeys( FdoPtr<FdoSmPhRdPkeyReader> rdr );
-
     /// Gather all errors for this element and child elements into a chain of exceptions.
     /// Adds each error as an exception, to the given exception chain and returns
     /// the chain.
@@ -246,10 +201,8 @@
         FdoPtr<FdoSmPhTableIndexReader> rdr
     );
 
-    /// Readers for Primary Key, Constraints, Foreign Keys and Indexes.
+    /// Readers for Constraints and Indexes.
     /// All have provider-specific implementations
-    virtual FdoPtr<FdoSmPhRdPkeyReader> CreatePkeyReader() const = 0;
-    virtual FdoPtr<FdoSmPhRdFkeyReader> CreateFkeyReader() const = 0;
 	virtual FdoPtr<FdoSmPhRdConstraintReader> CreateConstraintReader(FdoString* type) const = 0;
     virtual FdoPtr<FdoSmPhRdIndexReader> CreateIndexReader() const = 0;
 
@@ -267,14 +220,6 @@
 		FdoSchemaElementState elementState = FdoSchemaElementState_Added
     ) = 0;
 
-    /// Foreign key object creator
-    virtual FdoSmPhFkeyP NewFkey(
-        FdoStringP name, 
-        FdoStringP pkeyTableName,
-        FdoStringP pkeyTableOwner,
-		FdoSchemaElementState elementState = FdoSchemaElementState_Added
-    ) = 0;
-
     /// Commit modifications to child objects
     virtual void CommitChildren( bool isBeforeParent );
 
@@ -287,9 +232,6 @@
 	/// Commit new added Check constraints
 	virtual void CommitCConstraints( bool isBeforeParent );
 
-    /// Autogenerate a unique primary key name for this table.
-	virtual FdoStringP GenPkeyName();
-
     /// Column update functions, each provider must implement.
     virtual bool AddColumn( FdoSmPhColumnP column ) = 0;
     virtual bool ModifyColumn( FdoSmPhColumnP column ) = 0;
@@ -301,19 +243,9 @@
 	/// Add a constrait given the fully qualified string.
 	virtual bool AddConstraint( FdoStringP constraint ) = 0;
 
-    void LoadPkeys( FdoPtr<FdoSmPhReader> pkeyRdr, bool isSkipAdd = false );
-
-    virtual void AddPkeyColumnError(FdoStringP columnName);
     virtual void AddIndexColumnError(FdoStringP columnName);
 
-    FdoSmPhColumnsP mPkeyColumns;
-
 private:
-    /// Load Primary Key if not yet loaded
-    void LoadPkeys();
-    /// Load Foreign Keys if not yet loaded
-    void LoadFkeys();
-    void LoadFkeys( FdoPtr<FdoSmPhReader> fkeyRdr, bool isSkipAdd );
     /// Load Unique Keys if not yet loaded
 	void LoadUkeys();
 	void LoadUkeys( FdoPtr<FdoSmPhReader> ukeyRdr, bool isSkipAdd );
@@ -331,16 +263,9 @@
     // Create new check constraint group reader
     virtual FdoPtr<FdoSmPhTableComponentReader> NewTableCkeyReader( FdoPtr<FdoSmPhRdConstraintReader> rdr );
 
-    // Create new foreign key group reader
-    virtual FdoPtr<FdoSmPhTableComponentReader> NewTableFkeyReader( FdoPtr<FdoSmPhRdFkeyReader> rdr );
-
     // Create new index group reader
     virtual FdoPtr<FdoSmPhTableIndexReader> NewTableIndexReader( FdoPtr<FdoSmPhRdIndexReader> rdr );
 
-    // Create new primary key group reader
-    virtual FdoPtr<FdoSmPhTableComponentReader> NewTablePkeyReader( FdoPtr<FdoSmPhRdPkeyReader> rdr );
-
-    void AddFkeyColumnError(FdoStringP columnName);
 	void AddUkeyColumnError(FdoStringP columnName);
 	void AddUkeyError(FdoStringP columnNames);
     void AddCkeyColumnError(FdoStringP columnName);
@@ -351,11 +276,8 @@
 	FdoSmPhCheckConstraintsP	mCkeysCollection;
 	FdoStringsP					mDeletedConstraints;
 
-    FdoSmPhFkeysP mFkeysUp;
-
     FdoSmPhIndexesP mIndexes;
 
-	FdoStringP mPkeyName;
 };
 
 typedef FdoPtr<FdoSmPhTable> FdoSmPhTableP;

Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Ph/View.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Ph/View.h	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Ph/View.h	2007-02-15 17:36:56 UTC (rev 2519)
@@ -32,30 +32,6 @@
 class FdoSmPhView : virtual public FdoSmPhDbObject
 {
 public:
-    /// Get the underlying table if this is a view over a foreign table
-    const FdoSmPhDbObject* RefRootObject() const;
-    FdoSmPhDbObjectP GetRootObject();
-
-    virtual FdoSmPhDbObjectP GetLowestRootObject();
-
-    /// Get the underlying table name if this is a view over a foreign table
-    FdoStringP GetRootObjectName() const
-    {
-        return mRootObjectName;
-    }
-
-    /// Get the underlying table owner if this is a view over a foreign table
-    FdoStringP GetRootOwner() const
-    {
-        return mRootOwner;
-    }
-
-    /// Get the underlying table database if this is a view over a foreign table
-    FdoStringP GetRootDatabase() const
-    {
-        return mRootDatabase;
-    }
-
     void SetRootObject( FdoSmPhDbObjectP rootObject );
 
     /// Serialize the table to an XML file.
@@ -104,12 +80,6 @@
     virtual FdoStringP GetRootNameSql() = 0;
 
 private:
-    /// The following three are only set when this "table" is actually a view.
-    FdoStringP mRootObjectName;
-    FdoStringP mRootDatabase;
-    FdoStringP mRootOwner;
-
-    FdoSmPhDbObjectP mRootObject;
 };
 
 typedef FdoPtr<FdoSmPhView> FdoSmPhViewP;

Modified: trunk/Utilities/SchemaMgr/LogicalPhysical.vcproj
===================================================================
--- trunk/Utilities/SchemaMgr/LogicalPhysical.vcproj	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/LogicalPhysical.vcproj	2007-02-15 17:36:56 UTC (rev 2519)
@@ -41,6 +41,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm110"
 				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(FDO)\Unmanaged\Inc&quot;;&quot;$(FDO)\Unmanaged&quot;;Inc;&quot;$(FDOUTILITIES)\Common\Inc&quot;"
 				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_AFXDLL"

Modified: trunk/Utilities/SchemaMgr/Nls/SmMessage.mc
===================================================================
--- trunk/Utilities/SchemaMgr/Nls/SmMessage.mc	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Nls/SmMessage.mc	2007-02-15 17:36:56 UTC (rev 2519)
@@ -161,6 +161,11 @@
 Language=English
 Class '%1$ls' uses Base table mapping; Cannot include base property '%2$ls' in unique constraint
 .
+MessageId=2235
+SymbolicName=FDOSM_30
+Language=English
+Cannot add foreign key '%1$ls' to '%2$ls'; adding foreign key to this type of object is not supported
+.
 MessageId=2327
 SymbolicName=FDOSM_122
 Language=English

Modified: trunk/Utilities/SchemaMgr/Physical.vcproj
===================================================================
--- trunk/Utilities/SchemaMgr/Physical.vcproj	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Physical.vcproj	2007-02-15 17:36:56 UTC (rev 2519)
@@ -171,6 +171,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Src\Sm\Ph\BaseObject.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\Src\Sm\Ph\CharacterSet.cpp"
 				>
 			</File>
@@ -219,11 +223,11 @@
 				>
 			</File>
 			<File
-				RelativePath=".\src\Sm\Ph\ColumnList.cpp"
+				RelativePath=".\Src\Sm\Ph\ColumnList.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\Src\Sm\Ph\ColumnList.cpp"
+				RelativePath=".\src\Sm\Ph\ColumnList.cpp"
 				>
 			</File>
 			<File
@@ -446,6 +450,10 @@
 					</FileConfiguration>
 				</File>
 				<File
+					RelativePath=".\Src\Sm\Ph\Rd\BaseObjectReader.cpp"
+					>
+				</File>
+				<File
 					RelativePath=".\Src\Sm\Ph\Rd\CharacterSetReader.cpp"
 					>
 				</File>
@@ -975,6 +983,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Inc\Sm\Ph\BaseObject.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Inc\Sm\Ph\BaseObjectCollection.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Inc\Sm\Ph\CharacterSet.h"
 				>
 			</File>
@@ -1350,6 +1366,10 @@
 					>
 				</File>
 				<File
+					RelativePath=".\Inc\Sm\Ph\Rd\BaseObjectReader.h"
+					>
+				</File>
+				<File
 					RelativePath=".\Inc\Sm\Ph\Rd\CharacterSetReader.h"
 					>
 				</File>

Added: trunk/Utilities/SchemaMgr/Src/Sm/Ph/BaseObject.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/BaseObject.cpp	                        (rev 0)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/BaseObject.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2006  Autodesk, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser
+ * General Public License as published by the Free Software Foundation.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#include "stdafx.h"
+#include <Sm/Ph/DbObject.h>
+#include <Sm/Ph/Mgr.h>
+
+FdoSmPhBaseObject::FdoSmPhBaseObject(
+    FdoStringP name, 
+    FdoPtr<FdoSmPhDbObject> parent,
+    FdoStringP ownerName,
+    FdoStringP databaseName
+) : 
+    FdoSmPhDbElement(name, (FdoSmPhMgr*) NULL, parent, FdoSchemaElementState_Detached ),
+    mOwnerName(ownerName),
+    mDatabaseName(databaseName)
+{
+    if ( ownerName == L"" ) 
+        mOwnerName = parent->GetParent()->GetName();
+}
+
+FdoSmPhBaseObject::FdoSmPhBaseObject(
+    FdoPtr<FdoSmPhDbObject> dbObject,
+    FdoPtr<FdoSmPhDbObject> parent
+) : 
+    FdoSmPhDbElement(dbObject->GetName(), (FdoSmPhMgr*) NULL, parent, FdoSchemaElementState_Detached ),
+    mOwnerName(dbObject->GetParent()->GetName()),
+    mDatabaseName(dbObject->GetParent()->GetParent()->GetName()),
+    mDbObject(dbObject)
+{
+}
+
+FdoSmPhBaseObject::FdoSmPhBaseObject(void)
+{
+}
+
+FdoSmPhBaseObject::~FdoSmPhBaseObject(void)
+{
+}
+
+
+const FdoSmPhDbObject* FdoSmPhBaseObject::RefDbObject() const
+{
+    FdoSmPhDbObjectP rootObject = ((FdoSmPhBaseObject*) this)->GetDbObject();
+
+    return (FdoSmPhDbObject*) rootObject;
+}
+
+FdoSmPhDbObjectP FdoSmPhBaseObject::GetDbObject()
+{
+    if ( (wcslen(GetName()) > 0) && (!mDbObject) ) 
+        mDbObject = GetManager()->FindDbObject( GetName(), GetOwnerName(), GetDatabaseName() );
+
+    return mDbObject;
+}
+
+FdoStringP FdoSmPhBaseObject::GetOwnerName() const
+{
+    return mOwnerName;
+}
+
+FdoStringP FdoSmPhBaseObject::GetDatabaseName() const
+{
+    return mDatabaseName;
+}
+

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Column.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Column.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Column.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -262,6 +262,16 @@
     return hasData;
 }
 
+bool FdoSmPhColumn::DefinitionEquals( FdoSmPhColumnP otherColumn )
+{
+    bool equals = false;
+
+    if ( (GetType() == otherColumn->GetType()) && (GetNullable() == otherColumn->GetNullable()) )
+        equals = true;
+
+    return equals;
+}
+
 void FdoSmPhColumn::SetElementState(FdoSchemaElementState elementState)
 {
     FdoSchemaElementState oldState = GetElementState();

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnDecimal.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnDecimal.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnDecimal.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -28,3 +28,20 @@
 {
 }
 
+bool FdoSmPhColumnDecimal::DefinitionEquals( FdoSmPhColumnP otherColumn )
+{
+    bool equals = FdoSmPhColumnVarlen::DefinitionEquals( otherColumn );
+
+    if ( equals ) {
+        equals = false;
+
+        FdoSmPhColumnDecimalP otherDecimalColumn = otherColumn->SmartCast<FdoSmPhColumnDecimal>();
+
+        if ( otherDecimalColumn && (GetScale() == otherDecimalColumn->GetScale()) ) 
+            equals = true;
+    }
+
+    return equals;
+}
+
+

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnGeom.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnGeom.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnGeom.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -101,6 +101,25 @@
     mSpatialIndex = NULL;
 }
 
+bool FdoSmPhColumnGeom::DefinitionEquals( FdoSmPhColumnP otherColumn )
+{
+    bool equals = FdoSmPhColumn::DefinitionEquals( otherColumn );
+
+    if ( equals ) {
+        equals = false;
+
+        FdoSmPhColumnGeomP otherGeomColumn = otherColumn->SmartCast<FdoSmPhColumnGeom>();
+
+        if ( otherGeomColumn &&
+             (GetDimensionality() == otherGeomColumn->GetDimensionality()) &&
+             (GetSRID() == otherGeomColumn->GetSRID())
+        ) 
+            equals = true;
+    }
+
+    return equals;
+}
+
 void FdoSmPhColumnGeom::SetSpatialIndex( FdoSmPhSpatialIndexP spatialIndex )
 {
     FdoSmPhTableP table = 

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnVarlen.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnVarlen.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/ColumnVarlen.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -40,3 +40,19 @@
     return 1;
 }
 
+bool FdoSmPhColumnVarlen::DefinitionEquals( FdoSmPhColumnP otherColumn )
+{
+    bool equals = FdoSmPhColumn::DefinitionEquals( otherColumn );
+
+    if ( equals ) {
+        equals = false;
+
+        FdoSmPhColumnVarlenP otherVarColumn = otherColumn->SmartCast<FdoSmPhColumnVarlen>();
+
+        if ( otherVarColumn && (GetLength() == otherVarColumn->GetLength()) ) 
+            equals = true;
+    }
+
+    return equals;
+}
+

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Database.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Database.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Database.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -85,6 +85,17 @@
     return(pOwner);
 }
 
+FdoSmPhOwnerP FdoSmPhDatabase::GetCachedOwner(FdoInt32 idx)
+{
+    FdoSmPhOwnerP owner;
+    FdoSmPhOwnersP owners = GetOwners();
+
+    if ( (idx >= 0) && (idx < owners->GetCount()) ) 
+        owner = owners->GetItem( idx );
+
+    return owner;
+}
+
 const FdoSmPhCharacterSet* FdoSmPhDatabase::RefCharacterSet(FdoStringP characterSetName) const
 {
     return (FdoSmPhCharacterSet*) ((FdoSmPhDatabase*) this)->FindCharacterSet(characterSetName);

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/DbObject.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/DbObject.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/DbObject.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -23,8 +23,12 @@
 #include <Sm/Ph/DependencyCollection.h>
 #include <Sm/Ph/Rd/QueryReader.h>
 #include <Sm/Ph/Rd/ColumnReader.h>
+#include <Sm/Ph/Rd/BaseObjectReader.h>
+#include <Sm/Ph/Rd/PkeyReader.h>
+#include <Sm/Ph/Rd/FkeyReader.h>
 #include <Sm/Ph/DependencyReader.h>
 #include <Sm/Ph/TableComponentReader.h>
+#include <Sm/Error.h>
 
 FdoSmPhDbObject::FdoSmPhDbObject(
     FdoStringP name, 
@@ -59,7 +63,32 @@
 	return mColumns;
 }
 
+const FdoSmPhColumnCollection* FdoSmPhDbObject::RefPkeyColumns() const
+{
+    FdoSmPhColumnsP columns = ((FdoSmPhDbObject*) this)->GetPkeyColumns();
 
+    return (FdoSmPhColumnCollection*) columns;
+}
+
+FdoSmPhColumnsP FdoSmPhDbObject::GetPkeyColumns()
+{
+    LoadPkeys();
+
+	return mPkeyColumns;
+}
+
+const FdoSmPhFkeyCollection* FdoSmPhDbObject::RefFkeysUp() const
+{
+    return (FdoSmPhFkeyCollection*) ((FdoSmPhDbObject*) this)->GetFkeysUp();
+}
+
+FdoSmPhFkeysP FdoSmPhDbObject::GetFkeysUp()
+{
+    LoadFkeys();
+
+	return mFkeysUp;
+}
+
 const FdoSmPhDependencyCollection* FdoSmPhDbObject::GetDependenciesDown() const
 {
 	((FdoSmPhDbObject*) this)->LoadDependencies(false);
@@ -74,11 +103,148 @@
 	return (FdoSmPhDependencyCollection*) mDependenciesUp;
 }
 
+FdoSmPhColumnsP FdoSmPhDbObject::GetBestIdentity()
+{
+    FdoSmPhColumnsP bestIdentity = GetBestIdentity( (FdoSmPhDbObject*) NULL );
+
+    // Choose primary key only if present
+
+    FdoSmPhDbObjectP rootObject = FDO_SAFE_ADDREF(this);
+
+    // If this database object does not have best identity of its own, look for a 
+    // best identity from its root objects. 
+    FdoInt32 level = 1;
+    while ( bestIdentity == NULL ) {
+        rootObject = rootObject->GetRootObject();
+        if ( rootObject ) 
+            bestIdentity = rootObject->GetBestIdentity( FDO_SAFE_ADDREF(this) );
+        else
+            break;
+
+        // Give up if this object has circular root object dependencies. 
+        if ( !CheckRootObjectLoop(level) )
+            break;
+    }
+
+    return bestIdentity;
+}
+
+FdoSmPhColumnsP FdoSmPhDbObject::GetBestIdentity( FdoSmPhDbObjectP dbObject )
+{
+    FdoSmPhColumnsP bestIdentity = GetPkeyColumns();
+
+    // Choose primary key only if present
+    if ( bestIdentity->GetCount() == 0 ) {
+        bestIdentity = NULL;
+    }
+
+    if ( bestIdentity ) {
+        if ( dbObject && !dbObject->HasColumns(bestIdentity) ) 
+            bestIdentity = NULL;
+    }
+
+    return bestIdentity;
+}
+
+FdoStringP FdoSmPhDbObject::GetPkeyName() const
+{
+    // Trip a load of the primary key.
+	RefPkeyColumns();
+
+	return mPkeyName;
+}
+
+const FdoSmPhDbObject* FdoSmPhDbObject::RefRootObject() const
+{
+    FdoSmPhDbObjectP rootObject = ((FdoSmPhDbObject*) this)->GetRootObject();
+
+    return (FdoSmPhDbObject*) rootObject;
+}
+
+FdoSmPhDbObjectP FdoSmPhDbObject::GetRootObject()
+{
+    FdoSmPhDbObjectP rootObject;
+
+    FdoSmPhBaseObjectsP baseObjects = GetBaseObjects();
+
+    if ( baseObjects->GetCount() == 1 ) {
+        FdoSmPhBaseObjectP baseObject = baseObjects->GetItem(0);
+        rootObject = baseObject->GetDbObject();
+    }
+
+    return rootObject;
+}
+
 FdoSmPhDbObjectP FdoSmPhDbObject::GetLowestRootObject()
 {
-    return FDO_SAFE_ADDREF(this);
+    FdoSmPhDbObjectP rootObject = GetRootObject();
+
+    if ( rootObject ) 
+        rootObject = rootObject->GetLowestRootObject();
+    else
+        rootObject = FDO_SAFE_ADDREF(this);
+
+    return rootObject;
 }
 
+FdoStringP FdoSmPhDbObject::GetRootObjectName() const
+{
+    FdoStringP rootObjectName;
+
+    const FdoSmPhBaseObjectCollection* baseObjects = RefBaseObjects();
+
+    if ( baseObjects->GetCount() == 1 ) {
+        const FdoSmPhBaseObject* baseObject = baseObjects->RefItem(0);
+        rootObjectName = baseObject->GetName();
+    }
+
+    return rootObjectName;
+}
+
+FdoStringP FdoSmPhDbObject::GetRootOwner() const
+{
+    FdoStringP rootOwnerName;
+
+    const FdoSmPhBaseObjectCollection* baseObjects = RefBaseObjects();
+
+    if ( baseObjects->GetCount() == 1 ) {
+        const FdoSmPhBaseObject* baseObject = baseObjects->RefItem(0);
+        rootOwnerName = baseObject->GetOwnerName();
+    }
+
+    return rootOwnerName;
+}
+
+FdoStringP FdoSmPhDbObject::GetRootDatabase() const
+{
+    FdoStringP rootDatabaseName;
+
+    const FdoSmPhBaseObjectCollection* baseObjects = RefBaseObjects();
+
+    if ( baseObjects->GetCount() == 1 ) {
+        const FdoSmPhBaseObject* baseObject = baseObjects->RefItem(0);
+        rootDatabaseName = baseObject->GetDatabaseName();
+    }
+
+    return rootDatabaseName;
+}
+
+
+const FdoSmPhBaseObjectCollection* FdoSmPhDbObject::RefBaseObjects() const
+{
+    FdoSmPhBaseObjectsP baseObjects = ((FdoSmPhDbObject*) this)->GetBaseObjects();
+
+    return (FdoSmPhBaseObjectCollection*) baseObjects;
+}
+
+FdoSmPhBaseObjectsP FdoSmPhDbObject::GetBaseObjects()
+{
+    LoadBaseObjects();
+
+	return mBaseObjects;
+}
+
+
 FdoStringP FdoSmPhDbObject::GetDDLName() const
 {
     return GetDbName();
@@ -144,6 +310,45 @@
 	return NULL;
 }
 
+FdoBoolean FdoSmPhDbObject::IsUkeyPkey( FdoSmPhColumnsP ukeyColumns )
+{
+    FdoBoolean      isUkeyPkey  = false;
+    FdoInt32        idx;
+    FdoSmPhColumnsP pkeyColumns = GetPkeyColumns();
+
+    if ( (ukeyColumns->GetCount() > 0) && (ukeyColumns->GetCount() == pkeyColumns->GetCount()) ) {
+        isUkeyPkey = true;
+
+        for ( idx = 0; idx < ukeyColumns->GetCount(); idx++ ) {
+            FdoSmPhColumnP ukeyColumn = ukeyColumns->GetItem( idx );
+
+            if ( pkeyColumns->IndexOf(ukeyColumn->GetName()) < 0 ) {
+                isUkeyPkey = false;
+                break;
+            }
+        }
+    }
+
+    return isUkeyPkey;
+}
+
+FdoBoolean FdoSmPhDbObject::HasColumns( FdoSmPhColumnsP columns )
+{
+    FdoBoolean hasColumns = true;
+    FdoInt32 ix;
+
+    for ( ix = 0; ix < columns->GetCount(); ix++ ) {
+        FdoSmPhColumnP column = columns->GetItem( ix );
+        FdoSmPhColumnP thisColumn = GetColumns()->FindItem(column->GetName());
+        if ( (!thisColumn) || !column->DefinitionEquals(thisColumn) ) {
+            hasColumns = false;
+            break;
+        }
+    }
+
+    return hasColumns;
+}
+
 FdoStringsP FdoSmPhDbObject::GetRefColsSql()
 {
 	FdoSmPhColumnsP columns = GetColumns();
@@ -157,6 +362,58 @@
     return _getRefColsSql( columns );
 }
    
+FdoStringP FdoSmPhDbObject::GetAddPkeySql()
+{
+    FdoSmPhColumnsP     pkeyColumns = GetPkeyColumns();
+    FdoStringP          pkeySql;
+    bool                ansiQuotes = GetManager()->SupportsAnsiQuotes();
+
+    if ( pkeyColumns->GetCount() > 0 ) {
+        FdoStringsP pkColNames = GetKeyColsSql( pkeyColumns );
+        
+        pkeySql = FdoStringP::Format( 
+            L"constraint %ls%ls%ls primary key ( %ls )",
+            ansiQuotes ? L"\"" : L"",
+            (FdoString*) this->GenPkeyName(),
+            ansiQuotes ? L"\"" : L"",
+            (FdoString*) pkColNames->ToString()
+        );
+    }
+
+    return pkeySql;
+}
+
+void FdoSmPhDbObject::SetPkeyName( FdoStringP pkeyName )
+{
+    if ( GetElementState() != FdoSchemaElementState_Added )
+        throw FdoSchemaException::Create(
+            FdoSmError::NLSGetMessage(
+                FDO_NLSID(FDOSM_20), 
+				(FdoString*) GetQName()
+            )
+        );
+
+    mPkeyName = pkeyName;
+}
+
+void FdoSmPhDbObject::AddPkeyCol(FdoStringP columnName )
+{
+    LoadPkeys();
+
+	FdoSmPhColumnP column = GetColumns()->FindItem( columnName );
+
+	if ( column ) 
+		mPkeyColumns->Add( column );
+	else
+		throw FdoSchemaException::Create(
+            FdoSmError::NLSGetMessage(
+			    FDO_NLSID(FDOSM_213),				
+   				(FdoString*) columnName, 
+				GetName()
+			)
+		);
+}
+
 FdoStringP FdoSmPhDbObject::XMLSerializeProviderAtts() const
 {
     return FdoStringP::mEmptyString;
@@ -461,6 +718,38 @@
 
     return column;
 }
+
+FdoSmPhFkeyP FdoSmPhDbObject::CreateFkey(
+    FdoStringP name, 
+    FdoStringP pkeyTableName,
+    FdoStringP pkeyTableOwner
+)
+{
+    FdoStringP lTableOwner = pkeyTableOwner;
+
+    if ( lTableOwner == L"" ) 
+        lTableOwner = GetParent()->GetName();
+
+    FdoSmPhFkeyP fkey = NewFkey( name, pkeyTableName, lTableOwner );
+    if ( fkey == NULL ) 
+        AddCreateFkeyError( name );
+
+    FdoSmPhFkeysP fkeys = GetFkeysUp();
+    fkeys->Add( fkey );
+
+    return fkey;
+}
+
+void FdoSmPhDbObject::Commit( bool fromParent, bool isBeforeParent )
+{
+    FdoSmPhDbObjectP rootObject = this->GetRootObject();
+
+    if ( rootObject ) 
+        rootObject->Commit(fromParent, isBeforeParent);
+
+    FdoSmPhDbElement::Commit( fromParent, isBeforeParent );
+}
+
 /*
 void FdoSmPhDbObject::CheckNewColumn(
     FdoStringP columnName, 
@@ -533,6 +822,44 @@
     }
 }
 
+void FdoSmPhDbObject::CacheBaseObjects( FdoSmPhRdBaseObjectReaderP rdr )
+{
+    // Do nothing if base objects already loaded
+	if ( !mBaseObjects ) {
+		mBaseObjects = new FdoSmPhBaseObjectCollection( this );
+
+        FdoSmPhTableComponentReaderP groupReader = NewTableBaseReader(
+            rdr
+        );
+
+        LoadBaseObjects( groupReader );
+    }
+}
+
+void FdoSmPhDbObject::CachePkeys( FdoSmPhRdPkeyReaderP rdr )
+{
+    // Do nothing if primary key already loaded
+	if ( !mPkeyColumns ) {
+        mPkeyColumns = new FdoSmPhColumnCollection();
+
+        LoadPkeys( NewTablePkeyReader(rdr)->SmartCast<FdoSmPhReader>(), false );
+    }
+    else
+        LoadPkeys( NewTablePkeyReader(rdr)->SmartCast<FdoSmPhReader>(), true );
+}
+
+void FdoSmPhDbObject::CacheFkeys( FdoSmPhRdFkeyReaderP rdr )
+{
+    // Do nothing if foreign keys already loaded.
+    if ( !mFkeysUp ) {
+        mFkeysUp = new FdoSmPhFkeyCollection();
+
+        LoadFkeys( NewTableFkeyReader(rdr)->SmartCast<FdoSmPhReader>(), false );
+    }
+    else
+        LoadFkeys( NewTableFkeyReader(rdr)->SmartCast<FdoSmPhReader>(), true );
+}
+
 void FdoSmPhDbObject::CacheDependenciesUp( FdoSmPhDependencyReaderP rdr )
 {
     // Do nothing if "up" dependencies already loaded
@@ -557,6 +884,30 @@
     }
 }
 
+void FdoSmPhDbObject::CommitFkeys( bool isBeforeParent )
+{
+    FdoInt32        i;
+    FdoSmPhFkeysP   fkeys = GetFkeysUp();
+    FdoStringsP     fkeyClauses = FdoStringCollection::Create();
+
+    for ( i = (fkeys->GetCount() - 1); i >= 0; i-- ) {
+        FdoSmPhFkeyP(fkeys->GetItem(i))->Commit(true, isBeforeParent);
+    }
+}
+
+void FdoSmPhDbObject::ForceDelete()
+{
+    FdoInt32 i;
+
+  	FdoSmPhSchemaElement::SetElementState( FdoSchemaElementState_Deleted );
+
+    // Must explicitly delete any foreign keys when table is deleted.
+    FdoSmPhFkeysP   fkeys = GetFkeysUp();
+    for ( i = 0; i < fkeys->GetCount(); i++ ) {
+        FdoSmPhFkeyP(fkeys->GetItem(i))->SetElementState(FdoSchemaElementState_Deleted);
+    }
+}
+
 FdoSchemaExceptionP FdoSmPhDbObject::Errors2Exception(FdoSchemaException* pFirstException ) const
 {
 
@@ -564,11 +915,19 @@
 	FdoSchemaExceptionP pException = FdoSmPhDbElement::Errors2Exception(pFirstException);
 
     const FdoSmPhColumnCollection* pColumns = RefColumns();
+    int i;
 
 	// Add errors for the database object's columns.
-	for ( int i = 0; i < pColumns->GetCount(); i++ )
+	for ( i = 0; i < pColumns->GetCount(); i++ )
 		pException = pColumns->RefItem(i)->Errors2Exception(pException);
 
+    if ( mFkeysUp ) {
+
+	    // Add errors for the database object's foreign keys.
+	    for ( i = 0; i < mFkeysUp->GetCount(); i++ )
+		    pException = mFkeysUp->RefItem(i)->Errors2Exception(pException);
+    }
+
 	return pException;
 }
 /*
@@ -630,13 +989,33 @@
     }
 }
 
+FdoPtr<FdoSmPhTableComponentReader> FdoSmPhDbObject::NewTablePkeyReader( FdoSmPhRdPkeyReaderP rdr )
+{
+    return new FdoSmPhTableComponentReader(
+        GetName(),
+        L"",
+        L"table_name",
+        rdr->SmartCast<FdoSmPhReader>()
+    );
+}
+
+FdoPtr<FdoSmPhTableComponentReader> FdoSmPhDbObject::NewTableFkeyReader( FdoSmPhRdFkeyReaderP rdr )
+{
+    return new FdoSmPhTableComponentReader(
+        GetName(),
+        L"",
+        L"table_name",
+        rdr->SmartCast<FdoSmPhReader>()
+    );
+}
+
 FdoStringsP FdoSmPhDbObject::_getRefColsSql( FdoSmPhColumnCollection* columns )
 {
     FdoInt32        i;
     FdoStringsP     colClauses = FdoStringCollection::Create();
 
     for ( i = 0; i < columns->GetCount(); i++ ) {
-        colClauses->Add( columns->GetItem(i)->GetDbName() );
+        colClauses->Add( columns->RefItem(i)->GetDbName() );
     }
 
     return colClauses;
@@ -652,6 +1031,16 @@
     mLockingMode = mode;
 }
 
+void FdoSmPhDbObject::SetRootObject( FdoSmPhDbObjectP rootObject )
+{
+    mBaseObjects->Clear();
+
+    if ( rootObject ) {
+        FdoSmPhBaseObjectP baseObject = NewBaseObject( rootObject );
+        mBaseObjects->Add( baseObject );
+    }
+}
+
 void FdoSmPhDbObject::LoadColumns()
 {
     if ( !mColumns ) {
@@ -680,10 +1069,145 @@
 {
     while ( colRdr->ReadNext() ) {
         FdoSmPhColumnP newColumn = NewColumn( colRdr->GetColumnReader() );
-        mColumns->Add( newColumn );
+        if ( newColumn ) 
+            mColumns->Add( newColumn );
     }
 }
 
+void FdoSmPhDbObject::LoadBaseObjects()
+{
+    if ( !mBaseObjects ) {
+        // Base objects not loaded so initialize the list.
+        mBaseObjects = new FdoSmPhBaseObjectCollection( this );
+
+        // Skip database access when not necessary: object is new or has no name.
+        // Some temporary objects created by various readers have no name.
+        if ( (GetElementState() != FdoSchemaElementState_Added) && (wcslen(GetName()) > 0) ) {
+            FdoPtr<FdoSmPhRdBaseObjectReader> baseObjRdr = CreateBaseObjectReader();
+
+            // Read each column from the database and add it to this database object.
+            if ( baseObjRdr ) {
+                FdoSmPhTableComponentReaderP groupReader = NewTableBaseReader(
+                    baseObjRdr
+                );
+
+                LoadBaseObjects( groupReader );
+            }
+        }
+    }
+}
+
+void FdoSmPhDbObject::LoadBaseObjects( FdoPtr<FdoSmPhTableComponentReader> baseObjRdr )
+{
+    while ( baseObjRdr->ReadNext() ) {
+        FdoSmPhBaseObjectP newBaseObject = NewBaseObject( baseObjRdr );
+        if ( newBaseObject ) 
+            mBaseObjects->Add( newBaseObject );
+    }
+}
+
+void FdoSmPhDbObject::LoadPkeys(void)
+{
+    // Do nothing if primary key already loaded
+	if ( !mPkeyColumns ) {
+        mPkeyColumns = new FdoSmPhColumnCollection();
+
+        // Skip load if new table.
+        if ( GetElementState() != FdoSchemaElementState_Added ) {
+            FdoPtr<FdoSmPhRdPkeyReader> pkeyRdr = CreatePkeyReader();
+
+            if ( pkeyRdr ) 
+                LoadPkeys( pkeyRdr->SmartCast<FdoSmPhReader>(), false );
+        }
+    }
+}
+
+void FdoSmPhDbObject::LoadPkeys( FdoSmPhReaderP pkeyRdr, bool isSkipAdd )
+{
+    // read each primary key column.
+    while (pkeyRdr->ReadNext() ) {
+        mPkeyName = pkeyRdr->GetString(L"", L"constraint_name");
+        FdoStringP columnName = pkeyRdr->GetString(L"",L"column_name");
+
+        FdoSmPhColumnP pkeyColumn = GetColumns()->FindItem( columnName );
+
+        if ( pkeyColumn == NULL ) {
+            // Primary Key column must be in this table.
+            if ( GetElementState() != FdoSchemaElementState_Deleted )
+		        AddPkeyColumnError( columnName );
+	    }
+	    else if( ! isSkipAdd ) {
+	        mPkeyColumns->Add(pkeyColumn);
+	    }
+    }
+}
+
+void FdoSmPhDbObject::LoadFkeys(void)
+{
+    // Do nothing if already loaded
+	if ( !mFkeysUp ) {
+        mFkeysUp = new FdoSmPhFkeyCollection();
+
+        // Skip load for new tables
+        if ( GetElementState() != FdoSchemaElementState_Added ) {
+            FdoPtr<FdoSmPhRdFkeyReader> fkeyRdr = CreateFkeyReader();
+
+            if ( fkeyRdr ) 
+                LoadFkeys( fkeyRdr->SmartCast<FdoSmPhReader>(), false );
+        }
+    }
+}
+
+void FdoSmPhDbObject::LoadFkeys( FdoSmPhReaderP fkeyRdr, bool isSkipAdd  )
+{
+    FdoStringP                  nextFkey;
+    FdoSmPhFkeyP                fkey;
+
+    // Read each foreign key and column
+    while ( fkeyRdr->ReadNext() ) {
+        nextFkey = fkeyRdr->GetString(L"",L"constraint_name");
+
+        if ( !fkey || (nextFkey != fkey->GetName()) ) {
+            // hit the next foreign key. Create an object for it
+            fkey = NewFkey(
+                nextFkey, 
+                fkeyRdr->GetString(L"", "r_table_name"),
+                fkeyRdr->GetString(L"", "r_owner_name"),
+                FdoSchemaElementState_Unchanged
+            );
+
+            if( fkey && ! isSkipAdd )
+                mFkeysUp->Add(fkey);
+        }
+
+        // Add the column to the foreign key
+        FdoStringP columnName = fkeyRdr->GetString(L"",L"column_name");
+        FdoSmPhColumnP column = GetColumns()->FindItem(columnName);
+
+        if ( fkey && column ) {
+            fkey->AddFkeyColumn( 
+                column,
+                fkeyRdr->GetString(L"", "r_column_name")
+            );
+        }
+        else {
+            // Foreign Key column must be in this table.
+	        if ( GetElementState() != FdoSchemaElementState_Deleted )
+		        AddFkeyColumnError( columnName );
+        }
+    }
+}
+
+FdoPtr<FdoSmPhTableComponentReader> FdoSmPhDbObject::NewTableBaseReader( FdoSmPhRdBaseObjectReaderP rdr )
+{
+    return new FdoSmPhTableComponentReader(
+        GetName(),
+        L"",
+        L"name",
+        rdr->SmartCast<FdoSmPhReader>()
+    );
+}
+
 FdoSmPhColumnP FdoSmPhDbObject::NewColumn(
     FdoPtr<FdoSmPhRdColumnReader> colRdr
 )
@@ -826,6 +1350,68 @@
     }
 }
 
+FdoSmPhBaseObjectP FdoSmPhDbObject::NewBaseObject(
+    FdoPtr<FdoSmPhTableComponentReader> baseObjRdr
+)
+{
+    return NewBaseObject(
+        baseObjRdr->GetString(L"",L"base_name"),
+        baseObjRdr->GetString(L"",L"base_owner"),
+        baseObjRdr->GetString(L"",L"base_database")
+    );
+}
+
+FdoSmPhBaseObjectP FdoSmPhDbObject::NewBaseObject(
+    FdoStringP name,
+    FdoStringP ownerName,
+    FdoStringP databaseName
+)
+{
+    return new FdoSmPhBaseObject( name, FDO_SAFE_ADDREF(this), ownerName, databaseName );
+}
+
+FdoSmPhBaseObjectP FdoSmPhDbObject::NewBaseObject(
+    FdoPtr<FdoSmPhDbObject> dbObject
+)
+{
+    return new FdoSmPhBaseObject( dbObject, FDO_SAFE_ADDREF(this));
+}
+
+FdoStringP FdoSmPhDbObject::GenPkeyName()
+{
+    if ( mPkeyName == L"" ) {
+        FdoSmPhOwner* pOwner = dynamic_cast<FdoSmPhOwner*>((FdoSmPhSchemaElement*) GetParent());
+        mPkeyName = pOwner->UniqueDbObjectName( FdoStringP(L"PK_") + FdoStringP(GetName()) ).Replace(L".",L"_");
+    }
+
+    return mPkeyName;
+}
+
+FdoSmPhFkeyP FdoSmPhDbObject::NewFkey(
+    FdoStringP name, 
+    FdoStringP pkeyTableName,
+    FdoStringP pkeyTableOwner,
+    FdoSchemaElementState elementState
+)
+{
+    return (FdoSmPhFkey*) NULL;
+}
+
+FdoPtr<FdoSmPhRdBaseObjectReader> FdoSmPhDbObject::CreateBaseObjectReader() const
+{
+    return (FdoSmPhRdBaseObjectReader*) NULL;
+}
+
+FdoPtr<FdoSmPhRdPkeyReader> FdoSmPhDbObject::CreatePkeyReader() const
+{
+    return (FdoSmPhRdPkeyReader*) NULL;
+}
+
+FdoPtr<FdoSmPhRdFkeyReader> FdoSmPhDbObject::CreateFkeyReader() const
+{
+    return (FdoSmPhRdFkeyReader*) NULL;
+}
+
 void FdoSmPhDbObject::UpdRollbackCache()
 {
     GetManager()->AddRollbackTable( GetQName(), GetCommitState() );
@@ -836,45 +1422,104 @@
     ((FdoSmPhOwner*) GetParent())->DiscardDbObject( this );
 }
 
-
-/*
-void FdoSmPhDbObject::AddReferenceLoopError(void)
+void FdoSmPhDbObject::AddPkeyColumnError(FdoStringP columnName)
 {
-	mpErrors->Add( FdoRdbmsSmErrorType_Other, 
-		FdoStringP( 
-			NlsMsgGet1(
-				FDORDBMS_215,
-				"Tried to finalize table %1$ls when already finalizing",
-				GetName()
-			)
-		)
+	GetErrors()->Add( FdoSmErrorType_Other, 
+        FdoSchemaException::Create(
+            FdoSmError::NLSGetMessage(
+                FDO_NLSID(FDOSM_217), 
+				(FdoString*) columnName, 
+				(FdoString*) GetQName()
+            )
+        )
 	);
 }
 
+bool FdoSmPhDbObject::CheckRootObjectLoop( FdoInt32& level )
+{
+    bool ok = true;
 
-void FdoSmPhDbObject::AddPkeyColumnError(FdoStringP columnName)
+    // When there are 100 or levels of object dependencies, there is likely something wrong.
+    // Check for a dependency loop in this case. This is done by counting the total number
+    // of DbObjects currently in the cache. If there are fewer objects than dependency levels
+    // we must have visited an object more than once, meaning that there is a dependency loop.
+    if ( (level % 100) == 0 ) {
+        FdoInt32 totalObjectCount = 0;
+        FdoInt32 ixD = 0;
+        
+        // Count objects for each database
+        for ( ixD = 0; ; ixD++ ) {
+            FdoSmPhDatabaseP database = GetManager()->GetCachedDatabase( ixD );
+            if ( database == NULL ) 
+                break;
+
+            FdoInt32 ixO;
+
+            // Count objects for each owner within database
+            for ( ixO = 0; ; ixO++ ) {
+                FdoSmPhOwnerP owner = database->GetCachedOwner( ixO );
+                if ( owner == NULL ) 
+                    break;
+
+                FdoInt32 ixB;
+
+                // Count each object for each owner.
+                for ( ixB = 0; ; ixB++ ) {
+                    FdoSmPhDbObjectP dbObject = owner->GetCachedDbObject( ixB );
+                    if ( dbObject == NULL ) 
+                        break;
+
+                    totalObjectCount++;
+                }
+            }
+        }
+        
+        // Add 1 to be on the safe side.
+        if ( level > (totalObjectCount + 1) ) {
+            ok = false;
+        }
+    }
+
+    level++;
+
+    return ok;
+}
+
+void FdoSmPhDbObject::AddFkeyColumnError(FdoStringP columnName)
 {
-	mpErrors->Add( FdoRdbmsSmErrorType_Other, 
-		FdoStringP( 
-			NlsMsgGet2(
-				FDORDBMS_217,
-				"Primary Key column %1$ls is not a column in table %2$ls",
+	GetErrors()->Add( FdoSmErrorType_Other, 
+        FdoSchemaException::Create(
+            FdoSmError::NLSGetMessage(
+                FDO_NLSID(FDOSM_2), 
 				(FdoString*) columnName, 
-				GetName()
-			)
-		)
+				(FdoString*) GetQName()
+            )
+        )
 	);
 }
 
-void FdoSmPhDbObject::AddNotNullColError(FdoStringP columnName)
+void FdoSmPhDbObject::AddCreateFkeyError(FdoStringP fkeyName)
 {
+	GetErrors()->Add( FdoSmErrorType_Other, 
+        FdoSchemaException::Create(
+            FdoSmError::NLSGetMessage(
+                FDO_NLSID(FDOSM_30), 
+				(FdoString*) fkeyName, 
+				(FdoString*) GetQName()
+            )
+        )
+	);
+}
+
+/*
+void FdoSmPhDbObject::AddReferenceLoopError(void)
+{
 	mpErrors->Add( FdoRdbmsSmErrorType_Other, 
 		FdoStringP( 
-			NlsMsgGet2(
-				FDORDBMS_218,
-				"Table %1$ls has rows; cannot add non nullable column %2$ls to it",
-				GetName(), 
-				(FdoString*) columnName 
+			NlsMsgGet1(
+				FDORDBMS_215,
+				"Tried to finalize table %1$ls when already finalizing",
+				GetName()
 			)
 		)
 	);

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Makefile.am
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Makefile.am	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Makefile.am	2007-02-15 17:36:56 UTC (rev 2519)
@@ -24,6 +24,7 @@
 libSmPhysical_la_SOURCES = \
   AssociationReader.cpp \
   AssociationWriter.cpp \
+  BaseObject.cpp \
   CharacterSet.cpp \
   ClassPropertyReader.cpp \
   ClassPropertySADReader.cpp \

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Mgr.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Mgr.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Mgr.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -208,6 +208,16 @@
     return(pDatabase);
 }
 
+FdoSmPhDatabaseP FdoSmPhMgr::GetCachedDatabase(FdoInt32 idx)
+{
+    FdoSmPhDatabaseP database;
+
+    if ( mDatabases && (idx >= 0) && (idx < mDatabases->GetCount()) ) 
+        database = mDatabases->GetItem( idx );
+
+    return database;
+}
+
 FdoSmPhOwnerP FdoSmPhMgr::FindOwner(FdoStringP ownerName, FdoStringP database, bool caseSensitive)
 {
     FdoSmPhDatabaseP pDatabase = FindDatabase(database, caseSensitive);

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Owner.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Owner.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Owner.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -23,6 +23,7 @@
 #include <Sm/Ph/Mgr.h>
 #include <Sm/Ph/Rd/QueryReader.h>
 #include <Sm/Ph/Rd/ColumnReader.h>
+#include <Sm/Ph/Rd/BaseObjectReader.h>
 #include <Sm/Ph/Rd/DbObjectReader.h>
 #include <Sm/Ph/Rd/CoordSysReader.h>
 #include <Sm/Ph/Rd/ConstraintReader.h>
@@ -235,6 +236,17 @@
     return(pDbObject);
 }
 
+FdoSmPhDbObjectP FdoSmPhOwner::GetCachedDbObject(FdoInt32 idx)
+{
+    FdoSmPhDbObjectP dbObject;
+    FdoSmPhDbObjectsP dbObjects = GetDbObjects();
+
+    if ( (idx >= 0) && (idx < dbObjects->GetCount()) ) 
+        dbObject = dbObjects->GetItem( idx );
+
+    return dbObject;
+}
+
 FdoSmPhSpatialContextsP FdoSmPhOwner::GetSpatialContexts()
 {
     LoadSpatialContexts();
@@ -356,6 +368,11 @@
     return (FdoSmPhRdColumnReader*) NULL;
 }
 
+FdoPtr<FdoSmPhRdBaseObjectReader> FdoSmPhOwner::CreateBaseObjectReader() const
+{
+    return (FdoSmPhRdBaseObjectReader*) NULL;
+}
+
 FdoPtr<FdoSmPhRdSpatialContextReader> FdoSmPhOwner::CreateRdSpatialContextReader()
 {
     return new FdoSmPhRdSpatialContextReader(FDO_SAFE_ADDREF(this) );
@@ -423,6 +440,7 @@
 
         FdoSmPhRdDbObjectReaderP objReader;
         FdoSmPhRdColumnReaderP columnReader;
+        FdoSmPhRdBaseObjectReaderP baseObjectReader;
         FdoSmPhRdConstraintReaderP ukeyReader;
         FdoSmPhRdConstraintReaderP ckeyReader;
         FdoSmPhRdFkeyReaderP fkeyReader;
@@ -440,6 +458,7 @@
             // Doing a single query per owner for each component is more efficient than
             // a query per dbObject.
             columnReader = CreateColumnReader();
+            baseObjectReader = CreateBaseObjectReader();
             ukeyReader = CreateConstraintReader( L"", L"U" );
             ckeyReader = CreateConstraintReader( L"", L"C" );
             fkeyReader = CreateFkeyReader();
@@ -456,6 +475,15 @@
                 if ( columnReader ) 
                     dbObject->CacheColumns( columnReader );
 
+                if ( baseObjectReader ) 
+                    dbObject->CacheBaseObjects( baseObjectReader );
+
+                if ( fkeyReader ) 
+                    dbObject->CacheFkeys( fkeyReader );
+
+                if ( pkeyReader ) 
+                    dbObject->CachePkeys( pkeyReader );
+
                 // Load the components into the db object.
                 FdoSmPhTableP table = dbObject->SmartCast<FdoSmPhTable>();
 
@@ -466,14 +494,8 @@
                     if ( ckeyReader ) 
                         table->CacheCkeys( ckeyReader );
 
-                    if ( fkeyReader ) 
-                        table->CacheFkeys( fkeyReader );
-
                     if ( indexReader ) 
                         table->CacheIndexes( indexReader );
-
-                    if ( pkeyReader ) 
-                        table->CachePkeys( pkeyReader );
                 }
             }
         }
@@ -642,10 +664,8 @@
 
     if ( mDbObjects ) {
         for ( i = (mDbObjects->GetCount() - 1); i >= 0; i-- ) {
-            // Only tables have foreign keys.
-            FdoSmPhTableP table = mDbObjects->GetItem(i)->SmartCast<FdoSmPhTable>(true);
-            if ( table ) 
-                table->CommitFkeys( isBeforeParent );
+            FdoSmPhDbObjectP dbObject = mDbObjects->GetItem(i);
+            dbObject->CommitFkeys( isBeforeParent );
         }
     }
 }

Added: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/BaseObjectReader.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/BaseObjectReader.cpp	                        (rev 0)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/BaseObjectReader.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2006  Autodesk, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser
+ * General Public License as published by the Free Software Foundation.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include <Sm/Ph/Rd/BaseObjectReader.h>
+#include <Sm/Ph/Mgr.h>
+
+FdoSmPhRdBaseObjectReader::FdoSmPhRdBaseObjectReader(
+    FdoSmPhReaderP reader,
+    FdoSmPhOwnerP owner
+) :
+	FdoSmPhReader(reader),
+    mOwner(owner)
+{
+}
+
+FdoSmPhRdBaseObjectReader::FdoSmPhRdBaseObjectReader(
+    FdoSmPhReaderP reader,
+    FdoSmPhDbObjectP dbObject
+) :
+	FdoSmPhReader(reader),
+    mDbObject(dbObject)
+{
+}
+
+FdoSmPhRdBaseObjectReader::~FdoSmPhRdBaseObjectReader(void)
+{
+}
+
+FdoSmPhRowsP FdoSmPhRdBaseObjectReader::MakeRows( FdoSmPhMgrP mgr)
+{
+    FdoSmPhRowsP rows = new FdoSmPhRowCollection();
+
+    // Single row, no joins
+    FdoSmPhRowP row = new FdoSmPhRow(mgr, L"BaseObjectFields"); 
+    rows->Add(row);
+
+    // Each field adds itself to the row.
+    FdoSmPhFieldP pField = new FdoSmPhField(
+        row, 
+        L"name",
+        row->CreateColumnDbObject(L"name",false)
+    );
+
+    pField = new FdoSmPhField(
+        row, 
+        L"base_name",
+        row->CreateColumnDbObject(L"base_name",false)
+    );
+
+    pField = new FdoSmPhField(
+        row, 
+        L"base_owner",
+        row->CreateColumnDbObject(L"base_owner",false)
+    );
+
+    pField = new FdoSmPhField(
+        row, 
+        L"base_database",
+        row->CreateColumnDbObject(L"base_database",true)
+    );
+
+    return( rows);
+}
+
+

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/ClassReader.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/ClassReader.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/ClassReader.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -44,13 +44,13 @@
     FdoStringP schemaName, 
     FdoStringP className, 
     FdoSmPhMgrP mgr,
-    FdoBoolean keyedOnly,
+    FdoBoolean classifyDefaultTypes,
     FdoStringP database,
     FdoStringP owner
 
 ) :
 	FdoSmPhReader(mgr, froms),
-    mKeyedOnly(keyedOnly),
+    mClassifyDefaultTypes(classifyDefaultTypes),
     m_IsGeometryFromOrdinatesWanted(mgr->IsGeometryFromOrdinatesWanted()),
     mSchemaName(schemaName),
     mCurrDbObject(-1)
@@ -114,13 +114,11 @@
             // Get the current object and determine whether table or view 
             FdoSmPhDbObjectP pObject = mDbObjects->GetItem( mCurrDbObject );
             objectName = pObject->GetName();
-            FdoSmPhTableP pTable = pObject->SmartCast<FdoSmPhTable>();
-            FdoSmPhViewP pView = pObject->SmartCast<FdoSmPhView>();
-
+ 
             // Only classification of tables or views is supported
-            if ( pTable || pView ) {
+            if ( ClassifyObjectType(pObject, mClassifyDefaultTypes) ) {
                 // Check if class can be generated from this table or view.
-                classifiedObjectName = ClassifyObject( objectName, pTable ? FdoSmPhDbObjType_Table : FdoSmPhDbObjType_View );
+                classifiedObjectName = ClassifyObject( pObject );
                 if ( classifiedObjectName.GetLength() > 0 ) {
                     found = true;
 
@@ -201,35 +199,26 @@
 	return(!IsEOF());
 }
 
-FdoStringP FdoSmPhRdClassReader::ClassifyObject( FdoStringP objectName, FdoSmPhDbObjType objectType )
+bool FdoSmPhRdClassReader::ClassifyObjectType( FdoSmPhDbObjectP dbObject, FdoBoolean classifyDefaultTypes )
 {
-    FdoStringP classifiedObjectName = objectName;
-    bool hasKey = false;
+    FdoSmPhTableP pTable = dbObject->SmartCast<FdoSmPhTable>();
+    FdoSmPhViewP pView = dbObject->SmartCast<FdoSmPhView>();
 
-    if ( (classifiedObjectName.GetLength() > 0) &&
-         (objectType == FdoSmPhDbObjType_Table) 
-    ) {
-        FdoSmPhDbObjectP dbObject;
+    return ( pTable || pView );
+}
 
-        dbObject = mOwner->FindDbObject( classifiedObjectName );
+FdoStringP FdoSmPhRdClassReader::ClassifyObject( FdoSmPhDbObjectP dbObject )
+{
+    FdoStringP classifiedObjectName = dbObject->GetName();
+    bool hasKey = false;
 
-        if ( dbObject ) {
-            if ( (mSchemaName == L"") || (dbObject->GetBestSchemaName() == mSchemaName) ) {
-                // Find out if the table has a key.
-                FdoSmPhTable* pTable = dbObject ? dynamic_cast<FdoSmPhTable*>((FdoSmPhDbObject*) dbObject) : NULL;
-                if ( pTable ) {
-                    hasKey = (pTable->GetBestIdentity() != NULL);
-                }
-            }
-            else {
-                // DbObject is for a different feature schema.
-                classifiedObjectName = L"";
-            }
+    if ( classifiedObjectName.GetLength() > 0 ) {
+        if ( (mSchemaName == L"") || (dbObject->GetBestSchemaName() == mSchemaName) ) {
+            // Find out if the database object has a key.
+            hasKey = (dbObject->GetBestIdentity() != NULL);
         }
         else {
-             // DbObject can't be found, skip it.
-            // This can happen in the Oracle Provider for a number of 
-            // tables named 'bin$...'. These definitely need to be skipped.
+            // DbObject is for a different feature schema.
             classifiedObjectName = L"";
         }
     }
@@ -239,7 +228,7 @@
     // Classify only if the object is a table or we were asked to 
     // include any objects.
     // TODO: change the name of mKeyedOnly to reflect its new purpose.
-    return ( (!mKeyedOnly) || (objectType == FdoSmPhDbObjType_Table)) ? classifiedObjectName : FdoStringP(L"");
+    return classifiedObjectName;
 }
 
 FdoStringP FdoSmPhRdClassReader::FindGeometryProperty( FdoSmPhColumnsP cols, bool& hasGeom )
@@ -304,3 +293,9 @@
 
     return geomPropName;
 }
+
+// This function is now obsolete; override or extend ClassifyObject( FdoSmPhDbObjectP ) instead.
+FdoStringP FdoSmPhRdClassReader::ClassifyObject( FdoStringP objectName, FdoSmPhDbObjType objectType )
+{
+    throw FdoException::Create( L"Internal error, obsolete function FdoSmPhRdClassReader::ClassifyObject( FdoStringP , FdoSmPhDbObjType ) should never be called" );
+}

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/Makefile.am
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/Makefile.am	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/Makefile.am	2007-02-15 17:36:56 UTC (rev 2519)
@@ -21,6 +21,7 @@
 
 libSmPhRd_la_SOURCES = \
   AssociationReader.cpp \
+  BaseObjectReader.cpp \
   CharacterSetReader.cpp \
   ClassReader.cpp \
   CollationReader.cpp \

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/PropertyReader.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/PropertyReader.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Rd/PropertyReader.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -43,7 +43,6 @@
     mFieldIdx(-1),
     mFkeyIdx(-1),
     mDbObject(dbObject),
-    mpTable(NULL),
     m_IsGeometryFromOrdinatesWanted(mgr->IsGeometryFromOrdinatesWanted()),
     mFkeyCount(0)
 {
@@ -54,11 +53,8 @@
         SetEOF(true);
     }
     else {
-        // Count the number of foreign keys in the database object. Only
-        // tables have foreign keys.
-        mpTable = dynamic_cast<FdoSmPhTable*>((FdoSmPhDbObject*) mDbObject);
-        if ( mpTable ) 
-            mFkeyCount = mpTable->RefFkeysUp()->GetCount();
+        // Count the number of foreign keys in the database object.
+        mFkeyCount = mDbObject->RefFkeysUp()->GetCount();
 
         // Determine the identity properties (columns)
         ResolveIdentity();
@@ -165,7 +161,7 @@
 
                     // No more columns; get the next foreign key, and turn it into 
                     // an association property.
-					FdoSmPhFkeysP	pFkeys = mpTable->GetFkeysUp();
+					FdoSmPhFkeysP	pFkeys = mDbObject->GetFkeysUp();
                     FdoSmPhFkeyP pFkey = pFkeys->GetItem(mFkeyIdx);
                     const FdoSmPhTable* pPkeyTable = pFkey->RefPkeyTable();
 
@@ -252,10 +248,7 @@
 
 void FdoSmPhRdPropertyReader::ResolveIdentity()
 {
-    mIdCols = NULL;
-
-    if ( mpTable ) 
-        mIdCols = mpTable->GetBestIdentity();
+    mIdCols = mDbObject->GetBestIdentity();
 }
 
 FdoStringP FdoSmPhRdPropertyReader::GetIdPosn( FdoStringP colName )
@@ -280,20 +273,18 @@
     FdoStringP colName = column->GetName();
     int idx;
 
-    if ( mpTable ) {
-        // Special case: do not weed out identity columns. Data properties need to 
-        // be generated for them.
-        if ( FdoSmPhColumnP(FdoSmPhColumnsP(mpTable->GetPkeyColumns())->FindItem( colName )) ) 
-            return false;
+    // Special case: do not weed out identity columns. Data properties need to 
+    // be generated for them.
+    if ( FdoSmPhColumnP(FdoSmPhColumnsP(mDbObject->GetPkeyColumns())->FindItem( colName )) ) 
+        return false;
 
-        // Check if the column is in a foreign key.
-		FdoSmPhFkeysP	pFkeys = mpTable->GetFkeysUp();
-		for ( idx = 0; idx < pFkeys->GetCount(); idx++ ) {
-            FdoSmPhFkeyP fkey = pFkeys->GetItem(idx);
-			FdoSmPhColumnsP	columns = fkey->GetFkeyColumns();
-            if ( FdoSmPhColumnP(columns->FindItem(colName)) ) 
-                return true;
-        }
+    // Check if the column is in a foreign key.
+    FdoSmPhFkeysP	pFkeys = mDbObject->GetFkeysUp();
+	for ( idx = 0; idx < pFkeys->GetCount(); idx++ ) {
+        FdoSmPhFkeyP fkey = pFkeys->GetItem(idx);
+    	FdoSmPhColumnsP	columns = fkey->GetFkeyColumns();
+        if ( FdoSmPhColumnP(columns->FindItem(colName)) ) 
+            return true;
     }
 
     return false;

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -20,8 +20,6 @@
 #include <Sm/Ph/Table.h>
 #include <Sm/Ph/TableComponentReader.h>
 #include <Sm/Ph/Mgr.h>
-#include <Sm/Ph/Rd/PkeyReader.h>
-#include <Sm/Ph/Rd/FkeyReader.h>
 #include <Sm/Ph/Rd/ConstraintReader.h>
 #include <Sm/Ph/Rd/IndexReader.h>
 #include <Sm/Ph/Rd/ConstraintReader.h>
@@ -37,7 +35,7 @@
 {
     if ( !GetExists() )
         // Use given primary key name for new tables.
-        mPkeyName = pkeyName;
+        SetPkeyName(pkeyName);
 
 	mDeletedConstraints = FdoStringCollection::Create();
 }
@@ -51,20 +49,6 @@
     return true;
 }
 
-const FdoSmPhColumnCollection* FdoSmPhTable::RefPkeyColumns() const
-{
-    FdoSmPhColumnsP columns = ((FdoSmPhTable*) this)->GetPkeyColumns();
-
-    return (FdoSmPhColumnCollection*) columns;
-}
-
-FdoSmPhColumnsP FdoSmPhTable::GetPkeyColumns()
-{
-    LoadPkeys();
-
-	return mPkeyColumns;
-}
-
 const FdoSmPhBatchColumnCollection* FdoSmPhTable::RefUkeyColumns() const
 {
     FdoSmPhBatchColumnsP columnsColl = ((FdoSmPhTable*) this)->GetUkeyColumns();
@@ -105,81 +89,65 @@
 	return mIndexes;
 }
 
-FdoSmPhColumnsP FdoSmPhTable::GetBestIdentity()
+FdoSmPhColumnsP FdoSmPhTable::GetBestIdentity( FdoSmPhDbObjectP dbObject )
 {
     int idx = 0;
     long ixSize = (FdoSmPhIndex::mMaxWeight * 2);
     long bestIxSize = (FdoSmPhIndex::mMaxWeight * 2);
-
-    FdoSmPhColumnsP pkeyCols = GetPkeyColumns();
     FdoSmPhIndexP bestIndex;
 
-    // Choose primary key if present
-    if ( pkeyCols->GetCount() > 0 ) {
-        return pkeyCols;
-    }
+    FdoSmPhColumnsP bestIdentity = FdoSmPhDbObject::GetBestIdentity( dbObject );
 
-    // No primary key, use best unique index.
-    FdoSmPhIndexesP indexes = GetIndexes();
+    if ( bestIdentity == NULL ) {
 
-    for ( idx = 0; idx < indexes->GetCount(); idx++ ) {
-        FdoSmPhIndexP index = indexes->GetItem(idx);
+        // No primary key, use best unique index.
+        FdoSmPhIndexesP indexes = GetIndexes();
 
-        // Calculate index compactness score.
-        ixSize = index->GetWeight();
+        for ( idx = 0; idx < indexes->GetCount(); idx++ ) {
+            FdoSmPhIndexP index = indexes->GetItem(idx);
+            FdoSmPhColumnsP idxCols = index->GetColumns();
 
-        // Weed out non-unique indexes or indexes whose columns are too big.
-        if ( index->GetIsUnique() && (index->RefColumns()->GetCount() > 0) && (ixSize < FdoSmPhIndex::mMaxWeight) ) {
-            if ( bestIndex ) {
-                // Index already chosen, see if this one is better.
-                FdoSmPhColumnsP idxCols = index->GetColumns();
-                if (idxCols->GetCount() < bestIndex->RefColumns()->GetCount() ) {
-                    // This one has few columns, take it instead.
-                    bestIndex = index;
-                    bestIxSize = ixSize;
-                }
-                else if ( idxCols->GetCount() == bestIndex->RefColumns()->GetCount() ) {
-                    // same number of columns, take this index only if it has a better
-                    // compactness score.
-                    if ( ixSize < bestIxSize ) {
+            // Weed out non-unique indexes or indexes with no columns
+            if ( index->GetIsUnique() && (index->RefColumns()->GetCount() > 0) ) {
+                // Calculate index compactness score.
+                ixSize = index->GetWeight();
+
+                // Weed out indexes whose columns are too big.
+                // If a database object was specified, skip indexes whose columns
+                // are not all present on the database object.
+                if ( (ixSize < FdoSmPhIndex::mMaxWeight) && ((!dbObject) || dbObject->HasColumns(idxCols)) ) {
+                    if ( bestIndex ) {
+                        // Index already chosen, see if this one is better.
+                        if (idxCols->GetCount() < bestIndex->RefColumns()->GetCount() ) {
+                            // This one has few columns, take it instead.
+                            bestIndex = index;
+                            bestIxSize = ixSize;
+                        }
+                        else if ( idxCols->GetCount() == bestIndex->RefColumns()->GetCount() ) {
+                            // same number of columns, take this index only if it has a better
+                            // compactness score.
+                            if ( ixSize < bestIxSize ) {
+                                bestIndex = index;
+                                bestIxSize = ixSize;
+                            }
+                        }
+                    }
+                    else {
+                        // No index chosen yet, chose this one initially.
                         bestIndex = index;
                         bestIxSize = ixSize;
                     }
                 }
             }
-            else {
-                // No index chosen yet, chose this one initially.
-                bestIndex = index;
-                bestIxSize = ixSize;
-            }
         }
+
+        if ( bestIndex )
+            bestIdentity = bestIndex->GetColumns();
     }
 
-    if ( bestIndex )
-        return bestIndex->GetColumns();
-
-    return (FdoSmPhColumnCollection*) NULL;
+    return bestIdentity;
 }
 
-const FdoSmPhFkeyCollection* FdoSmPhTable::RefFkeysUp() const
-{
-    return (FdoSmPhFkeyCollection*) ((FdoSmPhTable*) this)->GetFkeysUp();
-}
-
-FdoSmPhFkeysP FdoSmPhTable::GetFkeysUp()
-{
-    LoadFkeys();
-
-	return mFkeysUp;
-}
-
-FdoStringP FdoSmPhTable::GetPkeyName() const
-{
-	((FdoSmPhTable*) this)->GetPkeyColumns();
-
-	return mPkeyName;
-}
-
 const FdoLockType* FdoSmPhTable::GetLockTypes(FdoInt32& size) const
 {
     FdoSmPhOwner* pOwner = static_cast<FdoSmPhOwner*>((FdoSmPhSchemaElement*) GetParent());
@@ -188,41 +156,6 @@
     return pOwner->GetLockTypes( GetLockingMode(), size );
 }
 
-void FdoSmPhTable::SetPkeyName( FdoStringP pkeyName )
-{
-    if ( GetElementState() != FdoSchemaElementState_Added )
-        throw FdoSchemaException::Create(
-            FdoSmError::NLSGetMessage(
-                FDO_NLSID(FDOSM_20), 
-				(FdoString*) GetQName()
-            )
-        );
-
-    mPkeyName = pkeyName;
-}
-
-FdoBoolean FdoSmPhTable::IsUkeyPkey( FdoSmPhColumnsP ukeyColumns )
-{
-    FdoBoolean      isUkeyPkey  = false;
-    FdoInt32        idx;
-    FdoSmPhColumnsP pkeyColumns = GetPkeyColumns();
-
-    if ( (ukeyColumns->GetCount() > 0) && (ukeyColumns->GetCount() == pkeyColumns->GetCount()) ) {
-        isUkeyPkey = true;
-
-        for ( idx = 0; idx < ukeyColumns->GetCount(); idx++ ) {
-            FdoSmPhColumnP ukeyColumn = ukeyColumns->GetItem( idx );
-
-            if ( pkeyColumns->IndexOf(ukeyColumn->GetName()) < 0 ) {
-                isUkeyPkey = false;
-                break;
-            }
-        }
-    }
-
-    return isUkeyPkey;
-}
-
 void FdoSmPhTable::SetLtMode( FdoLtLockModeType mode )
 {
     if ( (mode != GetLtMode()) && (GetElementState() != FdoSchemaElementState_Added) ) {
@@ -251,24 +184,6 @@
     FdoSmPhDbObject::SetLockingMode( mode );
 }
 
-void FdoSmPhTable::AddPkeyCol(FdoStringP columnName )
-{
-    LoadPkeys();
-
-	FdoSmPhColumnP column = GetColumns()->FindItem( columnName );
-
-	if ( column ) 
-		mPkeyColumns->Add( column );
-	else
-		throw FdoSchemaException::Create(
-            FdoSmError::NLSGetMessage(
-			    FDO_NLSID(FDOSM_213),				
-   				(FdoString*) columnName, 
-				GetName()
-			)
-		);
-}
-
 void FdoSmPhTable::AddUkeyCol(int uCollNum, FdoStringP columnName )
 {
     LoadUkeys();
@@ -309,42 +224,12 @@
     return index;
 }
 
-FdoSmPhFkeyP FdoSmPhTable::CreateFkey(
-    FdoStringP name, 
-    FdoStringP pkeyTableName,
-    FdoStringP pkeyTableOwner
-)
-{
-    FdoStringP lTableOwner = pkeyTableOwner;
-
-    if ( lTableOwner == L"" ) 
-        lTableOwner = GetParent()->GetName();
-
-    FdoSmPhFkeyP fkey = NewFkey( name, pkeyTableName, lTableOwner );
-
-    FdoSmPhFkeysP fkeys = GetFkeysUp();
-    fkeys->Add( fkey );
-
-    return fkey;
-}
-
 void FdoSmPhTable::DiscardIndex( FdoSmPhIndex* index )
 {
     FdoSmPhIndexesP indexes = GetIndexes();
     indexes->Remove( index );
 }
 
-void FdoSmPhTable::CommitFkeys( bool isBeforeParent )
-{
-    FdoInt32        i;
-    FdoSmPhFkeysP   fkeys = GetFkeysUp();
-    FdoStringsP     fkeyClauses = FdoStringCollection::Create();
-
-    for ( i = (fkeys->GetCount() - 1); i >= 0; i-- ) {
-        FdoSmPhFkeyP(fkeys->GetItem(i))->Commit(true, isBeforeParent);
-    }
-}
-
 void FdoSmPhTable::SetElementState(FdoSchemaElementState elementState)
 {
 	// Error if try to drop a table that has rows.
@@ -362,19 +247,6 @@
     }
 }
 
-void FdoSmPhTable::ForceDelete()
-{
-    FdoInt32 i;
-
-  	FdoSmPhSchemaElement::SetElementState( FdoSchemaElementState_Deleted );
-
-    // Must explicitly delete any foreign keys when table is deleted.
-    FdoSmPhFkeysP   fkeys = GetFkeysUp();
-    for ( i = 0; i < fkeys->GetCount(); i++ ) {
-        FdoSmPhFkeyP(fkeys->GetItem(i))->SetElementState(FdoSchemaElementState_Deleted);
-    }
-}
-
 void FdoSmPhTable::CacheUkeys( FdoSmPhRdConstraintReaderP rdr )
 {
     // Do nothing if unique constraints already loaded
@@ -399,18 +271,6 @@
         LoadCkeys( NewTableCkeyReader(rdr)->SmartCast<FdoSmPhReader>(), true );
 }
 
-void FdoSmPhTable::CacheFkeys( FdoSmPhRdFkeyReaderP rdr )
-{
-    // Do nothing if foreign keys already loaded.
-    if ( !mFkeysUp ) {
-        mFkeysUp = new FdoSmPhFkeyCollection();
-
-        LoadFkeys( NewTableFkeyReader(rdr)->SmartCast<FdoSmPhReader>(), false );
-    }
-    else
-        LoadFkeys( NewTableFkeyReader(rdr)->SmartCast<FdoSmPhReader>(), true );
-}
-
 void FdoSmPhTable::CacheIndexes( FdoSmPhRdIndexReaderP rdr )
 {
     // Do nothing if indexes already loaded
@@ -423,18 +283,6 @@
         LoadIndexes( NewTableIndexReader(rdr), true );
 }
 
-void FdoSmPhTable::CachePkeys( FdoSmPhRdPkeyReaderP rdr )
-{
-    // Do nothing if primary key already loaded
-	if ( !mPkeyColumns ) {
-        mPkeyColumns = new FdoSmPhColumnCollection();
-
-        LoadPkeys( NewTablePkeyReader(rdr)->SmartCast<FdoSmPhReader>(), false );
-    }
-    else
-        LoadPkeys( NewTablePkeyReader(rdr)->SmartCast<FdoSmPhReader>(), true );
-}
-
 FdoSchemaExceptionP FdoSmPhTable::Errors2Exception(FdoSchemaException* pFirstException ) const
 {
     FdoInt32 i;
@@ -458,13 +306,6 @@
 		    pException = mIndexes->RefItem(i)->Errors2Exception(pException);
     }
 
-    if ( mFkeysUp ) {
-
-	    // Add errors for the table's columns.
-	    for ( i = 0; i < mFkeysUp->GetCount(); i++ )
-		    pException = mFkeysUp->RefItem(i)->Errors2Exception(pException);
-    }
-
     if ( (GetElementState() == FdoSchemaElementState_Unchanged) ||
          (GetElementState() == FdoSchemaElementState_Modified)
     ) {
@@ -787,27 +628,6 @@
     );
 }
 
-FdoStringP FdoSmPhTable::GetAddPkeySql()
-{
-    FdoSmPhColumnsP     pkeyColumns = GetPkeyColumns();
-    FdoStringP          pkeySql;
-    bool                ansiQuotes = GetManager()->SupportsAnsiQuotes();
-
-    if ( pkeyColumns->GetCount() > 0 ) {
-        FdoStringsP pkColNames = GetKeyColsSql( pkeyColumns );
-        
-        pkeySql = FdoStringP::Format( 
-            L"constraint %ls%ls%ls primary key ( %ls )",
-            ansiQuotes ? L"\"" : L"",
-            (FdoString*) this->GenPkeyName(),
-            ansiQuotes ? L"\"" : L"",
-            (FdoString*) pkColNames->ToString()
-        );
-    }
-
-    return pkeySql;
-}
-
 FdoStringP FdoSmPhTable::GetAddUkeysSql()
 {
     FdoSmPhBatchColumnsP     ukeyColumnsColl = GetUkeyColumns();
@@ -896,52 +716,6 @@
     return constraintName;
 }
 
-
-FdoStringP FdoSmPhTable::GenPkeyName()
-{
-    if ( mPkeyName == L"" ) {
-        FdoSmPhOwner* pOwner = dynamic_cast<FdoSmPhOwner*>((FdoSmPhSchemaElement*) GetParent());
-        mPkeyName = pOwner->UniqueDbObjectName( FdoStringP(L"PK_") + FdoStringP(GetName()) ).Replace(L".",L"_");
-    }
-
-    return mPkeyName;
-}
-
-void FdoSmPhTable::LoadPkeys(void)
-{
-    // Do nothing if primary key already loaded
-	if ( !mPkeyColumns ) {
-        mPkeyColumns = new FdoSmPhColumnCollection();
-
-        // Skip load if new table.
-        if ( GetElementState() != FdoSchemaElementState_Added ) {
-            FdoPtr<FdoSmPhRdPkeyReader> pkeyRdr = CreatePkeyReader();
-
-            LoadPkeys( pkeyRdr->SmartCast<FdoSmPhReader>(), false );
-        }
-    }
-}
-
-void FdoSmPhTable::LoadPkeys( FdoSmPhReaderP pkeyRdr, bool isSkipAdd )
-{
-    // read each primary key column.
-    while (pkeyRdr->ReadNext() ) {
-        mPkeyName = pkeyRdr->GetString(L"", L"constraint_name");
-        FdoStringP columnName = pkeyRdr->GetString(L"",L"column_name");
-
-        FdoSmPhColumnP pkeyColumn = GetColumns()->FindItem( columnName );
-
-        if ( pkeyColumn == NULL ) {
-            // Primary Key column must be in this table.
-            if ( GetElementState() != FdoSchemaElementState_Deleted )
-		        AddPkeyColumnError( columnName );
-	    }
-	    else if( ! isSkipAdd ) {
-	        mPkeyColumns->Add(pkeyColumn);
-	    }
-    }
-}
-
 void FdoSmPhTable::LoadUkeys()
 {
     // Do nothing if unique constraints already loaded
@@ -1074,61 +848,6 @@
 }
 
 
-void FdoSmPhTable::LoadFkeys(void)
-{
-    // Do nothing if already loaded
-	if ( !mFkeysUp ) {
-        mFkeysUp = new FdoSmPhFkeyCollection();
-
-        // Skip load for new tables
-        if ( GetElementState() != FdoSchemaElementState_Added ) {
-            FdoPtr<FdoSmPhRdFkeyReader> fkeyRdr = CreateFkeyReader();
-
-            LoadFkeys( fkeyRdr->SmartCast<FdoSmPhReader>(), false );
-        }
-    }
-}
-
-void FdoSmPhTable::LoadFkeys( FdoSmPhReaderP fkeyRdr, bool isSkipAdd  )
-{
-    FdoStringP                  nextFkey;
-    FdoSmPhFkeyP                fkey;
-
-    // Read each foreign key and column
-    while ( fkeyRdr->ReadNext() ) {
-        nextFkey = fkeyRdr->GetString(L"",L"constraint_name");
-
-        if ( !fkey || (nextFkey != fkey->GetName()) ) {
-            // hit the next foreign key. Create an object for it
-            fkey = NewFkey(
-                nextFkey, 
-                fkeyRdr->GetString(L"", "r_table_name"),
-                fkeyRdr->GetString(L"", "r_owner_name"),
-                FdoSchemaElementState_Unchanged
-            );
-
-            if( ! isSkipAdd )
-                mFkeysUp->Add(fkey);
-        }
-
-        // Add the column to the foreign key
-        FdoStringP columnName = fkeyRdr->GetString(L"",L"column_name");
-        FdoSmPhColumnP column = GetColumns()->FindItem(columnName);
-
-        if ( column ) {
-            fkey->AddFkeyColumn( 
-                column,
-                fkeyRdr->GetString(L"", "r_column_name")
-            );
-        }
-        else {
-            // Foreign Key column must be in this table.
-	        if ( GetElementState() != FdoSchemaElementState_Deleted )
-		        AddFkeyColumnError( columnName );
-        }
-    }
-}
-
 void FdoSmPhTable::LoadIndexes(void)
 {
     // Do nothing if already loaded
@@ -1196,16 +915,6 @@
     );
 }
 
-FdoPtr<FdoSmPhTableComponentReader> FdoSmPhTable::NewTableFkeyReader( FdoSmPhRdFkeyReaderP rdr )
-{
-    return new FdoSmPhTableComponentReader(
-        GetName(),
-        L"",
-        L"table_name",
-        rdr->SmartCast<FdoSmPhReader>()
-    );
-}
-
 FdoPtr<FdoSmPhTableIndexReader> FdoSmPhTable::NewTableIndexReader( FdoSmPhRdIndexReaderP rdr )
 {
     return new FdoSmPhTableIndexReader(
@@ -1214,16 +923,6 @@
     );
 }
 
-FdoPtr<FdoSmPhTableComponentReader> FdoSmPhTable::NewTablePkeyReader( FdoSmPhRdPkeyReaderP rdr )
-{
-    return new FdoSmPhTableComponentReader(
-        GetName(),
-        L"",
-        L"table_name",
-        rdr->SmartCast<FdoSmPhReader>()
-    );
-}
-
 FdoSmPhIndexP FdoSmPhTable::CreateIndex(
     FdoPtr<FdoSmPhTableIndexReader> rdr
 )
@@ -1251,19 +950,6 @@
     return index;
 }
 
-void FdoSmPhTable::AddPkeyColumnError(FdoStringP columnName)
-{
-	GetErrors()->Add( FdoSmErrorType_Other, 
-        FdoSchemaException::Create(
-            FdoSmError::NLSGetMessage(
-                FDO_NLSID(FDOSM_217), 
-				(FdoString*) columnName, 
-				(FdoString*) GetQName()
-            )
-        )
-	);
-}
-
 void FdoSmPhTable::AddUkeyColumnError(FdoStringP columnName)
 {
 	GetErrors()->Add( FdoSmErrorType_Other, 
@@ -1290,18 +976,6 @@
 	);
 }
 
-void FdoSmPhTable::AddFkeyColumnError(FdoStringP columnName)
-{
-	GetErrors()->Add( FdoSmErrorType_Other, 
-        FdoSchemaException::Create(
-            FdoSmError::NLSGetMessage(
-                FDO_NLSID(FDOSM_2), 
-				(FdoString*) columnName, 
-				(FdoString*) GetQName()
-            )
-        )
-	);
-}
 void FdoSmPhTable::AddIndexColumnError(FdoStringP columnName)
 {
 	GetErrors()->Add( FdoSmErrorType_Other, 

Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/View.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/View.cpp	2007-02-14 23:37:11 UTC (rev 2518)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/View.cpp	2007-02-15 17:36:56 UTC (rev 2519)
@@ -28,48 +28,21 @@
     const FdoSmPhOwner* pOwner,
     FdoSchemaElementState elementState
 ) : 
-    FdoSmPhDbObject(viewName, pOwner, elementState ),
-    mRootDatabase(rootDatabase),
-    mRootOwner(rootOwner),
-    mRootObjectName(rootObjectName)
+    FdoSmPhDbObject(viewName, pOwner, elementState )
 {
+    if ( rootObjectName != L"" ) {
+        FdoSmPhBaseObjectP baseObject = NewBaseObject( rootObjectName, rootOwner, rootDatabase );
+        GetBaseObjects()->Add( baseObject );
+    }
 }
 
 FdoSmPhView::~FdoSmPhView(void)
 {
 }
 
-const FdoSmPhDbObject* FdoSmPhView::RefRootObject() const
-{
-    FdoSmPhDbObjectP rootObject = ((FdoSmPhView*) this)->GetRootObject();
-
-    return (FdoSmPhDbObject*) rootObject;
-}
-
-FdoSmPhDbObjectP FdoSmPhView::GetRootObject()
-{
-    if ( (mRootObjectName.GetLength() > 0) && (!mRootObject) ) 
-        mRootObject = GetManager()->FindDbObject( mRootObjectName, mRootDatabase, mRootOwner );
-
-    return mRootObject;
-}
-
-FdoSmPhDbObjectP FdoSmPhView::GetLowestRootObject()
-{
-    FdoSmPhDbObjectP rootObject = GetRootObject();
-
-    if ( rootObject ) 
-        rootObject = rootObject->GetLowestRootObject();
-
-    return rootObject;
-}
-
 void FdoSmPhView::SetRootObject( FdoSmPhDbObjectP rootObject )
 {
-    mRootObject = rootObject;
-    mRootObjectName = rootObject ? rootObject->GetName() : L"";
-    mRootOwner = rootObject ? rootObject->GetParent()->GetName() : L"";
-    mRootDatabase = rootObject ? rootObject->GetParent()->GetParent()->GetName() : L"";
+    FdoSmPhDbObject::SetRootObject( rootObject );
 }
 
 void FdoSmPhView::XMLSerialize( FILE* xmlFp, int ref ) const
@@ -118,6 +91,17 @@
             }
         }
     }
+
+    // After view commit, just commit the columns to update their element states.
+    if ( !isBeforeParent ) {
+        FdoSmPhColumnsP columns = GetColumns();
+
+        for ( i = (columns->GetCount() - 1); i >= 0; i-- ) {
+            FdoSmPhColumnP column = columns->GetItem(i);
+
+            column->Commit( true, isBeforeParent );
+        }
+    }
 }
 
 FdoStringP FdoSmPhView::GetAddSql()



More information about the fdo-commits mailing list