/* Test insert/update/select (but not setting/getting any lock info) on a table that supports locking. */
void BasicUpdateTests::update_on_lock_enabled_table ()
{
    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcov());
        mConnection->Open ();

		// Clean up previous tests:
        CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaSample(), ArcSDETestConfig::ClassNameSample(), true);
        
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (ArcSDETestConfig::QClassNameSample());
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoStringValue> expression = FdoStringValue::Create (L"Zozo");
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (AdjustRdbmsName(L"LockProperty"), expression);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 newId = 0;
        if (reader->ReadNext())
            newId = reader->GetInt32(AdjustRdbmsName(L"Id"));

        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameSample());
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf(filter, ELEMENTS(filter), L"%ls = %d", AdjustRdbmsName(L"Id"), newId);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
	    values = update->GetPropertyValues ();
	    value = FdoPropertyValue::Create ();
        value->SetName (AdjustRdbmsName(L"LockProperty"));
		value->SetValue (L"'All mimsy were the borogoves'");
        values->Add (value);
        if (1 != update->Execute ())
            CPPUNIT_FAIL ("update execute failed");

        // check by doing a select
        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameSample());
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect value", 0 == wcscmp (L"All mimsy were the borogoves", reader->GetString (AdjustRdbmsName(L"LockProperty"))));
        }
        reader->Close();

		// Clean up after test:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassSimple(), ArcSDETestConfig::ClassNameSample(), true);
        mConnection->Close();
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}
void RfpTestRasterConversion::_setUp()
{
	m_connection = CreateConnection();
	CPPUNIT_ASSERT(m_connection != NULL);
	FdoPtr<FdoIoStream> stream = FdoIoFileStream::Create(L"../../TestData/RGB/RGB.xml", L"r");
	m_connection->SetConfiguration(stream);
	m_connection->Open();
	
	// execute the query
	FdoICommand * cmd = m_connection->CreateCommand(FdoCommandType_Select);
	FdoPtr<FdoISelect> cmdSelect = static_cast<FdoISelect*>(cmd);

	cmdSelect->SetFeatureClassName(L"Photo");
	FdoPtr<FdoIFeatureReader> reader = cmdSelect->Execute();
	reader->ReadNext();

	// get the raster
	m_raster = reader->GetRaster(L"Image");

	reader->Close();
}
Exemple #3
0
EGwsStatus CGwsFdoInsertCommand::Execute (CGwsMutableFeature & feat)
{
    Clear ();

    EGwsStatus fdoes = eGwsOk;
    if(!m_bIsPrepared) {
        PushStatus (eGwsFdoCommandIsNotPrepared);
        return eGwsFdoCommandIsNotPrepared;
    }

    try
    {
        GetPropertyValues (); // initialize property value collection
        eGwsOkThrow(SetProperties (feat, true)) ;

        FdoPtr<FdoIFeatureReader> pReader = ((FdoIInsert*)m_pCommand.p)->Execute();

        //!FDO may return null pointer even if the command succeed. So remove the following assert.
        //assert (pReader != NULL);

        // Read assigned Id
        if( pReader !=  NULL )
        {
            if (pReader->ReadNext()) {

                // Read the key of just inserted record
                //
                CGwsDataValueCollection  *  keyvals = NULL;

                for (FdoInt32 idx = 0; m_identity != NULL && idx < m_identity->GetCount (); idx ++) {
                    FdoPtr<FdoDataPropertyDefinition>  keyprop =
                        m_identity->GetItem (idx);
                    FdoPtr<FdoDataValue>               val =
                        GwsQueryUtils::GetDataPropertyValue (pReader,
                        keyprop->GetDataType (),
                        keyprop->GetName ());
                    if (val == NULL)
                        continue;
                    if (keyvals == NULL)
                        keyvals = (CGwsDataValueCollection *) CGwsDataValueCollection::Create ();
                    keyvals->Add (val);
                    feat.SetValue (keyprop->GetName (),val);
                }

#ifdef OBJECT_PROPERTIES
                //insert object property values that were cached in SetProperties()
                if(!m_objPropNames.empty())
                {
                    //Get object property class instance array that was cached in SetProperties()
                    int numProps = m_objPropNames.size();
                    for( int i = 0; i<numProps; i++)
                    {
                        const std::wstring strPropName = m_objPropNames[i];
                        const std::wstring objectClassName =
                            acmapFdoUtils::constructObjectClassName(aTOw(m_classname.Class()),strPropName.c_str());

                        //get the object property values
                        AcMapFdoFeatureIterator* featIter = NULL;
                        eGwsOkThrow(feature.GetFeature(wTOa(strPropName.c_str()),featIter));
                        assert(featIter != NULL);
                        //insert the primary keys of the parent feature and the object property values
                        eGwsOkThrow(InsertObjectProperties(objectClassName.c_str(), valList, featIter));
                    }
                }
#endif

                // long ver;
                // Read sequence number
                if (!m_revisionprop.empty()) {
                    FdoInt32 revnum = pReader->GetInt32 (m_revisionprop.c_str ());
                    feat.SetRevisionNumber (revnum);
                }
                feat.SetFeatureId (GWSFeatureId (keyvals));
            }
            pReader->Close();
        }

    } catch(FdoException *e) {
        PushFdoException (eGwsFailedToExecuteCommand, e);
        e->Release();
        fdoes = eGwsFailedToExecuteCommand;

    } catch(EGwsStatus es) {
        PushStatus (es);
        fdoes = es;
    }
    ReleasePropertyValues (); // releases property value collection

    return fdoes;
}
void MySqlFdoInsertTest::insertDate ()
{
    wprintf(L"InsertDate: Test insert command with different date/time settings.\n");
    FdoPtr<FdoIConnection> connection = UnitTestUtil::GetConnection(mSuffix, true);

    int         baseColorIndex    = 990,
                numberTestCases   = 9;
    bool        exceptionExpected = false;
    FdoStringP  colorIndex;
    FdoDateTime dateTime;

    for (int j = 0; j < numberTestCases; j++)
    {
        // Reinitialize the date-time object as defined by the constructor.

        dateTime.year    = -1;
        dateTime.month   = -1;
        dateTime.day     = -1;
        dateTime.hour    = -1;
        dateTime.minute  = -1;
        dateTime.seconds = 0.0f;;

        colorIndex = FdoStringP::Format(L"%d", (baseColorIndex+j));
        switch (j)
        {
            case 0:
                wprintf(L"  > (1) No date or time specification: should fail.\n");
                exceptionExpected = true;
                break;

            case 1:
                wprintf(L"  > (2)Complete date, but no time specification: should work.\n");
                dateTime.year    = 2003;
                dateTime.month   = 1;
                dateTime.day     = 1;
                exceptionExpected = false;
                break;

            case 2:
                wprintf(L"  > (3) Complete time, but no date specification: should work.\n");
                dateTime.hour    = 1;
                dateTime.minute  = 11;
                dateTime.seconds = 0;
                exceptionExpected = false;
                break;

            case 3:
                wprintf(L"  > (4) Complete date and time specification: should work.\n");
                dateTime.year    = 2003;
                dateTime.month   = 1;
                dateTime.day     = 1;
                dateTime.hour    = 1;
                dateTime.minute  = 11;
                dateTime.seconds = 11;
                exceptionExpected = false;
                break;

            case 4:
                wprintf(L"  > (5) Partial date, but no time specification: should fail.\n");
                dateTime.year     = 2003;
                dateTime.day      = 1;
                exceptionExpected = true;
                break;

            case 5:
                wprintf(L"  > (6) Partial time, but no date specification: should fail.\n");
                dateTime.hour     = 1;
                dateTime.seconds  = 0;
                exceptionExpected = true;
                break;

            case 6:
                wprintf(L"  > (7) Partial date and time specification: should fail.\n");
                dateTime.year     = 2003;
                dateTime.day      = 1;
                dateTime.hour     = 1;
                dateTime.seconds  = 0;
                exceptionExpected = true;
                break;

            case 7:
                wprintf(L"  > (8) Partial date and complete time specification: should fail.\n");
                dateTime.year     = 2003;
                dateTime.day      = 1;
                dateTime.hour     = 1;
                dateTime.minute   = 11;
                dateTime.seconds  = 0;
                exceptionExpected = true;
                break;

            case 8:
                wprintf(L"  > (9) Partial time and complete date specification: should fail.\n");
                dateTime.year     = 2003;
                dateTime.month    = 1;
                dateTime.day      = 1;
                dateTime.hour     = 1;
                dateTime.seconds  = 0;
                exceptionExpected = true;
                break;

        }

        // Attempt to insert a record using the constructed date-time object.
        try
        {
            FdoInsertTest::insertDate(connection, dateTime, colorIndex);
        }

        catch (FdoException *ex)
        {
            if (!exceptionExpected)
            {
                wprintf(L"    Unexpected Exception: %ls\n", ex->GetExceptionMessage());
                connection->Close();
                UnitTestUtil::FailOnException(ex);
            }

            wchar_t expectedErrMsg[] = L"Incomplete date/time setting. ";
            FdoString *excMsg = ex->GetExceptionMessage();
            // eliminate a space from the end if is the case
            if (excMsg[wcslen(excMsg) - 1] != L' ')
                expectedErrMsg[wcslen(expectedErrMsg)-1] = L'\0';

            if ((wcscmp(excMsg, expectedErrMsg)) != 0)
            {
                wprintf(L"    Unexpected Exception: %ls\n", ex->GetExceptionMessage());
                connection->Close();
                UnitTestUtil::FailOnException(ex);
            }
            else
                wprintf(L"    Expected Exception: %ls\n", ex->GetExceptionMessage());
            ex->Release();
        }

        catch ( ... )
        {
            connection->Close();
            UnitTestUtil::FailOnException(FdoException::Create(L"    Unexpected Exception in insertDate()\n"));
        }

    }

    wprintf(L"  > Test Verification.\n");
    insertDateVerification(connection, 3);

    wprintf(L"  > Test Cleanup.\n");
    FdoInsertTest::insertDateCleanUp(connection);

    connection->Close();
}
void RfpTestEcw::testRGB()
{
	FdoPtr<FdoIConnection> connection = CreateConnection();
	FdoPtr<FdoIoStream> stream = FdoIoFileStream::Create(L"../../TestData/Ecw/Adelaide_sample.xml", L"r");
	connection->SetConfiguration(stream);
	connection->Open();

	FdoICommand* cmd = connection->CreateCommand(FdoCommandType_Select);
	FdoPtr<FdoISelect> cmdSelect = dynamic_cast<FdoISelect*>(cmd);
	cmdSelect->SetFeatureClassName(L"Photo");
	FdoPtr<FdoIFeatureReader> featureReader = cmdSelect->Execute();
	CPPUNIT_ASSERT(featureReader->ReadNext());

	FdoPtr<FdoIRaster> raster = featureReader->GetRaster(L"Image");
    FdoInt32 xSize = raster->GetImageXSize();
    FdoInt32 ySize = raster->GetImageYSize();
	CPPUNIT_ASSERT(xSize == 2814);
	CPPUNIT_ASSERT(ySize == 2187);

	FdoPtr<FdoRasterDataModel> dataModel = raster->GetDataModel();
	CPPUNIT_ASSERT(dataModel->GetBitsPerPixel() == 32);
	CPPUNIT_ASSERT(dataModel->GetDataModelType() == FdoRasterDataModelType_RGBA);
	CPPUNIT_ASSERT(dataModel->GetTileSizeX() == raster->GetImageXSize());
	CPPUNIT_ASSERT(dataModel->GetTileSizeY() == raster->GetImageYSize());

	const FdoInt32 tileSizeX = 1024, tileSizeY = 1024;
	dataModel->SetTileSizeX(tileSizeX);
	dataModel->SetTileSizeY(tileSizeY);
	raster->SetDataModel(dataModel);

	FdoPtr<FdoIStreamReaderTmpl<FdoByte> > reader = dynamic_cast<FdoIStreamReaderTmpl<FdoByte>*>(raster->GetStreamReader());	
	int numTileRows = (2187 - 1) / tileSizeX + 1; 
	int numTileCols = (2814 - 1) / tileSizeY + 1; 
	const int bytesTile = tileSizeX * tileSizeY * 4;

	FdoByte* buffer = new FdoByte[bytesTile];
	for (int i = 0; i < numTileRows; i++)
	{
		// read the first tile of the tile row
		FdoInt32 numRead = reader->ReadNext(buffer, 0, bytesTile);
		CPPUNIT_ASSERT(numRead == bytesTile);

		// skip the rest tiles
		reader->Skip(bytesTile * (numTileCols - 1));
	}
    
	// no data
	CPPUNIT_ASSERT(reader->ReadNext(buffer, 0, 1) == 0);
	delete buffer;

	// scale down to 1/4 of original size and read it row by row
	raster->SetImageXSize(703); 
	raster->SetImageYSize(546); 
	dataModel->SetTileSizeX(raster->GetImageXSize());
	dataModel->SetTileSizeY(raster->GetImageYSize());
	raster->SetDataModel(dataModel);
	reader = dynamic_cast<FdoIStreamReaderTmpl<FdoByte>*>(raster->GetStreamReader());	

	// iterate all rows
	FdoByte buff[2816]; //2816=703*4+4
	for (int row = 0; row < 546; row++)
	{
		FdoInt32 numRead = reader->ReadNext(buff, 0, 2816);
		CPPUNIT_ASSERT(numRead == 2816);
	}
	CPPUNIT_ASSERT(reader->ReadNext(buff, 0, 1) == 0);

	connection->Close();

}
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" );

}
/// <summary>Executes the release lock command, returning an FdoILockConflictReader.</summary>
/// <returns>Returns an FdoILockConflictReader</returns> 
FdoILockConflictReader* ArcSDEReleaseLockCommand::Execute ()
{
    const CHAR* columns[1];
    FdoPtr<ArcSDEConnection> connection;
    CHAR table[SE_QUALIFIED_TABLE_NAME];
    CHAR column[SE_MAX_COLUMN_LEN];
    wchar_t* wcolumn;
    CHAR *where;
    SHORT count;
    SE_FILTER* filters;
    FdoString* property;
    LONG result;
    SE_STREAM stream;
    CHAR user_name[SE_MAX_OWNER_LEN];
    wchar_t* me;
    CHAR logfile[SE_MAX_PATH_LEN];
    SE_SQL_CONSTRUCT  sql_construct;
    CHAR* tables[1];
    FdoPtr<FdoISQLDataReader> reader;
    SE_LOG log;
    LONG number = 0;
    Lock* locks = NULL;
    wchar_t* locktable = NULL;
    FdoPtr<ArcSDELockConflictReader> ret;

    // verify the connection
    connection = static_cast<ArcSDEConnection*>(GetConnection ());
    if (connection == NULL)
        throw FdoException::Create (NlsMsgGet (ARCSDE_CONNECTION_NOT_ESTABLISHED, "Connection not established."));

    // verify the feature class name is specified
    if (mClassName == NULL)
        throw FdoException::Create (NlsMsgGet (ARCSDE_FEATURE_CLASS_UNSPECIFIED, "Feature class name not specified."));

    // get the class definition which reflects the requested feature class name
    FdoPtr<FdoClassDefinition> definition = connection->GetRequestedClassDefinition (mClassName);

    // get the filter if any
    FdoPtr<FdoFilter> filter = GetFilter ();

    // get SQL query's "from" table list
    mConnection->ClassToTable (table, definition);

    // ensure lockable table
    if (!ArcSDELockUtility::IsLockable (connection->GetConnection (), table, column))
    {
        wchar_t* wtable;
        sde_multibyte_to_wide (wtable, table);
        throw FdoException::Create (NlsMsgGet1 (ARCSDE_LOCKING_NOT_ENABLED, "Table '%1$ls' is not lock enabled.", wtable));
    }

    // get the property name that is the row_id
    sde_multibyte_to_wide (wcolumn, column);
    property = connection->ColumnToProperty (definition, wcolumn);

    // get SQL query's "where" clause & spatial filters
    where = NULL;
    count = 0;
    filters = NULL;
    GetFilterInfo (connection, filter, definition, where, count, filters);

    // establish an empty conflict reader
    ret = new ArcSDELockConflictReader (connection, definition->GetQualifiedName (), table, property);

    // initialize the stream query
    result = SE_stream_create (connection->GetConnection (), &stream);
    handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_ALLOC, "Cannot initialize SE_STREAM structure.");

    // if necessary, version enable the stream
    ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

    // release lock, don't return rows
    result = SE_connection_get_user_name (connection->GetConnection (), user_name);
    handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_USER_UNKNOWN, "Cannot determine current user.");
    sde_multibyte_to_wide (me, user_name);
    if (0 == wcscmp (GetLockOwner (), L""))
    {
        result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_UNLOCK_ON_QUERY
        | SE_ROWLOCKING_LOCK_ONLY);
        handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");
    }
    else if (0 == wcscmp (GetLockOwner (), me))
    {
        result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_UNLOCK_ON_QUERY
        | SE_ROWLOCKING_FILTER_MY_LOCKS | SE_ROWLOCKING_LOCK_ONLY);
        handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");
    }
    else
    {
        LONG *ids = NULL;
        CHAR **users = NULL;
        CHAR lt[SE_QUALIFIED_TABLE_NAME];

        if (0)
            throw FdoCommandException::Create (NlsMsgGet (ARCSDE_RELEASE_UNOWNED_LOCKS, "Releasing other owners locks is not supported."));

        result = SE_table_get_rowlocks (connection->GetConnection(), table, &number, &ids, &users);
        handle_sde_err<FdoCommandException>(connection->GetConnection(), result, __FILE__, __LINE__, ARCSDE_GET_ROW_LOCK_LIST_FAILED, "Failed to get the row lock list.");
        if (0 != number)
        {
            // put the id's and users in an array of lock structures
            locks = (Lock*)calloc (number, sizeof (Lock));
            for (int i = 0; i < number; i++)
            {
                locks[i].id = ids[i];
                sde_strcpy (sde_pus2wc(locks[i].user), sde_pcus2wc(users[i]));
            }
            qsort (locks, number, sizeof (LONG), compare);
            ArcSDELockUtility::LockTableName (lt, connection, table);
            sde_multibyte_to_wide (locktable, lt);
            SE_table_free_rowlocks_list (number, ids, users);
        }
    }

    // apply attribute and spatial query to stream
    columns[0] = column;
    ApplyFilterInfoToStream (connection, stream, table, where, 1, columns, count, filters);

    // set up a temporary log file
    mConnection->MakeLog (&log, table);

    // accumulate the query in the log file
    result = SE_stream_set_logfile (stream, log, FALSE);
    handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_LOG_SET_LOGFILE, "Could not set log file.");

    // lock the table's lock table to prevent alteration
    reader = ArcSDELockUtility::LockLockTable (mConnection, table);

    // actually execute the query
    result = SE_stream_execute (stream);
    handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");

    result = SE_stream_fetch (stream);
    // three possibilities: locks for the specified user exist (SE_SUCCESS) and the log file isn't filled,
    // everything was unlocked (SE_FINISHED)
    // or there was a conflict (SE_LOCK_CONFLICT)
    switch (result)
    {
        case SE_SUCCESS:
            if (0 != number)
            {
                CHAR* user;
                LONG id;
                wchar_t drop[1024];
                FdoPtr<FdoISQLCommand> sql;
                Lock key;
                Lock* item;

		// Get lock owner name:
		const wchar_t *wLockOwner = GetLockOwner();
		wchar_t *wLockOwnerUpr = (wchar_t*)alloca( (1+wcslen(wLockOwner)) * sizeof(wchar_t));
		wcscpy(wLockOwnerUpr, wLockOwner);
		FdoCommonOSUtil::wcsupr(wLockOwnerUpr);  // ToDo: Oracle-specific
                sde_wide_to_multibyte (user, wLockOwnerUpr);

                // process each row returned (ignoring the log file)
                sql = (FdoISQLCommand*)connection->CreateCommand (FdoCommandType_SQLCommand);
                do
                {
                    if (SE_SUCCESS != (result = SE_stream_get_integer (stream, 1, &id)))
                    {
                        sde_multibyte_to_wide (wcolumn, column);
                        handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_GET, "Stream get ('%1$ls') failed for column '%2$ls'.", L"SE_stream_get_integer", wcolumn);
                    }
                    else
                    {
                        key.id = id;
                        // look it up to see if it's a conflict (i.e. not found)
                        if (NULL != (item = (Lock*)bsearch (&key, locks, number, sizeof (LONG), compare)))
                        {
                            if (0 == sde_strcmp (sde_pcus2wc(user), sde_pcus2wc(item->user)))
                            {
                                // ToDo: optimize this singleton delete somewhat
                                //ROW_ID                                    NOT NULL NUMBER(38)
                                //USER_NAME                                 NOT NULL VARCHAR2(32)
                                FdoCommonOSUtil::swprintf (drop, ELEMENTS (drop), L"delete from %ls where user_name=upper('%ls') and row_id = %ld", locktable, GetLockOwner (), id);
                                sql->SetSQLStatement (drop);
                                sql->ExecuteNonQuery ();
                            }
                            else
                                ret->AddIdentity (id);
                        }
                        else
                        {
                            // no lock, hence no conflict
                        }
                    }
                }
                while (SE_SUCCESS == (result = SE_stream_fetch (stream)));
                if (SE_FINISHED != result)
                    handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_FETCH, "Stream fetch failed.");
            }
            break;
        case SE_FINISHED:
            break;
        case SE_LOCK_CONFLICT:
            // reuse the same stream
            result = SE_stream_close (stream, TRUE);

            // if necessary, version enable the stream
            ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

            // select locks still remaining
            result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_FILTER_OTHER_LOCKS);
            handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");

            // get the list of row ids from the log file
            tables[0] = table;
            sql_construct.tables = tables;
            sql_construct.num_tables = ELEMENTS (tables);
            sql_construct.where = NULL;
            ArcSDELockUtility::GetLogFile (logfile, connection->GetConnection (), log);
            result = SE_stream_query_logfile (stream, logfile, 1, columns, &sql_construct);
            handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_LOG_FILE_QUERY, "Unable to query log file.");

            // execute the query that fetches conflicts
            result = SE_stream_execute (stream);
            handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");

            // gather the conflicts
            ArcSDELockUtility::GatherConflicts (stream, column, 1, ret);

            // if there were conflicts (and there will be), do a partial unlock
            if (0 != ret->mIds->GetCount ())
            {
                // reuse the same stream
                result = SE_stream_close (stream, TRUE);

                // if necessary, version enable the stream
                ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

                // select locks still remaining
                result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_FILTER_MY_LOCKS | SE_ROWLOCKING_UNLOCK_ON_QUERY | SE_ROWLOCKING_LOCK_ONLY);
                handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");

                // get the list of row ids from the log file
                result = SE_stream_query_logfile (stream, logfile, 1, columns, &sql_construct);
                handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_LOG_FILE_QUERY, "Unable to query log file.");

                // execute the query that unlocks rows
                result = SE_stream_execute (stream);
                handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");
            }
            else
                throw FdoException::Create (NlsMsgGet(ARCSDE_UNEXPECTED_ERROR, "Unexpected error encountered in ArcSDE Provider."));
            break;
        default:
            handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_FETCH, "Stream fetch failed.");
    }

    // release the transaction lock
    if (reader != NULL)
        reader->Close ();

    // clean up
    if (NULL != locks)
        free(locks);
    result = SE_stream_free (stream);
    handle_sde_err<FdoCommandException>(connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_FREE, "Stream free failed.");
    delete[] where;
    if (NULL != filters)
    {
        for (int i = 0; i < count; i++)
            if (NULL != filters[i].filter.shape)
                SE_shape_free (filters[i].filter.shape);
        delete[] filters;
    }

    return (FDO_SAFE_ADDREF (ret.p));
}
void FdoSpatialContextTest::DoTest( bool hasMetaSchema )
{
    FdoPtr<FdoIConnection> connection;
    StaticConnection* staticConn = NULL;

    try {
        if ( !hasMetaSchema ) {
            staticConn = UnitTestUtil::NewStaticConnection();
            staticConn->connect();
            UnitTestUtil::CreateDBNoMeta( 
                staticConn->CreateSchemaManager(),
                UnitTestUtil::GetEnviron("datastore", DB_NAME_SUFFIX)
            );
        }


        // delete, re-create and open the datastore
		printf( "Initializing Connection ... \n" );
		connection = UnitTestUtil::CreateConnection(
			hasMetaSchema,
			hasMetaSchema,
            DB_NAME_SUFFIX,
            0,
            NULL,
            0
		);

		printf( "Creating Spatial Contexts ... \n" );

        UnitTestUtil::CreateSpatialContext( connection, L"Bermuda", L"Bermuda 1957", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Rectangular", L"", 0, 0, 1000, 1000 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Bermuda Duplicate", L"Bermuda 1957", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Luxembourg Delete", L"Luxembourg 1930", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"South", L"Australian Antarctic", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"sc_2", L"Puerto Rico", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"South Delete", L"Australian Antarctic", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"sc_1", L"NAD27", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"South Duplicate", L"Australian Antarctic", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Liberia by WKT", L"", 0, 0, 10, 10, L"GEOGCS[\"Liberia 1964\", DATUM[\"Liberia 1964\", ELLIPSOID[\"Clarke 1880 (RGS)\", 6378249.145, 293.465]], PRIMEM[\"Greenwich\", 0], UNIT[\"Degree\", 0.0174532925199433]]" ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Qatar wrong name", L"Bermuda 1957", 0, 0, 10, 10, L"GEOGCS[\"Qatar 1974\", DATUM[\"Qatar 1974\", ELLIPSOID[\"International 1924\", 6378388, 297]], PRIMEM[\"Greenwich\", 0], UNIT[\"Degree\", 0.0174532925199433]]" ); 
        UnitTestUtil::CreateSpatialContext( connection, L"California", L"CA-I", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Bermuda Mentor", L"Bermuda.LL", 0, 0, 10, 10 ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Mentor by WKT", L"", 0, 0, 10, 10, L"PROJCS[\"Quebec test\",GEOGCS[\"For testing only\",DATUM[\"Test\",SPHEROID[\"NAD 27\",6300000,123.465,]]]]" ); 
        UnitTestUtil::CreateSpatialContext( connection, L"Rectangular (Metre)", L"XY-M", 0, 0, 10, 10); 
        UnitTestUtil::CreateSpatialContext( connection, L"Rectangular (Feet)", L"XY-FT", 0, 0, 10, 10); 

        connection->Close();
        connection->Open();

		printf( "Deleting Spatial Contexts ... \n" );

        UnitTestUtil::DeleteSpatialContext( connection, L"Luxembourg Delete" );
        UnitTestUtil::DeleteSpatialContext( connection, L"South Delete" );

        connection->Close();
        connection->Open();

        CreateSchema( connection, hasMetaSchema );

		printf( "Writing output ... \n" );

        FdoStringP datastore = UnitTestUtil::GetEnviron("datastore", DB_NAME_SUFFIX);

        FdoIoMemoryStreamP stream1 = FdoIoMemoryStream::Create();

        FdoXmlSpatialContextFlagsP flags = FdoXmlSpatialContextFlags::Create(
            L"fdo.osgeo.org/schemas/feature",
            FdoXmlFlags::ErrorLevel_Normal,
            true,
            FdoXmlSpatialContextFlags::ConflictOption_Add,
            true
        );

        UnitTestUtil::ExportDb( 
            connection, 
            stream1, 
            flags,
            false, 
            FdoStringP(L"Fdo") + datastore
        );

   		UnitTestUtil::Config2SortedFile( stream1, UnitTestUtil::GetOutputFileName( GenFileName(1, hasMetaSchema, false) ) );

        UnitTestUtil::CheckOutput( 
            GenFileName( 1, hasMetaSchema, true ),
            UnitTestUtil::GetOutputFileName( GenFileName(1, hasMetaSchema, false) )
        );

        InsertFeatures( connection );

        stream1 = FdoIoMemoryStream::Create();

        UnitTestUtil::ExportDb( 
            connection, 
            stream1, 
            flags,
            false, 
            FdoStringP(L"Fdo") + datastore,
            L"AutoGen",
            true
        );

   		UnitTestUtil::Config2SortedFile( stream1, UnitTestUtil::GetOutputFileName( GenFileName(2, hasMetaSchema, false) ) );

        UnitTestUtil::CheckOutput( 
            GenFileName( 2, hasMetaSchema, true ),
            UnitTestUtil::GetOutputFileName( GenFileName(2, hasMetaSchema, false) )
        );

        if ( !hasMetaSchema ) {
            CreateTables( staticConn, datastore );

            connection->Close();
            connection->Open();

            stream1 = FdoIoMemoryStream::Create();

            UnitTestUtil::ExportDb( 
                connection, 
                stream1, 
                flags,
                false, 
                FdoStringP(L"Fdo") + datastore,
                L"AutoGen",
                true
            );

   		    UnitTestUtil::Config2SortedFile( stream1, UnitTestUtil::GetOutputFileName( GenFileName(3, hasMetaSchema, false) ) );

            UnitTestUtil::CheckOutput( 
                GenFileName( 3, hasMetaSchema, true ),
                UnitTestUtil::GetOutputFileName( GenFileName(3, hasMetaSchema, false) )
            );


            try {
                UnitTestUtil::CreateSpatialContext( connection, L"Nowhere", L"JunkCS", 0, 0, 10, 10 ); 
                CPPUNIT_FAIL( "Setting unsupported coordinate system by name supposed to fail" );
            }
            catch (FdoException* e ) {
#ifdef _WIN32
#ifdef _DEBUG
                FdoStringP expectedMessage = L" Error creating spatial context Nowhere, coordinate system JunkCS is not in current datastore. ";
                FdoString* pMessage = wcschr( e->GetExceptionMessage(), ')' );
                if (pMessage) pMessage++;
#else
                FdoStringP expectedMessage = L"Error creating spatial context Nowhere, coordinate system JunkCS is not in current datastore. ";
                FdoString* pMessage = e->GetExceptionMessage();
#endif
                CPPUNIT_ASSERT( pMessage && expectedMessage.ICompare(pMessage) == 0 );
#endif
                FDO_SAFE_RELEASE(e);
            }

            try {
                UnitTestUtil::CreateSpatialContext( connection, L"California2", L"", 0, 0, 10, 10, L"PROJCS[\"CA-I\",GEOGCS[\"LL27\",DATUM[\"NAD27\",SPHEROID[\"CLRK66\",60.400,294.97869821]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"false_easting\",2000000.000],PARAMETER[\"false_northing\",0.000],PARAMETER[\"central_meridian\",-122.00000000000000],PARAMETER[\"latitude_of_origin\",39.33333333333333],PARAMETER[\"standard_parallel_1\",41.66666666666666],PARAMETER[\"standard_parallel_2\",40.00000000000000],UNIT[\"Foot_US\",0.30480060960122]]" ); 
                CPPUNIT_FAIL( "Setting unsupported coordinate system by wkt supposed to fail" );
            }
            catch (FdoException* e ) {
#ifdef _WIN32
#ifdef _DEBUG
                FdoStringP expectedMessage = L" Error creating spatial context California2, coordinate system catalog does not contain entry for WKT 'PROJCS[\"CA-I\",GEOGCS[\"LL27\",DATUM[\"NAD27\",SPHEROID[\"CLRK66\",60.400,294.97869821]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"false_easting\",2000000.000],PARAMETER[\"false_northing\",0.000],PARAMETER[\"central_meridian\",-122.00000000000000],PARAMETER[\"latitude_of_origin\",39.33333333333333],PARAMETER[\"standard_parallel_1\",41.66666666666666],PARAMETER[\"standard_parallel_2\",40.00000000000000],UNIT[\"Foot_US\",0.30480060960122]]' ";
                FdoString* pMessage = wcschr( e->GetExceptionMessage(), ')' );
                if (pMessage) pMessage++;
#else
                FdoStringP expectedMessage = L"Error creating spatial context California2, coordinate system catalog does not contain entry for WKT 'PROJCS[\"CA-I\",GEOGCS[\"LL27\",DATUM[\"NAD27\",SPHEROID[\"CLRK66\",60.400,294.97869821]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"false_easting\",2000000.000],PARAMETER[\"false_northing\",0.000],PARAMETER[\"central_meridian\",-122.00000000000000],PARAMETER[\"latitude_of_origin\",39.33333333333333],PARAMETER[\"standard_parallel_1\",41.66666666666666],PARAMETER[\"standard_parallel_2\",40.00000000000000],UNIT[\"Foot_US\",0.30480060960122]]' ";
                FdoString* pMessage = e->GetExceptionMessage();
#endif
                CPPUNIT_ASSERT( pMessage && expectedMessage.ICompare(pMessage) == 0 );
#endif
                FDO_SAFE_RELEASE(e);
            }
        }
        else {
            UnitTestUtil::CreateSpatialContext( connection, L"Nowhere", L"JunkCS", 0, 0, 10, 10 ); 
            UnitTestUtil::CreateSpatialContext( connection, L"California2", L"CA_I", 0, 0, 10, 10, L"PROJCS[\"CA-I\",GEOGCS[\"LL27\",DATUM[\"NAD27\",SPHEROID[\"CLRK66\",60.400,294.97869821]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"false_easting\",2000000.000],PARAMETER[\"false_northing\",0.000],PARAMETER[\"central_meridian\",-122.00000000000000],PARAMETER[\"latitude_of_origin\",39.33333333333333],PARAMETER[\"standard_parallel_1\",41.66666666666666],PARAMETER[\"standard_parallel_2\",40.00000000000000],UNIT[\"Foot_US\",0.30480060960122]]" ); 

            stream1 = FdoIoMemoryStream::Create();
            UnitTestUtil::ExportDb( 
                connection, 
                stream1, 
                flags,
                false, 
                FdoStringP(L"Fdo") + datastore,
                L"AutoGen",
                true
            );

            UnitTestUtil::Config2SortedFile( stream1, UnitTestUtil::GetOutputFileName( GenFileName(3, hasMetaSchema, false) ) );

            UnitTestUtil::CheckOutput( 
                GenFileName( 3, hasMetaSchema, true ),
                UnitTestUtil::GetOutputFileName( GenFileName(3, hasMetaSchema, false) )
            );

        }

        delete staticConn;
        connection->Close();
    }
    catch ( ... )
    {
        try {
            if ( staticConn ) delete staticConn;
            if ( connection ) connection->Close();
        }
        catch ( ... ) {
        }

        throw;
    }
}
/* Test basic update operation. */
void BasicUpdateTests::simple_update ()
{
    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcov());
        mConnection->Open ();

		// Clean up previous tests:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassSimple(), ArcSDETestConfig::ClassNameTestClassSimple(), true);

        // insert a feature
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassSimple());
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)FdoExpression::Parse (Data[0]->mPropertyData[0]);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (Data[0]->mPropertyName, expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5108.8 5104.7, 5109 5104, 5109 5105, 5108.8 5104.7))')");
        value = FdoPropertyValue::Create ((FdoString*)GetGeomPropName(), expression);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();

        int id;
        while (reader->ReadNext ())
            id = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        // update it
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassSimple());
	    FdoPtr<FdoPropertyValueCollection> propertyValues = update->GetPropertyValues();
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf(filter, ELEMENTS(filter), L"%ls = %d", (FdoString*)GetIdPropName(), id);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
	    values = update->GetPropertyValues ();
	    value = FdoPropertyValue::Create ();
        value->SetName (Data[0]->mPropertyName);
        //FdoPtr<FdoStringValue> _string = static_cast<FdoStringValue*>(value->GetValue ());
        //_string->SetNull ();
		value->SetValue (L"'All mimsy were the borogoves'");
        values->Add (value);
        if (1 != update->Execute ())
            CPPUNIT_FAIL ("update execute failed");

        // check by doing a select
        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassSimple());
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect value", 0 == wcscmp (L"All mimsy were the borogoves", reader->GetString (Data[0]->mPropertyName)));
            // check geometry was not affected
            FdoPtr<FdoGeometryValue> geometry = (FdoGeometryValue*)FDO_SAFE_ADDREF(expression.p);
            FdoPtr<FdoByteArray> fetched = reader->GetGeometry ((FdoString*)GetGeomPropName());
            FdoString* geometryText = geometry->ToString();
            FdoPtr<FdoGeometryValue> fetchedGeom = FdoGeometryValue::Create (fetched);
            FdoString* fetchedText = fetchedGeom->ToString ();
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", 0==wcscmp(geometryText, fetchedText));
        }
        reader->Close();

		// Clean up after test:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassSimple(), ArcSDETestConfig::ClassNameTestClassSimple(), true);
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}
/* Test insert/update/select on a table that has a UUID column. */
void BasicUpdateTests::update_uuid ()
{
    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcov());
        mConnection->Open ();

		// Clean up previous tests:
        CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassUuid(), ArcSDETestConfig::ClassNameTestClassUuid(), true);
        
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassUuid());
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoStringValue> expression = FdoStringValue::Create (L"Added");
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (AdjustRdbmsName(L"MYSTRING"), expression);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();

        expression->SetString(L"Updated");
        reader = insert->Execute ();

        expression->SetString(L"Deleted");
        reader = insert->Execute ();

        FdoStringP addedUuid1;
        FdoStringP updatedUuid1;
        FdoStringP deletedUuid;
        FdoStringP updatedUuid2 = L"{ABCDEFGH-IJKL-MNOP-QRST-UVWXYZ123456}";
        FdoStringP addedUuid3;
        FdoStringP updatedUuid3;
        
        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassUuid());
        reader = select->Execute ();

        while (reader->ReadNext ())
        {
            FdoStringP myString = reader->GetString(AdjustRdbmsName(L"MYSTRING"));

            if ( myString == L"Added" ) 
                addedUuid1 = reader->GetString(AdjustRdbmsName(L"ID"));
            else if ( myString == L"Updated" ) 
                updatedUuid1 = reader->GetString(AdjustRdbmsName(L"ID"));
            else if ( myString == L"Deleted" ) 
                deletedUuid = reader->GetString(AdjustRdbmsName(L"ID"));
        }
        reader->Close();
     
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassUuid());
        FdoStringP filter = FdoStringP::Format( L"%ls = '%ls'", (FdoString*) AdjustRdbmsName(L"ID"), (FdoString*) updatedUuid1 );
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
	    values = update->GetPropertyValues ();
	    value = FdoPropertyValue::Create ();
        value->SetName (AdjustRdbmsName(L"ID"));
        expression = FdoStringValue::Create (updatedUuid2);
        value->SetValue (expression);
        values->Add (value);

        bool updateFailed = false;

        // ID is readonly so update should fail.
        try 
        {
            update->Execute ();
        }
        catch ( FdoException* ex ) 
        {
            ex->Release();
            updateFailed = true;
        }

        CPPUNIT_ASSERT ("update failed");

        FdoPtr<FdoIDelete> dlte = (FdoIDelete*)mConnection->CreateCommand (FdoCommandType_Delete);
        dlte->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassUuid());
        filter = FdoStringP::Format( L"%ls = '%ls'", (FdoString*) AdjustRdbmsName(L"ID"), (FdoString*) deletedUuid );
        dlte->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        if (1 != dlte->Execute ())
            CPPUNIT_FAIL ("delete execute failed");

        // check by doing a select
        select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassUuid());
        reader = select->Execute ();
        int count = 0;
        while (reader->ReadNext ())
        {
            count++;
            FdoStringP myString = reader->GetString(AdjustRdbmsName(L"MYSTRING"));
            if ( myString == L"Added" ) 
                addedUuid3 = reader->GetString(AdjustRdbmsName(L"ID"));
            else if ( myString == L"Updated" ) 
                updatedUuid3 = reader->GetString(AdjustRdbmsName(L"ID"));
        }
        reader->Close();

        CPPUNIT_ASSERT( count == 2 );
        CPPUNIT_ASSERT( addedUuid3 == addedUuid1 );
        CPPUNIT_ASSERT( updatedUuid3 == updatedUuid1 );
        CPPUNIT_ASSERT( updatedUuid3 != updatedUuid2 );

        mConnection->Close();
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}
/* Test spatial filter. */
void BasicUpdateTests::spatial_filter ()
{
    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcovSingleDb());
        mConnection->Open ();

		// Clean up previous tests:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);

        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)FdoExpression::Parse (Data[0]->mPropertyData[0]);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (Data[0]->mPropertyName, expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5010.282 5011.717, 5010.4 5011.7, 5010.4 5011.3, 5010.282 5011.717))')");
        value = FdoPropertyValue::Create ((FdoString*)GetGeomPropName(), expression);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();

        int id1;
        while (reader->ReadNext ())
            id1 = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        value = values->GetItem (Data[0]->mPropertyName);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'John Smith'");
        value->SetValue (expression);
        value = values->GetItem ((FdoString*)GetGeomPropName());
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5000.919 5000.277, 5000.5 5000.2, 5000.5 5000.7, 5000.919 5000.277))')");
        value->SetValue (expression);
        reader = insert->Execute ();
        int id2;
        while (reader->ReadNext ())
            id2 = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        value = values->GetItem (Data[0]->mPropertyName);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'Mott the Hoople'");
        value->SetValue (expression);
        value = values->GetItem ((FdoString*)GetGeomPropName());
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5014.262 5015.018, 5014.3 5015.9, 5014.9 5015.9, 5014.262 5015.018))')");
        value->SetValue (expression);
        reader = insert->Execute ();
        int id3;
        while (reader->ReadNext ())
            id3 = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        // do a spatial filtered update
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (L"SHAPE INTERSECTS GEOMFROMTEXT ('POLYGON XY (( 5012 5012, 5020 5012, 5020 5016, 5012 5016, 5012 5012 ))')")));
	    values = update->GetPropertyValues ();
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'Alice in Wonderland'");
        value = FdoPropertyValue::Create (Data[0]->mPropertyName, expression);
        values->Add (value);
        if (1 != update->Execute ())
            CPPUNIT_FAIL ("update execute failed");

        // check by doing a select
        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        reader = select->Execute ();
        int id;
        while (reader->ReadNext ())
        {
            id = reader->GetInt32 ((FdoString*)GetIdPropName());
            FdoString* item = reader->GetString (Data[0]->mPropertyName);
            if (id == id3)
                CPPUNIT_ASSERT_MESSAGE ("value not changed", 0 == wcscmp (item, L"Alice in Wonderland"));
            else
                CPPUNIT_ASSERT_MESSAGE ("value mistakenly changed", 0 != wcscmp (item, L"Alice in Wonderland"));
        }
        reader->Close();

		// Clean up after test:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}
