[fdo-commits] r640 - in trunk/Utilities: SchemaMgr/Inc/Sm/Lp
SchemaMgr/Nls SchemaMgr/Src/Sm/Lp SchemaMgr/Src/Sm/Ph
TestCommon/Inc TestCommon/Src
svn_fdo at osgeo.org
svn_fdo at osgeo.org
Fri Jan 19 14:24:28 EST 2007
Author: brentrobinson
Date: 2007-01-19 14:24:27 -0500 (Fri, 19 Jan 2007)
New Revision: 640
Modified:
trunk/Utilities/SchemaMgr/Inc/Sm/Lp/ClassDefinition.h
trunk/Utilities/SchemaMgr/Inc/Sm/Lp/UniqueConstraint.h
trunk/Utilities/SchemaMgr/Nls/SmMessage.mc
trunk/Utilities/SchemaMgr/Src/Sm/Lp/ClassDefinition.cpp
trunk/Utilities/SchemaMgr/Src/Sm/Lp/SchemaCollection.cpp
trunk/Utilities/SchemaMgr/Src/Sm/Lp/UniqueConstraint.cpp
trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp
trunk/Utilities/TestCommon/Inc/TestCommonConstraints.h
trunk/Utilities/TestCommon/Src/TestCommonConstraints.cpp
Log:
Merged from branch 3.2.x
Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Lp/ClassDefinition.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Lp/ClassDefinition.h 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Lp/ClassDefinition.h 2007-01-19 19:24:27 UTC (rev 640)
@@ -701,10 +701,14 @@
);
void AddForeignNoFeatIdError( const FdoSmLpPropertyDefinition* pFeatId );
void AddUkeyPropMissingError(FdoDataPropertyDefinition* pProp);
+ void AddUkeyBasePropError(FdoDataPropertyDefinition* pProp);
void DropUkeys();
void CreateUkeysFromFdo();
bool MatchUkey( FdoClassDefinitionP pClass, FdoSmPhColumnsP pPhColls );
+
+ // Checks if given unique constraint has a base constraint and sets it if it does.
+ void MatchInheritedUkey( FdoSmLpUniqueConstraintP ukey );
bool HasUkey( FdoSmPhColumnsP pPhColls );
void DropCkeys();
void CreateCkeysFromFdo();
Modified: trunk/Utilities/SchemaMgr/Inc/Sm/Lp/UniqueConstraint.h
===================================================================
--- trunk/Utilities/SchemaMgr/Inc/Sm/Lp/UniqueConstraint.h 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Inc/Sm/Lp/UniqueConstraint.h 2007-01-19 19:24:27 UTC (rev 640)
@@ -33,6 +33,23 @@
FdoSmLpDataPropertyDefinitionCollection *GetProperties();
const FdoSmLpDataPropertyDefinitionCollection *RefProperties() const;
+ // Get the base constraint if constraint actually defined on base class.
+ // Returnes NULL if this constraint does not have a base
+ FdoPtr<FdoSmLpUniqueConstraint> GetBaseConstraint();
+ const FdoSmLpUniqueConstraint* RefBaseConstraint() const;
+
+ // Compare this constraint with another one.
+ // Returns 0 if the two costraints have the same properties by name.
+ // Return -1 otherwise.
+ FdoInt32 Compare( FdoPtr<FdoSmLpUniqueConstraint> other ) const;
+
+ // Create a unique constraint inherited from this constraint.
+ // Returns NULL if not all the constrained properties are in the subClass.
+ FdoPtr<FdoSmLpUniqueConstraint> CreateInherited( FdoSmLpClassBase* pSubClass, FdoSmLpPropertyDefinitionCollection* pSubClassProperties );
+
+ // Sets the base constraint for this constraint.
+ void SetBaseConstraint( FdoPtr<FdoSmLpUniqueConstraint> baseConstraint );
+
/// Serialize this class to an XML file.
/// Primarily for unit testing.
virtual void XMLSerialize( FILE* xmlFp, int ref ) const;
@@ -45,6 +62,7 @@
private:
FdoSmLpDataPropertiesP mProperties;
+ FdoPtr<FdoSmLpUniqueConstraint> mBaseConstraint;
};
Modified: trunk/Utilities/SchemaMgr/Nls/SmMessage.mc
===================================================================
--- trunk/Utilities/SchemaMgr/Nls/SmMessage.mc 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Nls/SmMessage.mc 2007-01-19 19:24:27 UTC (rev 640)
@@ -156,6 +156,11 @@
Language=English
Collation '%1$ls' does not exist or is inaccessible from current connection.
.
+MessageId=2234
+SymbolicName=FDOSM_29
+Language=English
+Class '%1$ls' uses Base table mapping; Cannot include base property '%2$ls' in unique constraint
+.
MessageId=2327
SymbolicName=FDOSM_122
Language=English
Modified: trunk/Utilities/SchemaMgr/Src/Sm/Lp/ClassDefinition.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Lp/ClassDefinition.cpp 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Lp/ClassDefinition.cpp 2007-01-19 19:24:27 UTC (rev 640)
@@ -1186,7 +1186,9 @@
// Skip the constraint if any of its columns do not correspond
// to a property.
if ( allFound && (pProps->GetCount() > 0) )
- {
+ {
+ // If constraint is inherited, match it with its base constraint.
+ MatchInheritedUkey( pUniqueC );
pLpUniqueConstraints->Add(pUniqueC);
}
}
@@ -1837,10 +1839,17 @@
for ( int j = 0; j < pFdoUniqueCs->GetCount(); j++ ) {
FdoDataPropertyP pFdoDataProp = pFdoUniqueCs->GetItem(j);
FdoSmLpDataPropertyP pLpDataProp = mProperties->FindItem( pFdoDataProp->GetName() )->SmartCast<FdoSmLpDataPropertyDefinition>(true);
- if ( pLpDataProp )
+ if ( pLpDataProp ) {
+ // If class shares table with base class then unique constraints on base properties are not allowed,
+ // since these would prevent multiple objects from being added to base class or
+ // other classes derived from it.
+ if ( (Get_TableMapping() == FdoSmOvTableMappingType_BaseTable) && (pLpDataProp->GetBaseProperty()) )
+ AddUkeyBasePropError( pFdoDataProp );
pLpUniqueC->GetProperties()->Add( pLpDataProp );
- else
+ }
+ else {
AddUkeyPropMissingError( pFdoDataProp );
+ }
}
if ( pFdoUniqueCs->GetCount() != 0 )
@@ -1853,7 +1862,9 @@
FdoSmLpUniqueConstraintsP pLpUniqueConstraintsB = mBaseClass->GetUniqueConstraints();
for ( int j = 0; j < pLpUniqueConstraintsB->GetCount(); j++ ) {
FdoSmLpUniqueConstraintP pLpUniqueC = pLpUniqueConstraintsB->GetItem(j);
- pLpUniqueConstraints->Add( pLpUniqueC );
+ FdoSmLpUniqueConstraintP pLpInhUniqueC = pLpUniqueC->CreateInherited( this, mProperties );
+ if ( pLpInhUniqueC )
+ pLpUniqueConstraints->Add( pLpInhUniqueC );
}
}
}
@@ -1902,6 +1913,26 @@
return found;
}
+void FdoSmLpClassBase::MatchInheritedUkey( FdoSmLpUniqueConstraintP ukey )
+{
+ if ( mBaseClass ) {
+ FdoSmLpUniqueConstraintsP baseUkeys = mBaseClass->GetUniqueConstraints();
+ FdoInt32 idx;
+
+ // Check each constraint from the base class
+ for ( idx = 0; idx < baseUkeys->GetCount(); idx++ ) {
+ FdoSmLpUniqueConstraintP baseUkey = baseUkeys->GetItem(idx);
+
+ if ( ukey->Compare(baseUkey) == 0 ) {
+ // Same as given constraint so given constraint is inherited from base constraint.
+ ukey->SetBaseConstraint( baseUkey );
+ break;
+ }
+ }
+ }
+}
+
+
bool FdoSmLpClassBase::HasUkey( FdoSmPhColumnsP pPhColls )
{
FdoSmLpUniqueConstraintsP pLpUniqueConstraints = GetUniqueConstraints();
@@ -3177,6 +3208,19 @@
);
}
+void FdoSmLpClassBase::AddUkeyBasePropError(FdoDataPropertyDefinition* pProp)
+{
+ GetErrors()->Add( FdoSmErrorType_Other,
+ FdoSchemaException::Create(
+ FdoSmError::NLSGetMessage(
+ FDO_NLSID(FDOSM_29),
+ (FdoString*)(GetQName()),
+ (FdoString*)(pProp->GetName())
+ )
+ )
+ );
+}
+
void FdoSmLpClassBase::XMLSerialize( FILE* xmlFp, int ref ) const
{
if ( ref == 0 ) {
Modified: trunk/Utilities/SchemaMgr/Src/Sm/Lp/SchemaCollection.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Lp/SchemaCollection.cpp 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Lp/SchemaCollection.cpp 2007-01-19 19:24:27 UTC (rev 640)
@@ -796,30 +796,51 @@
// UNIQUE() constraints : Load from the database
///////////////////////////////////////////////////////////////////////////
- FdoSmLpUniqueConstraintCollection* uLpUKeys = (FdoSmLpUniqueConstraintCollection *)((FdoSmLpClassBase *)pLpClassDef)->RefUniqueConstraints();
- FdoPtr<FdoUniqueConstraintCollection> pFdoUKeys = pFdoClassDef->GetUniqueConstraints();
- FdoPropertiesP pFdoProps = pFdoClassDef->GetProperties();
+ FdoSmLpUniqueConstraintCollection* uLpUKeys = (FdoSmLpUniqueConstraintCollection *)((FdoSmLpClassBase *)pLpClassDef)->RefUniqueConstraints();
+ FdoPtr<FdoUniqueConstraintCollection> pFdoUKeys = pFdoClassDef->GetUniqueConstraints();
+ FdoPropertiesP pFdoProps = pFdoClassDef->GetProperties();
+ FdoPtr<FdoReadOnlyPropertyDefinitionCollection> pFdoBaseProps = pFdoClassDef->GetBaseProperties();
for ( int i = 0; i < uLpUKeys->GetCount(); i++ ) {
FdoSmLpUniqueConstraintP pLpUniqueC = uLpUKeys->GetItem(i);
- FdoSmLpDataPropertiesP pLpProps = pLpUniqueC->GetProperties();
- // New constraints
- FdoPtr<FdoUniqueConstraint> pFdoUniqueC = FdoUniqueConstraint::Create();
- FdoDataPropertiesP pFdoUniqueProps = pFdoUniqueC->GetProperties();
+ // Skip inherited constraints since already defined on base class.
+ if ( !pLpUniqueC->GetBaseConstraint() ) {
+ FdoSmLpDataPropertiesP pLpProps = pLpUniqueC->GetProperties();
- for ( int j = 0; j < pLpProps->GetCount(); j++ ) {
- FdoSmLpDataPropertyP pLpProp = pLpProps->GetItem(j);
-
- // Find the Fdo data property
- FdoDataPropertyP pFdoProp = (FdoDataPropertyDefinition *)pFdoProps->FindItem(pLpProp->GetName());
-
- // Match the names and add to collection
- if ( pFdoProp && ( wcscmp(pLpProp->GetName(), pFdoProp->GetName()) == 0 ) )
- pFdoUniqueProps->Add( pFdoProp );
- }
- if ( pFdoUniqueProps->GetCount() != 0 )
- pFdoUKeys->Add(pFdoUniqueC);
+ // New constraints
+ FdoPtr<FdoUniqueConstraint> pFdoUniqueC = FdoUniqueConstraint::Create();
+ FdoDataPropertiesP pFdoUniqueProps = pFdoUniqueC->GetProperties();
+ bool constraintOk = true;
+
+ for ( int j = 0; j < pLpProps->GetCount(); j++ ) {
+ FdoSmLpDataPropertyP pLpProp = pLpProps->GetItem(j);
+
+ // Find the Fdo data property
+ FdoDataPropertyP pFdoProp = (FdoDataPropertyDefinition *)pFdoProps->FindItem(pLpProp->GetName());
+
+ // Match the names and add to collection
+ if ( pFdoProp && ( wcscmp(pLpProp->GetName(), pFdoProp->GetName()) == 0 ) ) {
+ pFdoUniqueProps->Add( pFdoProp );
+ }
+ else {
+ try {
+ pFdoProp = (FdoDataPropertyDefinition *)pFdoBaseProps->GetItem(pLpProp->GetName());
+ }
+ catch (...) {
+ }
+
+ if ( pFdoProp && ( wcscmp(pLpProp->GetName(), pFdoProp->GetName()) == 0 ) ) {
+ pFdoUniqueProps->Add( pFdoProp );
+ }
+ else {
+ constraintOk = false;
+ }
+ }
+ }
+ if ( constraintOk && (pFdoUniqueProps->GetCount() != 0) )
+ pFdoUKeys->Add(pFdoUniqueC);
+ }
}
///////////////////////////////////////////////////////////////////////////
Modified: trunk/Utilities/SchemaMgr/Src/Sm/Lp/UniqueConstraint.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Lp/UniqueConstraint.cpp 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Lp/UniqueConstraint.cpp 2007-01-19 19:24:27 UTC (rev 640)
@@ -22,6 +22,37 @@
mProperties = new FdoSmLpDataPropertyDefinitionCollection();
}
+FdoPtr<FdoSmLpUniqueConstraint> FdoSmLpUniqueConstraint::CreateInherited( FdoSmLpClassBase* pSubClass, FdoSmLpPropertyDefinitionCollection* pSubClassProperties )
+{
+ // Create the inherited constaint, making this constraint the base
+ FdoPtr<FdoSmLpUniqueConstraint> inheritedConstraint = new FdoSmLpUniqueConstraint();
+ inheritedConstraint->SetBaseConstraint( FDO_SAFE_ADDREF(this) );
+
+ // Set the inherited constaint's properties to the sub-class equivalents of the base constraint
+ // properties.
+ FdoSmLpDataPropertiesP baseProperties = GetProperties();
+ FdoSmLpDataPropertiesP subProperties = inheritedConstraint->GetProperties();
+
+ FdoInt32 idx;
+ bool propNotFound = false;
+
+ for ( idx = 0; idx < baseProperties->GetCount(); idx++ ) {
+ FdoSmLpDataPropertyP baseProperty = baseProperties->GetItem( idx );
+ FdoSmLpPropertyP subProperty = pSubClassProperties->FindItem( baseProperty->GetName() );
+
+ if ( subProperty && (subProperty->GetPropertyType() == FdoPropertyType_DataProperty) )
+ subProperties->Add( (FdoSmLpDataPropertyDefinition*)(subProperty.p) );
+ else
+ // Property not in subclass so can't inherit constraint.
+ propNotFound = true;
+ }
+
+ if ( propNotFound )
+ inheritedConstraint = NULL;
+
+ return inheritedConstraint;
+}
+
FdoSmLpDataPropertyDefinitionCollection *FdoSmLpUniqueConstraint::GetProperties()
{
return FDO_SAFE_ADDREF(mProperties.p);
@@ -32,6 +63,44 @@
return mProperties.p;
}
+FdoPtr<FdoSmLpUniqueConstraint> FdoSmLpUniqueConstraint::GetBaseConstraint()
+{
+ return mBaseConstraint;
+}
+
+FdoInt32 FdoSmLpUniqueConstraint::Compare( FdoPtr<FdoSmLpUniqueConstraint> other ) const
+{
+ FdoInt32 result = -1;
+
+ const FdoSmLpDataPropertyDefinitionCollection* myProps = RefProperties();
+ const FdoSmLpDataPropertyDefinitionCollection* otherProps = other->RefProperties();
+
+ if ( myProps->GetCount() == otherProps->GetCount() ) {
+ FdoInt32 idx;
+ result = 0;
+
+ for ( idx = 0; idx < myProps->GetCount(); idx++ ) {
+ const FdoSmLpDataPropertyDefinition* myProp = myProps->RefItem(idx);
+ if ( !otherProps->RefItem(myProp->GetName()) ) {
+ result = -1;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+const FdoSmLpUniqueConstraint* FdoSmLpUniqueConstraint::RefBaseConstraint() const
+{
+ return ( ((FdoSmLpUniqueConstraint*) this)->GetBaseConstraint().p );
+}
+
+void FdoSmLpUniqueConstraint::SetBaseConstraint( FdoPtr<FdoSmLpUniqueConstraint> baseConstraint )
+{
+ mBaseConstraint = baseConstraint;
+}
+
void FdoSmLpUniqueConstraint::Dispose()
{
delete this;
Modified: trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp
===================================================================
--- trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/SchemaMgr/Src/Sm/Ph/Table.cpp 2007-01-19 19:24:27 UTC (rev 640)
@@ -1029,6 +1029,9 @@
void FdoSmPhTable::LoadCkeys( FdoSmPhReaderP ckeyRdr, bool isSkipAdd )
{
+ FdoStringP ckeyNameCurr;
+ FdoSmPhCheckConstraintP ckeyCurr;
+
// read each check constraint column.
while (ckeyRdr && ckeyRdr->ReadNext() ) {
@@ -1047,11 +1050,27 @@
if ( GetElementState() != FdoSchemaElementState_Deleted )
AddCkeyColumnError( columnName );
}
- if( ! isSkipAdd ) {
- FdoSmPhCheckConstraintP pConstr = new FdoSmPhCheckConstraint( ckeyName, columnName, clause );
- mCkeysCollection->Add( pConstr );
+
+ if( ! isSkipAdd ) {
+ if ( ckeyName != ckeyNameCurr ) {
+ if ( ckeyCurr )
+ mCkeysCollection->Add( ckeyCurr );
+
+ ckeyCurr = new FdoSmPhCheckConstraint( ckeyName, columnName, clause );
+ }
+ else {
+ // FDO does not support multi-column value constraints.
+ // Also, Schema Manager is not yet set up to handle them so skip them.
+ ckeyCurr = NULL;
+ }
}
+
+ ckeyNameCurr = ckeyName;
}
+
+ // Add the last constraint
+ if ( ckeyCurr && ! isSkipAdd )
+ mCkeysCollection->Add( ckeyCurr );
}
Modified: trunk/Utilities/TestCommon/Inc/TestCommonConstraints.h
===================================================================
--- trunk/Utilities/TestCommon/Inc/TestCommonConstraints.h 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/TestCommon/Inc/TestCommonConstraints.h 2007-01-19 19:24:27 UTC (rev 640)
@@ -31,6 +31,7 @@
CPPUNIT_TEST( TestDescribeUpdatedConstraints );
CPPUNIT_TEST( TestRestrictCheckConstraints );
CPPUNIT_TEST( TestDateTimeConstraints );
+ CPPUNIT_TEST( TestBaseReferences );
CPPUNIT_TEST_SUITE_END();
@@ -43,6 +44,9 @@
virtual void TestRestrictCheckConstraints(void);
virtual void TestDateTimeConstraints(void);
+ // Tests unique constraints that reference base properties.
+ virtual void TestBaseReferences(void);
+
void CreateConstraintsSchema(FdoIConnection * connection);
void DescribeConstraintsSchema(FdoIConnection * connection, FdoString *className, int numUkeys, int numCkeys, bool afterUpdate);
void UpdateCheckConstraints(FdoIConnection * connection);
Modified: trunk/Utilities/TestCommon/Src/TestCommonConstraints.cpp
===================================================================
--- trunk/Utilities/TestCommon/Src/TestCommonConstraints.cpp 2007-01-19 18:55:21 UTC (rev 639)
+++ trunk/Utilities/TestCommon/Src/TestCommonConstraints.cpp 2007-01-19 19:24:27 UTC (rev 640)
@@ -27,6 +27,7 @@
#define SCHEMA_NAME L"constraints"
#define CLASS_NAME L"cdataclass" // lower case to compensate for MySQl on Linux
#define CLASS_NAME_BASE L"CDataBaseClass"
+#define CLASS_NAME_SUB L"CDataSubClass"
#define PROP_FEATID L"FeatureId"
@@ -431,6 +432,338 @@
}
}
+void TestCommonConstraints::TestBaseReferences ()
+{
+ FdoPtr<FdoIConnection> connection;
+
+ try
+ {
+ // delete, re-create and open the datastore
+ printf( "Initializing Connection ... \n" );
+ connection = CreateConnection( true );
+
+ printf( "Creating Constraints Schema ... \n" );
+
+ FdoPtr<FdoISchemaCapabilities> schemaCap = connection->GetSchemaCapabilities();
+
+ if ( schemaCap->SupportsUniqueValueConstraints() && schemaCap->SupportsCompositeUniqueValueConstraints() ) {
+ FdoPtr<FdoIApplySchema> pCmd = (FdoIApplySchema*) connection->CreateCommand(FdoCommandType_ApplySchema);
+
+ FdoFeatureSchemasP pSchemas = FdoFeatureSchemaCollection::Create(NULL);
+
+ FdoPtr<FdoFeatureSchema> pSchema = FdoFeatureSchema::Create( SCHEMA_NAME, L"AutoCAD schema" );
+ pSchemas->Add( pSchema );
+
+ FdoPtr<FdoFeatureClass> pCData = FdoFeatureClass::Create( CLASS_NAME_BASE, L"Constraints" );
+ pCData->SetIsAbstract(false);
+
+ FdoPtr<FdoDataPropertyDefinition> pProp = FdoDataPropertyDefinition::Create( PROP_FEATID, L"" );
+ pProp->SetDataType( FdoDataType_Int32 );
+ pProp->SetNullable(false);
+ FdoPropertiesP(pCData->GetProperties())->Add( pProp );
+ FdoDataPropertiesP(pCData->GetIdentityProperties())->Add( pProp );
+
+ //// Add the class to schema
+ FdoClassesP(pSchema->GetClasses())->Add( pCData );
+
+ FdoClassDefinitionP pClass = FdoClassesP( pSchema->GetClasses() )->GetItem( CLASS_NAME_BASE );
+
+ ////////////// 1st unique property - single ///////////////
+ FdoPtr<FdoDataPropertyDefinition> pUnique1Int = FdoDataPropertyDefinition::Create( PROP_UNIQUE1, L"" );
+ pUnique1Int->SetDataType( FdoDataType_Int32 );
+ pUnique1Int->SetNullable(true);
+ FdoPropertiesP(pCData->GetProperties())->Add( pUnique1Int );
+
+ ////////////// 2nd unique property - Composite ///////////////
+ FdoPtr<FdoDataPropertyDefinition> pUnique21Int = FdoDataPropertyDefinition::Create( PROP_UNIQUE2_1, L"" );
+ pUnique21Int->SetDataType( FdoDataType_Int32 );
+ pUnique21Int->SetNullable(true);
+ FdoPropertiesP(pCData->GetProperties())->Add( pUnique21Int );
+
+ // Create a new class based on the previous ...
+ FdoPtr<FdoFeatureClass> pCDataDerived = FdoFeatureClass::Create( CLASS_NAME, L"Constraits" );
+ pCDataDerived->SetBaseClass( pCData );
+ pCDataDerived->SetIsAbstract(false);
+ FdoPtr<FdoUniqueConstraintCollection> constraints = pCDataDerived->GetUniqueConstraints();
+
+ //// Add the class to schema
+ FdoClassesP(pSchema->GetClasses())->Add( pCDataDerived );
+
+ // Create constaint on base property
+ FdoPtr<FdoUniqueConstraint> newUniqueConstr1 = FdoUniqueConstraint::Create();
+ FdoPtr<FdoDataPropertyDefinitionCollection> pDataPropColl = newUniqueConstr1->GetProperties();
+ pDataPropColl->Add( pUnique1Int );
+ constraints->Add( newUniqueConstr1 );
+
+ FdoPtr<FdoDataPropertyDefinition> pUnique22Int = FdoDataPropertyDefinition::Create( PROP_UNIQUE2_2, L"" );
+ pUnique22Int->SetDataType( FdoDataType_Int32 );
+ pUnique22Int->SetNullable(true);
+ FdoPropertiesP(pCDataDerived->GetProperties())->Add( pUnique22Int );
+
+ // Create composite constraint on property and base property.
+ FdoPtr<FdoUniqueConstraint> newUniqueConstr2 = FdoUniqueConstraint::Create();
+ pDataPropColl = newUniqueConstr2->GetProperties();
+ pDataPropColl->Add( pUnique21Int );
+ pDataPropColl->Add( pUnique22Int );
+ constraints->Add( newUniqueConstr2 );
+
+ // Create a new class based on the previous ...
+ FdoPtr<FdoFeatureClass> pCDataSubDerived = FdoFeatureClass::Create( CLASS_NAME_SUB, L"Constraits" );
+ pCDataSubDerived->SetBaseClass( pCDataDerived);
+ pCDataSubDerived->SetIsAbstract(false);
+ constraints = pCDataSubDerived->GetUniqueConstraints();
+
+ //// Add the class to schema
+ FdoClassesP(pSchema->GetClasses())->Add( pCDataSubDerived );
+
+ // Create duplicate constaint on base property (should disappear on DescribeSchema)
+ newUniqueConstr1 = FdoUniqueConstraint::Create();
+ pDataPropColl = newUniqueConstr1->GetProperties();
+ pDataPropColl->Add( pUnique1Int );
+ constraints->Add( newUniqueConstr1 );
+
+ // Create constraint on subset of properties from a base class constraint - OK.
+ newUniqueConstr2 = FdoUniqueConstraint::Create();
+ pDataPropColl = newUniqueConstr2->GetProperties();
+ pDataPropColl->Add( pUnique22Int );
+ constraints->Add( newUniqueConstr2 );
+
+ ///////// Done.
+ pCmd->SetFeatureSchema( pSchema );
+ pCmd->Execute();
+
+ FdoPtr<FdoIInsert> insertCmd;
+
+ // This should succeed
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME_BASE,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection,CLASS_NAME_BASE),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 1000,
+ (FdoString*) NULL
+ );
+
+ // Unique constraint not on base class so should succeed.
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME_BASE,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME_BASE),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 1000,
+ (FdoString*) NULL
+ );
+
+ // This should succeed
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 2000,
+ (FdoString*) NULL
+ );
+
+ bool uniqueSuccess1 = true;
+ try {
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 2000,
+ (FdoString*) NULL
+ );
+ } catch (FdoException *ex) {
+ DBG(printf("Expected unique constraint violation exception: %ls", (FdoString* )ex->GetExceptionMessage()));
+ ex->Release();
+ uniqueSuccess1 = false;
+ }
+ CPPUNIT_ASSERT_MESSAGE("Should get unique constraint violation prop #4", uniqueSuccess1 == false );
+
+ // This should succeed
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME_BASE,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME_BASE),
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 1000,
+ (FdoString*) NULL
+ );
+
+ // Unique constraint not on base class so should succeed.
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME_BASE,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME_BASE),
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 1000,
+ (FdoString*) NULL
+ );
+
+ // This should succeed
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 1000,
+ PROP_UNIQUE2_2, FdoDataType_Int32, (FdoInt32) 2000,
+ (FdoString*) NULL
+ );
+
+ bool uniqueSuccess2 = true;
+
+ try {
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 1000,
+ PROP_UNIQUE2_2, FdoDataType_Int32, (FdoInt32) 2000,
+ (FdoString*) NULL
+ );
+
+ } catch (FdoException *ex) {
+ DBG(printf("Expected unique constraint violationexception: %ls", (FdoString* )ex->GetExceptionMessage()));
+ ex->Release();
+ uniqueSuccess2 = false;
+ }
+
+ CPPUNIT_ASSERT_MESSAGE("Should get unique constraint violation prop #[5,6]", uniqueSuccess2 == false );
+
+ // This should succeed
+
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 3000,
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 2000,
+ PROP_UNIQUE2_2, FdoDataType_Int32, (FdoInt32) 2000,
+ (FdoString*) NULL
+ );
+
+ // This should succeed
+
+ TestCommonMiscUtil::InsertObject(
+ connection,
+ insertCmd,
+ SCHEMA_NAME,
+ CLASS_NAME,
+ PROP_FEATID, FdoDataType_Int32, GetNextFeatId(connection, CLASS_NAME),
+ PROP_UNIQUE1, FdoDataType_Int32, (FdoInt32) 4000,
+ PROP_UNIQUE2_1, FdoDataType_Int32, (FdoInt32) 1000,
+ PROP_UNIQUE2_2, FdoDataType_Int32, (FdoInt32) 3000,
+ (FdoString*) NULL
+ );
+
+ FdoPtr<FdoIDescribeSchema> pDescCmd = (FdoIDescribeSchema*) connection->CreateCommand(FdoCommandType_DescribeSchema);
+
+ pDescCmd->SetSchemaName( SCHEMA_NAME );
+ FdoPtr<FdoFeatureSchemaCollection> pSchemas2 = pDescCmd->Execute();
+ FdoPtr<FdoFeatureSchema> pSchema2 = pSchemas2->GetItem( SCHEMA_NAME );
+ FdoPtr<FdoClassCollection> pClasses2 = pSchema2->GetClasses();
+ FdoPtr<FdoClassDefinition> pClass2 = pClasses2->GetItem( CLASS_NAME );
+ FdoPtr<FdoClassDefinition> pClassBase2 = pClass2->GetBaseClass();
+ FdoPtr<FdoClassDefinition> pClassSub2 = pClasses2->GetItem( CLASS_NAME_SUB );
+
+ ///////////////// UNIQUE() CONSTRAINTS //////////////////////////////////////////
+ FdoPtr<FdoUniqueConstraintCollection> pUniqueCs = pClass2->GetUniqueConstraints();
+
+ int count = 0;
+ bool found_unique1 = false;
+ bool found_unique2 = false;
+ bool found_unique3 = false;
+
+ for ( int i = 0; i < pUniqueCs->GetCount(); i++ ) {
+ FdoPtr<FdoUniqueConstraint> pUniqueC = pUniqueCs->GetItem(i);
+ FdoDataPropertiesP pProps = pUniqueC->GetProperties();
+
+ printf("Unique key #%d:\n", i);
+
+ for ( int j = 0; j < pProps->GetCount(); j++ ) {
+ FdoDataPropertyP pProp = pProps->GetItem(j);
+
+ printf("\t%d %ls\n", j, pProp->GetName());
+ count++;
+
+ if ( wcscmp(pProp->GetName(), PROP_UNIQUE1 ) == 0 )
+ found_unique1 = true;
+ else if ( wcscmp(pProp->GetName(), PROP_UNIQUE2_1 ) == 0 )
+ found_unique2 = true;
+ else if ( wcscmp(pProp->GetName(), PROP_UNIQUE2_2 ) == 0 )
+ found_unique3 = true;
+ }
+ }
+
+ CPPUNIT_ASSERT_MESSAGE("Wrong number of unique keys", count == 3 );
+ CPPUNIT_ASSERT_MESSAGE("Unique keys properties not found", found_unique1 && found_unique2 && found_unique3);
+
+ // None of the unique constraints on derived class should find their way to the base
+ // class.
+ pUniqueCs = pClassBase2->GetUniqueConstraints();
+ CPPUNIT_ASSERT_MESSAGE("Base class has unique keys", pUniqueCs->GetCount() == 0 );
+
+ // Sub class should have on 1 constraint (one with subset of properties). Duplicate
+ // constraint should disappear
+ pUniqueCs = pClassSub2->GetUniqueConstraints();
+ CPPUNIT_ASSERT_MESSAGE("Sub class does not have 1 unique key", pUniqueCs->GetCount() == 1 );
+ FdoPtr<FdoUniqueConstraint> pUniqueC = pUniqueCs->GetItem(0);
+ FdoDataPropertiesP pProps = pUniqueC->GetProperties();
+ CPPUNIT_ASSERT_MESSAGE("Sub class unique key does not have 1 property ", pProps->GetCount() == 1 );
+ pProp = pProps->GetItem(0);
+ CPPUNIT_ASSERT( wcscmp(pProp->GetName(), PROP_UNIQUE2_2) == 0);
+
+ printf( "Closing Connection ... \n" );
+
+ connection->Close();
+ }
+ }
+ catch ( FdoException* e )
+ {
+ try {
+ if ( connection) connection->Close();
+ }
+ catch ( ... )
+ {
+ }
+ TestCommonFail( e );
+ }
+ catch ( CppUnit::Exception e )
+ {
+ try {
+ if ( connection) connection->Close();
+ }
+ catch ( ... )
+ {
+ }
+ throw;
+ }
+ catch (...)
+ {
+ try {
+ if ( connection) connection->Close();
+ }
+ catch ( ... )
+ {
+ }
+
+ CPPUNIT_FAIL ("caught unexpected exception");
+ }
+}
+
void TestCommonConstraints::CreateConstraintsSchema( FdoIConnection* connection )
{
FdoPtr<FdoISchemaCapabilities> schemaCap = connection->GetSchemaCapabilities();
@@ -951,7 +1284,6 @@
pDescCmd->SetSchemaName( SCHEMA_NAME );
FdoPtr<FdoFeatureSchemaCollection> pSchemas2 = pDescCmd->Execute();
-pSchemas2->WriteXml( L"constraints.xml" );
FdoPtr<FdoFeatureSchema> pSchema2 = pSchemas2->GetItem( SCHEMA_NAME );
FdoPtr<FdoClassCollection> pClasses2 = pSchema2->GetClasses();
FdoPtr<FdoClassDefinition> pClass2 = pClasses2->GetItem( className );
More information about the fdo-commits
mailing list