FdoSchemaManagerP OdbcStaticConnection::CreateSchemaManager() { FdoSchemaManagerP schMgr = new FdoOdbcSchemaManager(m_gdbi_conn, (FdoString*) FdoStringP(mDatastore)); FdoSmPhOdbcMgrP physMgr = schMgr->GetPhysicalSchema()->SmartCast<FdoSmPhOdbcMgr>(); // Pass down the location of the COM directory for MetaSchema creation scripts. physMgr->SetHomeDir( FdoStringP(L"Dbg/com") ); physMgr->SetRdbiContext( m_rdbi_context ); return schMgr; }
void MySqlFdoInsertTest::characterSets() { StaticConnection* conn = new MySqlStaticConnection(); try { UnitTestUtil::SetProvider( conn->GetServiceName() ); conn->connect(); FdoSchemaManagerP mgr = conn->CreateSchemaManager(); FdoSmPhMgrP phMgr = mgr->GetPhysicalSchema(); FdoStringP datastore = phMgr->GetDcOwnerName( UnitTestUtil::GetEnviron("datastore", CHARSET_SUFFIX) ); FdoSmPhDatabaseP database = phMgr->GetDatabase(); FdoSmPhOwnerP owner = phMgr->FindOwner( datastore, L"", false ); if ( owner ) { owner->SetElementState( FdoSchemaElementState_Deleted ); owner->Commit(); } owner = database->CreateOwner( datastore, false ); owner->SetPassword( L"test" ); owner->Commit(); owner->SetCurrent(); FdoSmPhGrdMgrP grdMgr = phMgr->SmartCast<FdoSmPhGrdMgr>(); GdbiConnection* gdbiConnection = grdMgr->GetGdbiConnection(); // Create tables for various combinations of character set and types of characters // that will be stored in the table. charSetCreateTable( gdbiConnection, L"latin1", L"ascii7" ); charSetCreateTable( gdbiConnection, L"latin1", L"8bit" ); charSetCreateTable( gdbiConnection, L"utf8", L"ascii7" ); charSetCreateTable( gdbiConnection, L"utf8", L"8bit" ); charSetCreateTable( gdbiConnection, L"utf8", L"japan" ); charSetCreateTable( gdbiConnection, L"ucs2", L"ascii7" ); charSetCreateTable( gdbiConnection, L"ucs2", L"8bit" ); charSetCreateTable( gdbiConnection, L"ucs2", L"japan" ); charSetCreateTable( gdbiConnection, L"cp932", L"ascii7" ); charSetCreateTable( gdbiConnection, L"cp932", L"japan" ); phMgr = NULL; mgr = NULL; conn->disconnect(); delete conn; conn = NULL; // A couple of combinations are not tried: // - latin11 character set, Japanese characters // = cp932 character set, 8 bit characters // since these are expected to fail (characters not in character set). FdoPtr<FdoIConnection> connection = UnitTestUtil::GetConnection(CHARSET_SUFFIX, false); // Round-trip insert/select test each table. charSetTestTable( connection, L"latin1", L"ascii7", L"abc", L"a" ); charSetTestTable( connection, L"latin1", L"8bit", L"\x00e4\x00e5", L"\x00e4" ); charSetTestTable( connection, L"utf8", L"ascii7", L"abc", L"a" ); charSetTestTable( connection, L"utf8", L"8bit", L"\x00e4\x00e5", L"\x00e4" ); charSetTestTable( connection, L"utf8", L"japan", L"\x30b0\x30b1", L"\x30b0" ); charSetTestTable( connection, L"ucs2", L"ascii7", L"abc", L"a" ); charSetTestTable( connection, L"ucs2", L"8bit", L"\x00e4\x00e5", L"\x00e4" ); charSetTestTable( connection, L"ucs2", L"japan", L"\x30b0\x30b1", L"\x30b0" ); charSetTestTable( connection, L"cp932", L"ascii7", L"abc", L"a" ); charSetTestTable( connection, L"cp932", L"japan", L"\x30b0\x30b1", L"\x30b0" ); } catch (FdoCommandException *ex) { if (conn) { conn->disconnect(); delete conn; } UnitTestUtil::FailOnException(ex); } catch (FdoException *ex) { if (conn) { conn->disconnect(); delete conn; } UnitTestUtil::FailOnException(ex); } }
void MySqlFdoInsertTest::insertBoundaryUnsigned() { StaticConnection* conn = new MySqlStaticConnection(); try { UnitTestUtil::SetProvider( conn->GetServiceName() ); conn->connect(); FdoSchemaManagerP mgr = conn->CreateSchemaManager(); FdoSmPhMgrP phMgr = mgr->GetPhysicalSchema(); FdoStringP datastore = phMgr->GetDcOwnerName( UnitTestUtil::GetEnviron("datastore", UNSIGNED_SUFFIX) ); FdoSmPhDatabaseP database = phMgr->GetDatabase(); FdoSmPhOwnerP owner = phMgr->FindOwner( datastore, L"", false ); if ( owner ) { owner->SetElementState( FdoSchemaElementState_Deleted ); owner->Commit(); } owner = database->CreateOwner( datastore, false ); owner->SetPassword( L"test" ); FdoStringP tableName = L"unsigned_test"; FdoSmPhTableP table = owner->CreateTable( tableName ); table->SetPkeyName( tableName + L"_key" ); FdoSmPhColumnP column = table->CreateColumnInt32( L"id", false ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnUnknown( L"uint_column", L"int unsigned", false, 0, 0 ); owner->Commit(); phMgr = NULL; mgr = NULL; conn->disconnect(); delete conn; conn = NULL; FdoPtr<FdoIConnection> connection = UnitTestUtil::GetConnection(UNSIGNED_SUFFIX, false); FdoPtr<FdoITransaction> featureTransaction = connection->BeginTransaction(); FdoPtr<FdoIInsert> insertCommand = (FdoIInsert *) connection->CreateCommand(FdoCommandType_Insert); insertCommand->SetFeatureClassName(tableName); FdoPtr<FdoPropertyValueCollection> propertyValues = insertCommand->GetPropertyValues(); FdoPtr<FdoDataValue> dataValue; dataValue = FdoDataValue::Create(L"1"); FdoPtr<FdoPropertyValue> propertyValue = AddNewProperty( propertyValues, L"id"); propertyValue->SetValue(dataValue); dataValue = FdoDataValue::Create(L"0"); propertyValue = AddNewProperty( propertyValues, L"uint_column"); propertyValue->SetValue(dataValue); FdoPtr<FdoIFeatureReader> reader = insertCommand->Execute(); dataValue = FdoDataValue::Create(L"2"); propertyValue = AddNewProperty( propertyValues, L"id"); propertyValue->SetValue(dataValue); dataValue = FdoDataValue::Create(L"4294967295"); propertyValue = AddNewProperty( propertyValues, L"uint_column"); propertyValue->SetValue(dataValue); reader = insertCommand->Execute(); featureTransaction->Commit(); // check FdoPtr<FdoISelect> selectCmd = (FdoISelect *) connection->CreateCommand(FdoCommandType_Select); selectCmd->SetFeatureClassName(tableName); FdoPtr<FdoIFeatureReader> featureReader = selectCmd->Execute(); FdoInt32 rowCount = 0; while ( featureReader->ReadNext() ) { rowCount++; switch ( featureReader->GetInt32(L"id") ) { case 1: CPPUNIT_ASSERT ( featureReader->GetInt64(L"uint_column") == 0 ); break; case 2: CPPUNIT_ASSERT ( featureReader->GetInt64(L"uint_column") == 4294967295LL); break; } } CPPUNIT_ASSERT( rowCount == 2 ); } catch (FdoCommandException *ex) { if (conn) { conn->disconnect(); delete conn; } UnitTestUtil::FailOnException(ex); } catch (FdoException *ex) { if (conn) { conn->disconnect(); delete conn; } UnitTestUtil::FailOnException(ex); } }
// Tests the creating of unique constraints that are too large for // MySQL. Verifies that the MySQL provider properly truncates // constraint columns to get the total size within the maximum allowed. void MySqlSchemaMgrTests::testWideConstraint () { StaticConnection* conn = CreateStaticConnection(); FdoPtr<FdoIConnection> fdoConn; FdoInt32 ix; try { char prvenv[100]; FdoStringP providerName = conn->GetServiceName(); sprintf( prvenv, "provider=%ls", (FdoString*) providerName ); #ifdef _WIN32 _putenv( prvenv ); #else putenv( prvenv ); #endif // Sets the other env. UnitTestUtil::SetProvider( conn->GetServiceName() ); printf( "\nOpening Connection ...\n" ); conn->connect(); FdoSchemaManagerP mgr = conn->CreateSchemaManager(); FdoSmPhGrdMgrP phMgr = mgr->GetPhysicalSchema()->SmartCast<FdoSmPhGrdMgr>(); FdoSmPhDatabaseP database = phMgr->GetDatabase(); printf( "Predeleting schema ...\n" ); FdoStringP datastore = phMgr->GetDcOwnerName( UnitTestUtil::GetEnviron("datastore", DB_NAME_SUFFIX) ); FdoSmPhOwnerP owner = phMgr->FindOwner( datastore, L"", false ); if ( owner ) { owner->SetElementState( FdoSchemaElementState_Deleted ); owner->Commit(); } printf( "Creating schema ...\n" ); owner = database->CreateOwner( datastore, false ); owner->SetPassword( L"test" ); owner->Commit(); FdoInt32 charLen = (FdoInt32)(owner->SmartCast<FdoSmPhMySqlOwner>()->GetCharacterSet()->SmartCast<FdoSmPhMySqlCharacterSet>()->GetCharLen()); // Table1 tests various column types and constraints // with various numbers and sizes of columns. // Primary Keys, indexes and unique constraints are tested. FdoSmPhTableP table = owner->CreateTable( phMgr->GetDcDbObjectName(L"TABLE1" )); FdoSmPhColumnP column = table->CreateColumnInt32( L"ID", false ); table->AddPkeyCol( column->GetName() ); // Columns of various types (tested by adding to primary key) column = table->CreateColumnBLOB( L"BLOB_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnChar( L"STRING_COLUMN", false, 50 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnSingle( L"SINGLE_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDouble( L"DOUBLE_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL_COLUMN", true, 65, 0 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnBool( L"BOOL_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnByte( L"BYTE_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnInt16( L"INT16_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnInt32( L"INT32_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnInt64( L"INT64_COLUMN", true ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDate( L"DATE_COLUMN", true ); table->AddPkeyCol( column->GetName() ); AddProviderColumns( table ); column = table->GetColumns()->GetItem( L"BINARY_COLUMN" ); table->AddPkeyCol( column->GetName() ); column = table->GetColumns()->GetItem( L"MEDIUMBLOB_COLUMN" ); column = table->GetColumns()->GetItem( L"TINYBLOB_COLUMN" ); column = table->GetColumns()->GetItem( L"VARBINARY_COLUMN" ); table->AddPkeyCol( column->GetName() ); column = table->GetColumns()->GetItem( L"DATE2_COLUMN" ); table->AddPkeyCol( column->GetName() ); column = table->GetColumns()->GetItem( L"TIMESTAMP_COLUMN" ); table->AddPkeyCol( column->GetName() ); // Columns of various length. column = table->CreateColumnChar( L"STRING100000", false, 100000 ); column = table->CreateColumnChar( L"STRING2000", false, 2000 ); column = table->CreateColumnChar( L"STRING700_1", false, 700 ); column = table->CreateColumnChar( L"STRING700_2", false, 700 ); for ( ix = 0; ix < 10; ix++ ) { column = table->CreateColumnChar( FdoStringP::Format(L"STRING300_%d", ix + 1), false, 300 ); } for ( ix = 0; ix < 10; ix++ ) { column = table->CreateColumnChar( FdoStringP::Format(L"STRING100_%d", ix + 1), false, 100 ); } for ( ix = 0; ix < 10; ix++ ) { column = table->CreateColumnChar( FdoStringP::Format(L"STRING40_%d", ix + 1), false, 40 ); } // Various unique constraints // One large (will be truncated) column, one small (not truncated) FdoSmPhColumnsP ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100000" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100_1" ); // Two large, one small. ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING2000" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING700_1" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING300_1" ); table->Commit(); // Three large, two small ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100000" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING2000" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING700_1" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100_3" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100_4" ); // Constraint will maximum number of columns (16): 11 large, 5 small. ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING2000" ); for ( ix = 0; ix < 10; ix++ ) { table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, FdoStringP::Format(L"STRING300_%d", ix + 1) ); } for ( ix = 0; ix < 4; ix++ ) { table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, FdoStringP::Format(L"STRING100_%d", ix + 1) ); } for ( ix = 0; ix < 1; ix++ ) { table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, FdoStringP::Format(L"STRING40_%d", ix + 1) ); } // No large columns, no truncation. // Tests columns whose size is over the initial truncation size but // under final truncation size. ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100_3" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING100_4" ); // No large columns, no truncation. // Tests columns whose size is under the initial truncation size. ukeyColumns = new FdoSmPhColumnCollection(); table->GetUkeyColumns()->Add( ukeyColumns ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING40_3" ); table->AddUkeyCol( table->GetUkeyColumns()->GetCount() - 1, L"STRING40_4" ); // Test an index. FdoSmPhIndexP index = table->CreateIndex(L"table1_ix1", true ); index->GetColumns()->Add( FdoSmPhColumnP(table->GetColumns()->GetItem(L"STRING2000")) ); index->GetColumns()->Add( FdoSmPhColumnP(table->GetColumns()->GetItem(L"STRING700_1")) ); FdoStringP pkeyClause = table->GetAddPkeySql(); FdoStringP expectedClause = FdoStringP::Format( L"constraint \"pk_table1\" primary key ( \"ID\", \"BLOB_COLUMN\"(%d), \"STRING_COLUMN\", \"SINGLE_COLUMN\", \"DOUBLE_COLUMN\", \"DECIMAL_COLUMN\", \"BOOL_COLUMN\", \"BYTE_COLUMN\", \"INT16_COLUMN\", \"INT32_COLUMN\", \"INT64_COLUMN\", \"DATE_COLUMN\", \"BINARY_COLUMN\", \"VARBINARY_COLUMN\", \"DATE2_COLUMN\", \"TIMESTAMP_COLUMN\" )", ( 680 - (charLen * 50)) ); // Verify that blob column got truncated to expected amount // (1000 - total size of other columns). CPPUNIT_ASSERT( pkeyClause == expectedClause ); FdoStringP ukeyClause = table->GetAddUkeysSql(); // Verify that all unique key columns got truncate to expected amounts. if ( charLen == 1 ) CPPUNIT_ASSERT( ukeyClause == L"UNIQUE (\"AUTOINCREMENT_COLUMN\"), UNIQUE (\"STRING100000\"(760), \"STRING100_1\"), UNIQUE (\"STRING2000\"(350), \"STRING700_1\"(350), \"STRING300_1\"), UNIQUE (\"STRING100000\"(266), \"STRING2000\"(266), \"STRING700_1\"(266), \"STRING100_3\", \"STRING100_4\"), UNIQUE (\"STRING2000\"(64), \"STRING300_1\"(64), \"STRING300_2\"(64), \"STRING300_3\"(64), \"STRING300_4\"(64), \"STRING300_5\"(64), \"STRING300_6\"(64), \"STRING300_7\"(64), \"STRING300_8\"(64), \"STRING300_9\"(64), \"STRING300_10\"(64), \"STRING100_1\"(64), \"STRING100_2\"(64), \"STRING100_3\"(64), \"STRING100_4\"(64), \"STRING40_1\"), UNIQUE (\"STRING100_3\", \"STRING100_4\"), UNIQUE (\"STRING40_3\", \"STRING40_4\")" ); // Table 2 tests a case where 3 constraint columns are // over initial truncation limit, 2 are over the next limit // and only 1 over the final limit. // Later on we verify truncation by trying some data inserts. table = owner->CreateTable( phMgr->GetDcDbObjectName(L"TABLE2" )); column = table->CreateColumnChar( L"STRING2000", false, 2000 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnChar( L"STRING400", false, 400 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnChar( L"STRING100", false, 100 ); table->AddPkeyCol( column->GetName() ); pkeyClause = table->GetAddPkeySql(); if ( charLen == 1 ) CPPUNIT_ASSERT( pkeyClause == L"constraint \"pk_table2\" primary key ( \"STRING2000\"(500), \"STRING400\"(400), \"STRING100\" )" ); // Calculating the size of MySql decimal columns is // complicated. Table3 tests creating constraints // with decimal columns of various sizes table = owner->CreateTable( phMgr->GetDcDbObjectName(L"TABLE3" )); FdoSmPhMySqlTableP mysqlTable = table->SmartCast<FdoSmPhMySqlTable>(); mysqlTable->SetStorageEngine( MySQLOvStorageEngineType_MyISAM ); // Add a couple of large strings to verify that they // are truncated to the expected amount. This verifies // that the decimal column size calculations are // correct (i.e. enough space was reserved for the // decimal columns). column = table->CreateColumnChar( L"STRING1", false, 2000 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnChar( L"STRING2", false, 2000 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL1", true, 65, 0 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL2", true, 65, 10 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL3", true, 45, 0 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL4", true, 44, 0 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL5", true, 21, 12 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL6", true, 10, 5 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL7", true, 5, 0 ); table->AddPkeyCol( column->GetName() ); column = table->CreateColumnDecimal( L"DECIMAL8", true, 1, 0 ); table->AddPkeyCol( column->GetName() ); pkeyClause = table->GetAddPkeySql(); if ( charLen == 1 ) CPPUNIT_ASSERT( pkeyClause == L"constraint \"pk_table3\" primary key ( \"STRING1\"(440), \"STRING2\"(440), \"DECIMAL1\", \"DECIMAL2\", \"DECIMAL3\", \"DECIMAL4\", \"DECIMAL5\", \"DECIMAL6\", \"DECIMAL7\", \"DECIMAL8\" )" ); database->Commit(); if ( charLen == 1 ) { // Test column truncation by inserting some data values. wchar_t prefix500[500]; wchar_t prefix400[400]; wchar_t prefix100[100]; // Fill in every character except the last // non-truncated one for each constraint column. for ( ix = 0; ix < 499; ix++ ) prefix500[ix] = 'a'; for ( ix = 0; ix < 399; ix++ ) prefix400[ix] = 'a'; for ( ix = 0; ix < 99; ix++ ) prefix100[ix] = 'a'; prefix500[499] = 0; prefix400[399] = 0; prefix100[99] = 0; GdbiConnection* gdbiConn = phMgr->GetGdbiConnection(); // Insert first object gdbiConn->ExecuteNonQuery( (FdoString*) FdoStringP::Format( L"insert into table2 ( STRING2000, STRING400, STRING100 ) values ( '%ls', '%ls', '%ls' )", (FdoString*) (FdoStringP(prefix500) + L"a"), (FdoString*) (FdoStringP(prefix400) + L"a"), (FdoString*) (FdoStringP(prefix100) + L"a") ) ); // Insert three more objects. In each case the truncated // key column values are identical exception for the // last character of one of the columns. gdbiConn->ExecuteNonQuery( (FdoString*) FdoStringP::Format( L"insert into table2 ( STRING2000, STRING400, STRING100 ) values ( '%ls', '%ls', '%ls' )", (FdoString*) (FdoStringP(prefix500) + L"b"), (FdoString*) (FdoStringP(prefix400) + L"a"), (FdoString*) (FdoStringP(prefix100) + L"a") ) ); gdbiConn->ExecuteNonQuery( (FdoString*) FdoStringP::Format( L"insert into table2 ( STRING2000, STRING400, STRING100 ) values ( '%ls', '%ls', '%ls' )", (FdoString*) (FdoStringP(prefix500) + L"a"), (FdoString*) (FdoStringP(prefix400) + L"b"), (FdoString*) (FdoStringP(prefix100) + L"a") ) ); gdbiConn->ExecuteNonQuery( (FdoString*) FdoStringP::Format( L"insert into table2 ( STRING2000, STRING400, STRING100 ) values ( '%ls', '%ls', '%ls' )", (FdoString*) (FdoStringP(prefix500) + L"a"), (FdoString*) (FdoStringP(prefix400) + L"a"), (FdoString*) (FdoStringP(prefix100) + L"b") ) ); bool duplicate = true; try { // try inserting a duplicate. The key column values are not duplicate // but the truncated values are. gdbiConn->ExecuteNonQuery( (FdoString*) FdoStringP::Format( L"insert into table2 ( STRING2000, STRING400, STRING100 ) values ( '%ls', '%ls', '%ls' )", (FdoString*) (FdoStringP(prefix500) + L"ab"), (FdoString*) (FdoStringP(prefix400) + L"ab"), (FdoString*) (FdoStringP(prefix100) + L"ab") ) ); } catch ( FdoException* exc ) { exc->Release(); duplicate = false; } catch ( ... ) { duplicate = false; } CPPUNIT_ASSERT( !duplicate ); } conn->disconnect(); delete conn; if ( charLen != 1 ) CPPUNIT_FAIL ("Test appears to be Ok; However database character set is not Latin1 so truncation validation was skipped"); printf( "Done\n" ); } catch (FdoException* e ) { UnitTestUtil::FailOnException(e); } catch (CppUnit::Exception exception) { throw exception; } catch (...) { CPPUNIT_FAIL ("unexpected exception encountered"); } }
// Tests character set and collation retrieval void MySqlSchemaMgrTests::testCharacterSets () { StaticConnection* conn = CreateStaticConnection(); FdoInt32 idx; try { char prvenv[100]; FdoStringP providerName = conn->GetServiceName(); sprintf( prvenv, "provider=%ls", (FdoString*) providerName ); #ifdef _WIN32 _putenv( prvenv ); #else putenv( prvenv ); #endif // Sets the other env. UnitTestUtil::SetProvider( conn->GetServiceName() ); printf( "\nOpening Connection ...\n" ); conn->connect(); FdoSchemaManagerP mgr = conn->CreateSchemaManager(); FdoSmPhGrdMgrP phMgr = mgr->GetPhysicalSchema()->SmartCast<FdoSmPhGrdMgr>(); FdoSmPhDatabaseP database = phMgr->GetDatabase(); for ( idx = 0; idx < 1; idx++ ) { FdoSmPhCharacterSetP charSet = database->FindCharacterSet( L"latin1" ); CPPUNIT_ASSERT( charSet != NULL ); FdoSmPhMySqlCharacterSetP mySqlCharSet = charSet->SmartCast<FdoSmPhMySqlCharacterSet>(); CPPUNIT_ASSERT( mySqlCharSet->GetCharLen() == 1 ); charSet = database->GetCharacterSet( L"utf8" ); mySqlCharSet = charSet->SmartCast<FdoSmPhMySqlCharacterSet>(); CPPUNIT_ASSERT( mySqlCharSet->GetCharLen() == 3 ); FdoSmPhCollationP collation = database->FindCollation( L"latin1_bin" ); CPPUNIT_ASSERT( collation != NULL ); charSet = collation->GetCharacterSet(); CPPUNIT_ASSERT( wcscmp(charSet->GetName(), L"latin1") == 0 ); collation = database->GetCollation( L"utf8_bin" ); charSet = collation->GetCharacterSet(); CPPUNIT_ASSERT( wcscmp(charSet->GetName(), L"utf8") == 0 ); } CPPUNIT_ASSERT( database->FindCharacterSet(L"noexist") == NULL ); CPPUNIT_ASSERT( database->FindCollation(L"noexist") == NULL ); bool succeeded = true; try { FdoSmPhCharacterSetP charSet = database->GetCharacterSet( L"noexist" ); } catch ( FdoException* exc ) { exc->Release(); succeeded = false; } CPPUNIT_ASSERT( !succeeded ); succeeded = true; try { FdoSmPhCollationP collation = database->GetCollation( L"noexist" ); } catch ( FdoException* exc ) { exc->Release(); succeeded = false; } CPPUNIT_ASSERT( !succeeded ); conn->disconnect(); delete conn; printf( "Done\n" ); } catch (FdoException* e ) { UnitTestUtil::FailOnException(e); } catch (CppUnit::Exception exception) { throw exception; } catch (...) { CPPUNIT_FAIL ("unexpected exception encountered"); } }
FdoIFeatureReader *FdoRdbmsSelectCommand::Execute( bool distinct, FdoInt16 callerId ) { if (!mConnection || !mFdoConnection || mFdoConnection->GetConnectionState() != FdoConnectionState_Open) throw FdoCommandException::Create(NlsMsgGet(FDORDBMS_13, "Connection not established")); // Flush out any outstanding modifications before selecting; so that the select // sees a current picture of the RDBMS. mIConnection->Flush(); int qid = -1; bool res = false; bool delStatement = true; GdbiStatement* statement = NULL; const FdoSmLpClassDefinition *classDefinition = mConnection->GetSchemaUtil()->GetClass(this->GetClassNameRef()->GetText()); bool isFeatureClass = ( classDefinition != NULL && classDefinition->GetClassType() == FdoClassType_FeatureClass ); bool isForUpdate = HasLobProperty( classDefinition ); bool doNotUseSimpleSelect = mHasObjectProps && (mIdentifiers == NULL || mIdentifiers->GetCount() == 0); try { // for now we support only select with joins if (callerId == (FdoInt16)FdoCommandType_Select && !doNotUseSimpleSelect && !mHasObjectProps) { FdoPtr<FdoRdbmsSqlBuilder> sqlBuilder = mFdoConnection->GetSqlBuilder(); if (sqlBuilder) { std::vector<NameOrderingPair> ordering; FdoPtr<FdoParameterValueCollection> params = GetParameterValues(); FdoPtr<FdoJoinCriteriaCollection> jcColl = GetJoinCriteria(); sqlBuilder->SetParameterValues(params); if (mOrderingIdentifiers && mOrderingIdentifiers->GetCount()) { for (int i=0; i<mOrderingIdentifiers->GetCount(); i++) { FdoPtr<FdoIdentifier> id = mOrderingIdentifiers->GetItem(i); ordering.push_back(NameOrderingPair(id.p, ((int)mOrderingOptions.size() != mOrderingIdentifiers->GetCount()) ? mOrderingOption : mOrderingOptions[id->GetName()])); } } FdoString* sqlString = sqlBuilder->ToSelectSqlString(GetClassNameRef(), mAliasName, GetFilterRef(), mIdentifiers, ordering, jcColl); if (sqlString != NULL && *sqlString != '\0') { statement = mConnection->GetGdbiConnection()->Prepare( sqlString ); std::vector< std::pair< FdoLiteralValue*, FdoInt64 > >* paramsUsed = sqlBuilder->GetUsedParameterValues(); if (paramsUsed != NULL && paramsUsed->size()) { if (mBindParamsHelper == NULL) mBindParamsHelper = new FdoRdbmsPropBindHelper(mConn); mBindParamsHelper->BindParameters(statement, paramsUsed); } GdbiQueryResult *queryRslt = statement->ExecuteQuery(); delete statement; if (mBindParamsHelper != NULL) mBindParamsHelper->Clear(); // statement will be deleted in the reader. delStatement = false; return FdoRdbmsSimpleFeatureReader::Create(mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers); } } } FdoPtr<FdoRdbmsFilterProcessor>flterProcessor = mFdoConnection->GetFilterProcessor(); FdoPtr<FdoParameterValueCollection> params = GetParameterValues(); flterProcessor->SetParameterValues(params); FdoRdbmsFilterUtilConstrainDef filterConstrain; filterConstrain.distinct = distinct; filterConstrain.orderingOption = mOrderingOption; filterConstrain.selectedProperties = mIdentifiers; filterConstrain.groupByProperties = mGroupingCol; filterConstrain.orderByProperties = mOrderingIdentifiers; // Verify if this is a special case we can optimize (no filter, no grouping filter, // and only aggregate functions Count() and/or SpatialExtents()) FdoRdbmsFeatureReader *reader = GetOptimizedFeatureReader( classDefinition ); if ( reader ) return reader; // FDO supports expression functions that may not have native support in the // underlying system. If this is the case then the request has to be handled // by the Expression Engine. bool isValidFilter = true, isValidSelectList = true; if ( this->GetFilterRef() != NULL ) isValidFilter = flterProcessor->IsValidExpression( this->GetFilterRef() ); isValidSelectList = flterProcessor->IsValidExpression( mIdentifiers ); if ( ( !isValidFilter ) || ( !isValidSelectList ) ) { // Either the selected property list of the the filter is invalid. In any case // create a SQL statement that selects all properties for the current class. // If the filter is valid it is used to narrow the selected amount of data. FdoString *sqlStatement = flterProcessor->FilterToSql( ((isValidFilter) ? this->GetFilterRef() : NULL), this->GetClassNameRef()->GetText() ); GdbiQueryResult *queryRslt = mConnection->GetGdbiConnection()->ExecuteQuery( sqlStatement ); FdoPtr<FdoIFeatureReader> featureReader = new FdoRdbmsFeatureReader( mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, NULL, 0, NULL ); // The Expression Engine cannot work with the class definition of type // "FdoSmLpClassDefinition". Instead it is necessary to get the corresponding // definition of type "FdoClassDefinition". This is done next. const FdoSmLpSchema* schema = mConnection->GetSchema( this->GetClassNameRef()->GetText() ); FdoFeatureSchemasP fdoFeatureSchemas = mFdoConnection->GetSchemaManager()->GetFdoSchemas( schema->GetName() ); FdoClassesP classCol = (FdoClassCollection *)fdoFeatureSchemas->FindClass( this->GetClassNameRef()->GetText() ); FdoClassDefinitionP classDef = classCol->GetItem(0); // Create the collection of custom functions. FdoSmLpSchemasP schemas = ((FdoSmLpSchema *) schema)->GetSchemas(); FdoExpressionEngineFunctionCollection *userDefinedFunctions = GetUserDefinedFunctions( schemas->GetSpatialContextMgr()->GetSpatialContexts(), classDef ); return FdoExpressionEngineUtilFeatureReader::Create( classDef, featureReader, this->GetFilterRef(), mIdentifiers, userDefinedFunctions); } // The selected properties and the filter are both valid. Do the normal processing. // Validate the filter if ( this->GetFilterRef() != NULL ) { FdoPtr<FdoIFilterCapabilities> filterCaps = mFdoConnection->GetFilterCapabilities(); FdoExpressionEngine::ValidateFilter( NULL, this->GetFilterRef(), NULL, filterCaps); } // Call FilterToSql just to populate the filter's list of geometric conditions; FdoString * sqlString = flterProcessor->FilterToSql( this->GetFilterRef(), this->GetClassNameRef()->GetText(), SqlCommandType_Select, FdoCommandType_Select, &filterConstrain, isForUpdate, callerId ); FdoPtr<FdoRdbmsFilterProcessor::BoundGeometryCollection> boundGeometries = flterProcessor->GetBoundGeometryValues(); FdoPtr<FdoRdbmsSecondarySpatialFilterCollection> geometricConditions = flterProcessor->GetGeometricConditions(); vector<int> * logicalOps = flterProcessor->GetFilterLogicalOps(); FdoPtr<FdoIdentifierCollection> idsWithGeoms = FdoIdentifierCollection::Create(); if (( mIdentifiers && mIdentifiers->GetCount() > 0) ) { // Make sure that the properties are listed for any geometric conditions that require secondary filtering. if (geometricConditions != NULL) { for (FdoInt32 i=0; i < geometricConditions->GetCount(); i++) { FdoPtr<FdoRdbmsSpatialSecondaryFilter> ssf = geometricConditions->GetItem(i); FdoString * ssfPropertyName = ssf->GetPropertyName(); FdoPtr<FdoIdentifier> ssfId = mIdentifiers->FindItem(ssfPropertyName); if (ssfId == NULL) { // Property wasn't selected by the caller. ssfId = FdoIdentifier::Create(ssfPropertyName); idsWithGeoms->Add(ssfId); } } // Convert to SQL again if we added geometric properties. if (idsWithGeoms->GetCount() > 0) { // Make our own copy of the original list, to avoid a side effect of changing // mIdentifiers, which the user can effectively see. Perserve original order, // effectively creating a new list that appends the geometry names. for (FdoInt32 i = mIdentifiers->GetCount()-1; i >= 0; i--) { FdoPtr<FdoIdentifier> id = mIdentifiers->GetItem(i); idsWithGeoms->Insert(0, id); } filterConstrain.selectedProperties = idsWithGeoms; sqlString = flterProcessor->FilterToSql( this->GetFilterRef(), this->GetClassNameRef()->GetText(), SqlCommandType_Select, FdoCommandType_Select, &filterConstrain, isForUpdate, callerId ); } } if (callerId == FdoCommandType_SelectAggregates) { FdoSchemaManagerP pschemaManager = mConnection->GetSchemaUtil()->GetSchemaManager(); FdoPtr<FdoFeatureSchemaCollection> schemas = pschemaManager->GetFdoSchemas(L""); FdoPtr<FdoCommonExpressionExecutor> expVer = FdoCommonExpressionExecutor::Create(schemas, GetClassNameRef()); FdoPtr<FdoIExpressionCapabilities> expCap = mFdoConnection->GetExpressionCapabilities(); expVer->ValidateIdentifiers(mIdentifiers, expCap); } } statement = mConnection->GetGdbiConnection()->Prepare( sqlString ); std::vector< std::pair< FdoLiteralValue*, FdoInt64 > >* paramsUsed = flterProcessor->GetUsedParameterValues(); if (paramsUsed != NULL && paramsUsed->size()) { if (mBindParamsHelper == NULL) mBindParamsHelper = new FdoRdbmsPropBindHelper(mConn); mBindParamsHelper->BindParameters(statement, paramsUsed); } GdbiQueryResult *queryRslt = statement->ExecuteQuery(); delete statement; if (mBindParamsHelper != NULL) mBindParamsHelper->Clear(); // statement will be deleted in the reader. delStatement = false; // For now only SQL Spatial Server supports SupportsSimpleReader, later (after we add some unit tests) we can extend it to other providers if (!flterProcessor->ContainsCustomObjects() && flterProcessor->SupportsSimpleReader() && geometricConditions == NULL && callerId == (FdoInt16)FdoCommandType_Select && !doNotUseSimpleSelect) { return FdoRdbmsSimpleFeatureReader::Create(mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers); } else { if (( mIdentifiers && mIdentifiers->GetCount() > 0)) return new FdoRdbmsFeatureSubsetReader (mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers, geometricConditions, logicalOps ); else return new FdoRdbmsFeatureReader (mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, NULL, 0, geometricConditions, logicalOps ); // The feature reader should free the queryRslt } } catch (FdoCommandException *ex) { if (delStatement) delete statement; ex; SELECT_CLEANUP; throw; } catch (FdoException *ex) { if (delStatement) delete statement; SELECT_CLEANUP; // Wrap in FdoPtr to remove original reference to original exception throw FdoCommandException::Create(ex->GetExceptionMessage(), FdoPtr<FdoException>(ex), ex->GetNativeErrorCode()); } catch ( ... ) { if (delStatement) delete statement; SELECT_CLEANUP; throw; } }
void FdoSchemaRollbackTest::DoTest ( bool bPreClear, const wchar_t* schemaName, bool bRollbackOnly, bool bCommit ) { FdoPtr<FdoIConnection> connection; StaticConnection* staticConn = NULL; FdoSchemaManagerP mgr; const FdoSmLpSchemaCollection* lp = NULL; // All of these tests exercise the Schema Manager but only one test // exercises sometime that can currently happen in FDO. Therefore, // to save time ... // mode. if ( bPreClear || (wcslen(schemaName) > 0) || (!bRollbackOnly) || bCommit ) { // these other tests are skipped by default. if ( !UnitTestUtil::DoThisTest( "rollback" ) ) return; } try { // delete, re-create and open the datastore printf( "Initializing Connection ... \n" ); connection = UnitTestUtil::CreateConnection( true, true, DB_NAME_SUFFIX, NULL, NULL, 0 ); staticConn = UnitTestUtil::NewStaticConnection(); staticConn->connect(); staticConn->SetSchema( DB_NAME_SUFFIX ); // The following tests must be run in the following order to get the expected results. printf( "Creating Acad Schema ... \n" ); CreateAcadSchema( connection ); printf( "Creating Electric Schema ... \n" ); CreateElectricSchema( connection ); // At this point all schema elements are in the rollback cache. The following // conditionally does a rollback, which clears the rollback cache. This means // that only subsequently modified elements will be later rolled back when // bRollbackOnly is true. if ( bPreClear ) { FdoPtr<FdoITransaction> clearTrans = connection->BeginTransaction(); clearTrans->Rollback(); } // Grab snapshot of original MetaSchema ( for debugging ). printf( "Writing Original Schema ... \n" ); FdoSchemaManagerP mgr = staticConn->CreateSchemaManager(); const FdoSmLpSchemaCollection* lp = mgr->RefLogicalPhysicalSchemas(); lp->XMLSerialize( UnitTestUtil::GetOutputFileName( L"schema_rollback_orig.xml" ) ); printf( "Deleting some tables ... \n" ); // Do some deletes outside of the schema manager. These tables will not be re-created // bPreClear and bRollbackOnly are true, since these tables won't be in the // rollback cache. FdoSmPhMgrP phMgr = mgr->GetPhysicalSchema(); FdoSmPhDbObjectP pObject = phMgr->FindDbObject( phMgr->GetDcDbObjectName(L"Conductor"), L"", L"", false ); pObject->SetElementState( FdoSchemaElementState_Deleted ); pObject->Commit(); pObject = phMgr->FindDbObject( phMgr->GetDcDbObjectName(L"AcDbEntity_AcXData"), L"", L"", false ); pObject->SetElementState( FdoSchemaElementState_Deleted ); pObject->Commit(); FdoPtr<FdoITransaction> trans1 = connection->BeginTransaction(); printf( "Modifying Acad Schema ... \n" ); ModAcadSchema( connection ); printf( "Modifying Electric Schema ... \n" ); ModElectricSchema( connection ); printf( "Performing rollback ... \n" ); if ( bCommit ) { // Commit before rollback if asked to. In this case, rollback will not // have any physical schema synchronizations to perform. trans1->Commit(); trans1 = connection->BeginTransaction(); } if ( (wcslen(schemaName) == 0) && bRollbackOnly ) { // Transaction rollback invokes SynchPhysical on all schemas ( synchronize // rollbacks only ) so exercise it in this case. trans1->Rollback(); } else { // For other cases, call SynchPhysical directly, after low-level rollback. UnitTestUtil::Sql2Db( L"rollback", connection ); mgr = staticConn->CreateSchemaManager(); mgr->SynchPhysical( schemaName, bRollbackOnly ); } // Write out the resulting metaschema printf( "Writing Schema after Rollback ... \n" ); mgr = staticConn->CreateSchemaManager(); lp = mgr->RefLogicalPhysicalSchemas(); lp->XMLSerialize( OutFileName(bPreClear, schemaName, bRollbackOnly, bCommit) ); try { trans1 = NULL; } catch ( ... ) { } printf( "Closing Connection ... \n" ); UnitTestUtil::CloseConnection( connection, false, DB_NAME_SUFFIX ); // Compare results with expected results. // Todo: check SqlServer and MySql results. #ifdef RDBI_DEF_ORA UnitTestUtil::CheckOutput( MasterFileName(bPreClear, schemaName, bRollbackOnly, bCommit), OutFileName(bPreClear, schemaName, bRollbackOnly, bCommit) ); #endif phMgr = NULL; mgr = NULL; delete staticConn; } catch ( FdoException* e ) { if ( staticConn ) delete staticConn; try { if ( connection ) connection->Close(); } catch ( ... ) { } UnitTestUtil::FailOnException( e ); } catch ( CppUnit::Exception e ) { if ( staticConn ) delete staticConn; if ( connection ) connection->Close(); throw; } catch (...) { if ( staticConn ) delete staticConn; if ( connection ) connection->Close(); CPPUNIT_FAIL ("caught unexpected exception"); } printf( "Done\n" ); }