/* Test geometry update operation. */
void BasicUpdateTests::geometry_update ()
{
    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcovSingleDb());
        mConnection->Open ();

		// Clean up previous tests:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);

        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex()); // misnomer, it's not a feature class
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)FdoExpression::Parse (Data[0]->mPropertyData[0]);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (Data[0]->mPropertyName, expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5010.282 5011.717, 5011 5012, 5013 5012, 5010.282 5011.717))')");
        FdoPtr<FdoPropertyValue> geometry = FdoPropertyValue::Create ((FdoString*)GetGeomPropName(), expression);
        values->Add (geometry);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();

        int id;
        while (reader->ReadNext ())
            id = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        value = values->GetItem (Data[0]->mPropertyName);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'John Smith'");
        value->SetValue (expression);
        value = values->GetItem ((FdoString*)GetGeomPropName());
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5000.919 5000.277, 5005 5000, 5005 5005, 5000.919 5000.277))')");
        value->SetValue (expression);
        reader = insert->Execute ();
        int id2;
        while (reader->ReadNext ())
            id2 = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();
        value = values->GetItem (Data[0]->mPropertyName);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'Mott the Hoople'");
        value->SetValue (expression);
        value = values->GetItem ((FdoString*)GetGeomPropName());
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5014.262 5000.018, 5015 5005, 5016 5010, 5014.262 5000.018))')");
        value->SetValue (expression);
        reader = insert->Execute ();
        int id3;
        while (reader->ReadNext ())
            id3 = reader->GetInt32 ((FdoString*)GetIdPropName());
        reader->Close();

        // update it
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
	    FdoPtr<FdoPropertyValueCollection> propertyValues = update->GetPropertyValues();
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf(filter, ELEMENTS(filter), L"%ls = %d", (FdoString*)GetIdPropName(), id);
		FdoPtr<FdoFilter> fdoFilter = FdoFilter::Parse (filter);
        update->SetFilter (fdoFilter);
	    values = update->GetPropertyValues ();
        expression = (FdoValueExpression*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5008.8 5004.7, 5010 5010, 5000 5005, 5008.8 5004.7))')");
        value = FdoPropertyValue::Create ((FdoString*)GetGeomPropName(), expression);
        values->Add (value);

        if (1 != update->Execute ())
            CPPUNIT_FAIL ("update execute failed");

        // check by doing a select
        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
		fdoFilter = FdoFilter::Parse (filter);
        select->SetFilter (fdoFilter);
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            FdoPtr<FdoGeometryValue> geometry = FDO_SAFE_ADDREF((FdoGeometryValue*)expression.p);
            FdoPtr<FdoByteArray> fetched = reader->GetGeometry ((FdoString*)GetGeomPropName());
            FdoString* referenceText = geometry->ToString();
            FdoPtr<FdoGeometryValue> fetchedGeom = FdoGeometryValue::Create (fetched);
            const wchar_t* fetchedText = fetchedGeom->ToString ();
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", 0==wcscmp(referenceText, fetchedText));
        }
        reader->Close();

		// Clean up after test:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}
/* Test all data types update operation. */
void BasicUpdateTests::full_update ()
{
    int iRow = 0;
    FdoPtr<FdoPropertyValueCollection> values;
    FdoPtr<FdoISelect> selectCmd;
    FdoPtr<FdoIFeatureReader> reader;

    if (CreateSchemaOnly())  return;

    try
    {
        mConnection = ArcSDETests::GetConnection ();
        mConnection->SetConnectionString (ArcSDETestConfig::ConnStringMetadcovSingleDb());
        mConnection->Open ();

		// Clean up previous tests:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);

        // Insert 2 rows of data:
        while (iRow<=1)
        {
            FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
            insert->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex()); // misnomer, it's not a feature class
            values = insert->GetPropertyValues ();
            for (int i = 0; i < PropertyCount; i++)
            {
                FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create ();
                value->SetName (Data[i]->mPropertyName);
                FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ArcSDETests::ParseByDataType (Data[i]->mPropertyData[iRow], Data[i]->mPropertyType);
                value->SetValue (expression);
                values->Add (value);
            }
            reader = insert->Execute ();
            // none returned: reader->Close ();

            iRow++;
        }
        // check by doing a select
        selectCmd = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        selectCmd->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        reader = selectCmd->Execute ();
        FdoInt32 iSelectedRow = 0;
        while (reader->ReadNext ())
        {
            // NOTE: we're assuming we receive the rows in the same order we inserted them
            for (int i = 0; i < PropertyCount; i++)
                checkEqual(reader, Data[i]->mPropertyName, Data[i]->mPropertyType, Data[i]->mPropertyData[iSelectedRow]);
            iSelectedRow++;
        }
        reader->Close ();


        // Update both rows, providing several values in the *reverse* order as class properties appear:
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex()); // misnomer, it's not a feature class
        wchar_t filter[1024];
        wcscpy (filter, Data[3]->mPropertyName);
        wcscat (filter, L" = ");
        wcscat (filter, Data[3]->mPropertyData[0]);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        for (int iPropertyIndex = 0; iPropertyIndex < PropertyCount; iPropertyIndex++)
        {
            int iDataIndex = (PropertyCount - 1) - iPropertyIndex;
            FdoPtr<FdoValueExpression> expression;
            expression = (FdoValueExpression*)ArcSDETests::ParseByDataType (Data[iDataIndex]->mPropertyData[iRow], Data[iDataIndex]->mPropertyType);
            FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (Data[iDataIndex]->mPropertyName, expression);
            values->Add (value);
        }
        FdoInt32 iUpdatedRows = update->Execute ();
        //NOTE: iUpdatedRows is currently always 1, regardless of the # of rows actually affected.

        // check by doing a select
        selectCmd = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        selectCmd->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        reader = selectCmd->Execute ();
        while (reader->ReadNext ())
            for (int i = 0; i < PropertyCount; i++)
                checkEqual(reader, Data[i]->mPropertyName, Data[i]->mPropertyType, Data[i]->mPropertyData[iRow]);
        reader->Close ();

        iRow++;



        // Update both rows, providing *mostly NULL value* in the *same* order as class properties appear:
        update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex()); // misnomer, it's not a feature class
        wcscpy (filter, Data[3]->mPropertyName);
        wcscat (filter, L" = ");
        wcscat (filter, Data[3]->mPropertyData[iRow-1]);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        for (int i = 0; i < PropertyCount; i++)
        {
            FdoPtr<FdoValueExpression> expression;
            expression = (FdoValueExpression*)ArcSDETests::ParseByDataType (Data[i]->mPropertyData[iRow], Data[i]->mPropertyType);
            FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (Data[i]->mPropertyName, expression);
            value->SetValue (expression);
            values->Add (value);
        }
        iUpdatedRows = update->Execute ();
        //NOTE: iUpdatedRows is currently always 1, regardless of the # of rows actually affected.

        // check by doing a select
        selectCmd = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        selectCmd->SetFeatureClassName (ArcSDETestConfig::QClassNameTestClassComplex());
        reader = selectCmd->Execute ();
        while (reader->ReadNext ())
            for (int i = 0; i < PropertyCount; i++)
                checkEqual(reader, Data[i]->mPropertyName, Data[i]->mPropertyType, Data[i]->mPropertyData[iRow]);
        reader->Close ();


		// Clean up after test:
		CleanUpClass(mConnection, ArcSDETestConfig::ClassSchemaTestClassComplex(), ArcSDETestConfig::ClassNameTestClassComplex(), true);
    }
    catch (FdoException* ge) 
    {
        fail (ge);
    }
}