/*
 * 
* Copyright (C) 2004-2006  Autodesk, Inc.
* 
* This library is free software; you can redistribute it and/or
* modify it under the terms of version 2.1 of the GNU Lesser
* General Public License as published by the Free Software Foundation.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
* 
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
* 
 */

#include "Pch.h"
#include "UpdateTests.h"

#include <FdoSpatial.h>
#include <FdoCommonFile.h>

#ifdef _WIN32
#define LOCATION L"..\\..\\TestData\\Testing"
#else
#define LOCATION L"../../TestData/Testing"
#endif

CPPUNIT_TEST_SUITE_REGISTRATION (UpdateTests);
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION (UpdateTests, "UpdateTests");

FdoPtr<FdoIConnection> UpdateTests::mConnection;

UpdateTests::UpdateTests (void)
{
}

UpdateTests::~UpdateTests (void)
{
}

void UpdateTests::setUp ()
{
    if (!FdoCommonFile::FileExists (LOCATION))
        FdoCommonFile::MkDir (LOCATION);
    mConnection = ShpTests::GetConnection ();
    mConnection->SetConnectionString (L"DefaultFileLocation=" LOCATION);
    CPPUNIT_ASSERT_MESSAGE ("connection state not open", FdoConnectionState_Open == mConnection->Open ());
}

void UpdateTests::tearDown ()
{
    // delete the class, if its there:
    TestCommonSchemaUtil::CleanUpClass(mConnection, NULL, L"Test");

    mConnection->Close ();
    FDO_SAFE_RELEASE(mConnection.p);

    if (FdoCommonFile::FileExists (LOCATION))
        FdoCommonFile::RmDir (LOCATION);
}

void UpdateTests::create_schema (FdoGeometricType type, bool elevation, bool measure)
{
    // delete the class, if its there:
    TestCommonSchemaUtil::CleanUpClass(mConnection, NULL, L"Test");

    // create the class
    FdoPtr<FdoFeatureSchema> schema = FdoFeatureSchema::Create (L"TheSchema", L" test schema");
    FdoPtr<FdoClassCollection> classes = schema->GetClasses ();

    FdoPtr<FdoDataPropertyDefinition> featid = FdoDataPropertyDefinition::Create (L"FeatId", L"integer");
    featid->SetDataType (FdoDataType_Int32);
    featid->SetIsAutoGenerated (true);
    featid->SetNullable (false);

    FdoPtr<FdoDataPropertyDefinition> id = FdoDataPropertyDefinition::Create (L"Id", L"integer");
    id->SetDataType (FdoDataType_Decimal);
    id->SetPrecision(10);
    id->SetScale(0);

    FdoPtr<FdoDataPropertyDefinition> street = FdoDataPropertyDefinition::Create (L"Street", L"text");
    street->SetDataType (FdoDataType_String);
    street->SetLength (64);

    FdoPtr<FdoDataPropertyDefinition> area = FdoDataPropertyDefinition::Create (L"Area", L"double");
    area->SetDataType (FdoDataType_Decimal);
    area->SetPrecision (20);
    area->SetScale (20);

    FdoPtr<FdoDataPropertyDefinition> vacant = FdoDataPropertyDefinition::Create (L"Vacant", L"boolean");
    vacant->SetDataType (FdoDataType_Boolean);

    FdoPtr<FdoDataPropertyDefinition> birthday = FdoDataPropertyDefinition::Create (L"Birthday", L"date");
    birthday->SetDataType (FdoDataType_DateTime);

    FdoPtr<FdoDataPropertyDefinition> age = FdoDataPropertyDefinition::Create (L"Age", L"an int32 property");
    age->SetDataType (FdoDataType_Int32);

    // build a location geometry property
    FdoPtr<FdoGeometricPropertyDefinition> location = FdoGeometricPropertyDefinition::Create (L"Geometry", L"geometry");
    location->SetGeometryTypes (type);
    location->SetHasElevation (elevation);
    location->SetHasMeasure (measure);

    //// assemble the feature class
    FdoPtr<FdoFeatureClass> feature = FdoFeatureClass::Create (L"Test", L"test class created with apply schema");
    FdoPtr<FdoPropertyDefinitionCollection> properties = feature->GetProperties ();
    FdoPtr<FdoDataPropertyDefinitionCollection> identities = feature->GetIdentityProperties ();
    properties->Add (featid);
    identities->Add (featid);
    properties->Add (id);
    properties->Add (street);
    properties->Add (area);
    properties->Add (vacant);
    properties->Add (birthday);
    properties->Add (age);
    properties->Add (location);
    feature->SetGeometryProperty (location);

    // submit the new schema
    classes->Add (feature);
    FdoPtr<FdoIApplySchema> apply = (FdoIApplySchema*)mConnection->CreateCommand (FdoCommandType_ApplySchema);
    apply->SetFeatureSchema (schema);
    apply->Execute ();
}

void UpdateTests::update ()
{
    try
    {
        create_schema (FdoGeometricType_Point, true, true);
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"24", FdoDataType_Decimal);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'1147 Trafford Drive'");
        value = FdoPropertyValue::Create (L"Street", expression);
        values->Add (value);
        // add NULL geometry value:
        FdoPtr<FdoGeometryValue> geometry = FdoGeometryValue::Create ();
        geometry->SetNullValue ();
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 featid;
        featid = -1;
        while (reader->ReadNext ())
        {
            if (-1 != featid)
                CPPUNIT_FAIL ("too many features inserted");
            featid = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();
        if (-1 == featid)
            CPPUNIT_FAIL ("too few features inserted");

        // update it
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", featid);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        value = FdoPropertyValue::Create ();
        value->SetName (L"Street");
        value->SetValue (L"'88 Noodle Court'");
        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 (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect featid value", featid == reader->GetInt32 (L"FeatId"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect id value", 24 == reader->GetDouble (L"Id"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"88 Noodle Court", reader->GetString (L"Street")));
            CPPUNIT_ASSERT_MESSAGE ("incorrect area value", reader->IsNull(L"Area"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->IsNull(L"Vacant"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect birthday year value", reader->IsNull (L"Birthday"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", reader->IsNull (L"Geometry"));
        }
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}

void UpdateTests::update_geometry_point_xy ()
{
    try
    {
        create_schema (FdoGeometricType_Point, false, false);
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"24", FdoDataType_Decimal);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'1147 Trafford Drive'");
        value = FdoPropertyValue::Create (L"Street", expression);
        values->Add (value);
        // add real geometry value:
        FdoPtr<FdoGeometryValue> geometry = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('POINT XY ( 999000 -999000 )')");
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 featid;
        featid = -1;
        while (reader->ReadNext ())
        {
            if (-1 != featid)
                CPPUNIT_FAIL ("too many features inserted");
            featid = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();
        if (-1 == featid)
            CPPUNIT_FAIL ("too few features inserted");

        // update it
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", featid);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        geometry = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('POINT XY ( 25626 2929 )')");
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        value->SetName (L"Geometry");
        value->SetValue (geometry);
        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 (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect featid value", featid == reader->GetInt32 (L"FeatId"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect id value", 24 == reader->GetDouble (L"Id"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"1147 Trafford Drive", reader->GetString (L"Street")));
            CPPUNIT_ASSERT_MESSAGE ("incorrect area value", reader->IsNull(L"Area"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->IsNull(L"Vacant"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect birthday year value", reader->IsNull (L"Birthday"));
            CPPUNIT_ASSERT_MESSAGE ("geometry is null", !reader->IsNull (L"Geometry"));
            FdoPtr<FdoByteArray> before = geometry->GetGeometry ();
            FdoPtr<FdoByteArray> after = reader->GetGeometry (L"Geometry");
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry size", before->GetCount () == after->GetCount ());
            int count = before->GetCount ();
            for (int i = 0; i < count; i++)
            {
                FdoByte left = before->GetData ()[i];
                FdoByte right = after->GetData ()[i];
                CPPUNIT_ASSERT_MESSAGE ("incorrect geometry content", left == right);
            }
        }
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}

// in this test the shape gets bigger, forcing the back end of the file to move
void UpdateTests::update_geometry_line_xy ()
{
    try
    {
        create_schema (FdoGeometricType_Curve, false, false);
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = FdoDecimalValue::Create (INT_MAX);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'~!@#$%^&*()'");
        value = FdoPropertyValue::Create (L"Street", expression);
        values->Add (value);
        expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"-8.8282e12", FdoDataType_Decimal);
        value = FdoPropertyValue::Create (L"Area", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"false");
        value = FdoPropertyValue::Create (L"Vacant", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"DATE'1957-3-2'");
        value = FdoPropertyValue::Create (L"Birthday", expression);
        values->Add (value);

        // add geometry value:
        FdoPtr<FdoGeometryValue> geometry = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('LINESTRING XY ( 7171.723 8282.99, 6824.82 6545.87, 8920.5 9929.77)')");
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 id;
        id = -1;
        while (reader->ReadNext ())
        {
            if (-1 != id)
                CPPUNIT_FAIL ("too many features inserted");
            id = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();

        if (-1 == id)
            CPPUNIT_FAIL ("too few features inserted");

        // insert a second one
        FdoPtr<FdoGeometryValue> geometry2 = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('LINESTRING XY ( 6677.99 7820.89, 6272.90 7020.20, 7012.82 7516.91)')");
        value->SetValue (geometry2);
        reader = insert->Execute ();
        FdoInt32 id2;
        id2 = -1;
        while (reader->ReadNext ())
        {
            if (-1 != id2)
                CPPUNIT_FAIL ("too many features inserted");
            id2 = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();

        // update the first one
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", id);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        FdoPtr<FdoGeometryValue> geometry3 = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('LINESTRING XY ( 123.45 872.45, 891.23 828.77, 882.99 728.34, 677.92 776.43, 552.52 928.45)')");
        value = FdoPropertyValue::Create (L"Geometry", geometry3);
        value->SetName (L"Geometry");
        value->SetValue (geometry3);
        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 (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            if (id == reader->GetInt32 (L"FeatId"))
            {
                CPPUNIT_ASSERT_MESSAGE ("incorrect id value", INT_MAX == reader->GetDouble (L"Id"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"~!@#$%^&*()", reader->GetString (L"Street")));
                CPPUNIT_ASSERT_MESSAGE ("incorrect area value", -8.8282e12 == reader->GetDouble (L"Area"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", !reader->GetBoolean (L"Vacant"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 1957 == reader->GetDateTime (L"Birthday").year);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 3 == reader->GetDateTime (L"Birthday").month);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 2 == reader->GetDateTime (L"Birthday").day);
                CPPUNIT_ASSERT_MESSAGE ("geometry is null", !reader->IsNull (L"Geometry"));
                FdoPtr<FdoByteArray> before = geometry3->GetGeometry ();
                FdoPtr<FdoByteArray> after = reader->GetGeometry (L"Geometry");
                int b = before->GetCount ();
                int a = after->GetCount ();
                CPPUNIT_ASSERT_MESSAGE ("incorrect geometry size", b == a);
                int count = before->GetCount ();
                for (int i = 0; i < count; i++)
                {
                    FdoByte left = before->GetData ()[i];
                    FdoByte right = after->GetData ()[i];
                    CPPUNIT_ASSERT_MESSAGE ("incorrect geometry content", left == right);
                }
            }
            else if (id2 == reader->GetInt32 (L"FeatId"))
            {
                CPPUNIT_ASSERT_MESSAGE ("incorrect id value", INT_MAX == reader->GetDouble (L"Id"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"~!@#$%^&*()", reader->GetString (L"Street")));
                CPPUNIT_ASSERT_MESSAGE ("incorrect area value", -8.8282e12 == reader->GetDouble (L"Area"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", !reader->GetBoolean (L"Vacant"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 1957 == reader->GetDateTime (L"Birthday").year);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 3 == reader->GetDateTime (L"Birthday").month);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 2 == reader->GetDateTime (L"Birthday").day);
                CPPUNIT_ASSERT_MESSAGE ("geometry is null", !reader->IsNull (L"Geometry"));
                FdoPtr<FdoByteArray> before = geometry2->GetGeometry ();
                FdoPtr<FdoByteArray> after = reader->GetGeometry (L"Geometry");
                int b = before->GetCount ();
                int a = after->GetCount ();
                CPPUNIT_ASSERT_MESSAGE ("incorrect geometry size", b == a);
                int count = before->GetCount ();
                for (int i = 0; i < count; i++)
                {
                    FdoByte left = before->GetData ()[i];
                    FdoByte right = after->GetData ()[i];
                    CPPUNIT_ASSERT_MESSAGE ("incorrect geometry content", left == right);
                }
            }
        }
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}

// in this test the shape gets smaller, forcing the back end of the file to move
void UpdateTests::update_geometry_polygon_xy ()
{
    try
    {
        create_schema (FdoGeometricType_Surface, false, false);
        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"7", FdoDataType_Decimal);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'Linux Loop'");
        value = FdoPropertyValue::Create (L"Street", expression);
        values->Add (value);
        expression = FdoDecimalValue::Create (99.9999);
        value = FdoPropertyValue::Create (L"Area", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"true");
        value = FdoPropertyValue::Create (L"Vacant", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"DATE'2005-03-22'");
        value = FdoPropertyValue::Create (L"Birthday", expression);
        values->Add (value);

        // add geometry value:
        FdoPtr<FdoGeometryValue> geometry = (FdoGeometryValue*)FdoExpression::Parse (L"GeomFromText('POLYGON XY ((5108.8 5104.7, 5109.02 5104.97, 5109.13 5105.94, 5113.45 5145.13, 5109.2 5138.67, 5108.8 5104.7))')");
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 id;
        id = -1;
        while (reader->ReadNext ())
        {
            if (-1 != id)
                CPPUNIT_FAIL ("too many features inserted");
            id = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();
        if (-1 == id)
            CPPUNIT_FAIL ("too few features inserted");

        // insert a second one
        FdoPtr<FdoGeometryValue> geometry2 = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('POLYGON XY ((2056.56 2345.87, 2067.54 2435.78, 1923.67 2390.87, 2056.56 2345.87))')");
        value->SetValue (geometry2);
        reader = insert->Execute ();
        FdoInt32 id2;
        id2 = -1;
        while (reader->ReadNext ())
        {
            if (-1 != id2)
                CPPUNIT_FAIL ("too many features inserted");
            id2 = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();

        // update the first one
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", id);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        FdoPtr<FdoGeometryValue> geometry3 = (FdoGeometryValue*)FdoExpression::Parse (L"GEOMFROMTEXT ('POLYGON XY ((5108.8 5104.7, 5109.02 5104.97, 5109.2 5138.67, 5108.8 5104.7))')");
        value = FdoPropertyValue::Create (L"Geometry", geometry3);
        value->SetName (L"Geometry");
        value->SetValue (geometry3);
        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 (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            if (id == reader->GetInt32 (L"FeatId"))
            {
                CPPUNIT_ASSERT_MESSAGE ("incorrect id value", 7 == reader->GetDouble (L"Id"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"Linux Loop", reader->GetString (L"Street")));
                CPPUNIT_ASSERT_MESSAGE ("incorrect area value", 99.9999 == reader->GetDouble (L"Area"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->GetBoolean (L"Vacant"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 2005 == reader->GetDateTime (L"Birthday").year);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 3 == reader->GetDateTime (L"Birthday").month);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 22 == reader->GetDateTime (L"Birthday").day);
                CPPUNIT_ASSERT_MESSAGE ("geometry is null", !reader->IsNull (L"Geometry"));
                FdoPtr<FdoByteArray> before = geometry3->GetGeometry ();
                FdoPtr<FdoByteArray> after = reader->GetGeometry (L"Geometry");
                int b = before->GetCount ();
                int a = after->GetCount ();
                CPPUNIT_ASSERT_MESSAGE ("incorrect geometry size", b == a);
                int count = before->GetCount ();
                for (int i = 0; i < count; i++)
                {
                    FdoByte left = before->GetData ()[i];
                    FdoByte right = after->GetData ()[i];
                    CPPUNIT_ASSERT_MESSAGE ("incorrect geometry content", left == right);
                }
            }
            else if (id2 == reader->GetInt32 (L"FeatId"))
            {
                CPPUNIT_ASSERT_MESSAGE ("incorrect id value", 7 == reader->GetDouble (L"Id"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect street value", 0 == wcscmp (L"Linux Loop", reader->GetString (L"Street")));
                CPPUNIT_ASSERT_MESSAGE ("incorrect area value", 99.9999 == reader->GetDouble (L"Area"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->GetBoolean (L"Vacant"));
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 2005 == reader->GetDateTime (L"Birthday").year);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 3 == reader->GetDateTime (L"Birthday").month);
                CPPUNIT_ASSERT_MESSAGE ("incorrect birthday value", 22 == reader->GetDateTime (L"Birthday").day);
                CPPUNIT_ASSERT_MESSAGE ("geometry is null", !reader->IsNull (L"Geometry"));
                FdoPtr<FdoByteArray> before = geometry2->GetGeometry ();
                FdoPtr<FdoByteArray> after = reader->GetGeometry (L"Geometry");
                int b = before->GetCount ();
                int a = after->GetCount ();
                CPPUNIT_ASSERT_MESSAGE ("incorrect geometry size", b == a);
                int count = before->GetCount ();
                for (int i = 0; i < count; i++)
                {
                    FdoByte left = before->GetData ()[i];
                    FdoByte right = after->GetData ()[i];
                    CPPUNIT_ASSERT_MESSAGE ("incorrect geometry content", left == right);
                }
            }
        }
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}


void UpdateTests::update_null_data_values ()
{
    try
    {
        create_schema (FdoGeometricType_Point, true, true);

        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"24", FdoDataType_Decimal);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"'1147 Trafford Drive'");
        value = FdoPropertyValue::Create (L"Street", expression);
        values->Add (value);
        // add NULL geometry value:
        FdoPtr<FdoGeometryValue> geometry = FdoGeometryValue::Create ();
        geometry->SetNullValue ();
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 featid;
        featid = -1;
        while (reader->ReadNext ())
        {
            if (-1 != featid)
                CPPUNIT_FAIL ("too many features inserted");
            featid = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();
        if (-1 == featid)
            CPPUNIT_FAIL ("too few features inserted");

        // update it
        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", featid);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        value = FdoPropertyValue::Create ();
        value->SetName (L"Street");
        //Leave NULL: value->SetValue ( ... );
        values->Add (value);
        value = FdoPropertyValue::Create ();
        value->SetName (L"Id");
        //Leave NULL: value->SetValue ( ... );
        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 (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect featid value", featid == reader->GetInt32 (L"FeatId"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect id value", reader->IsNull (L"Id"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect street value", reader->IsNull (L"Street"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect area value", reader->IsNull(L"Area"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->IsNull(L"Vacant"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect birthday year value", reader->IsNull (L"Birthday"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", reader->IsNull (L"Geometry"));
        }
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}



void UpdateTests::update_int32 ()
{
    try
    {
        create_schema (FdoGeometricType_Point, true, true);

        // Insert some values:
        /////////////////////////////////////////////////////////

        FdoPtr<FdoIInsert> insert = (FdoIInsert*)mConnection->CreateCommand (FdoCommandType_Insert);
        insert->SetFeatureClassName (L"TheSchema:Test");
        FdoPtr<FdoPropertyValueCollection> values = insert->GetPropertyValues ();
        FdoPtr<FdoValueExpression> expression = (FdoValueExpression*)ShpTests::ParseByDataType (L"24", FdoDataType_Decimal);
        FdoPtr<FdoPropertyValue> value = FdoPropertyValue::Create (L"Id", expression);
        values->Add (value);
        expression = (FdoValueExpression*)FdoExpression::Parse (L"-2147483647");
        value = FdoPropertyValue::Create (L"Age", expression);
        values->Add (value);
        // add NULL geometry value:
        FdoPtr<FdoGeometryValue> geometry = FdoGeometryValue::Create ();
        geometry->SetNullValue ();
        value = FdoPropertyValue::Create (L"Geometry", geometry);
        values->Add (value);
        FdoPtr<FdoIFeatureReader> reader = insert->Execute ();
        FdoInt32 featid;
        featid = -1;
        while (reader->ReadNext ())
        {
            if (-1 != featid)
                CPPUNIT_FAIL ("too many features inserted");
            featid = reader->GetInt32 (L"FeatId");
        }
        reader->Close ();
        if (-1 == featid)
            CPPUNIT_FAIL ("too few features inserted");

        // Read back the values
        FdoPtr<FdoISelect> select1 = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select1->SetFeatureClassName (L"TheSchema:Test");
        reader = select1->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect featid value", featid == reader->GetInt32 (L"FeatId"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect id value", !reader->IsNull (L"Id"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect age value", !reader->IsNull (L"Age"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect MIN INT value", reader->GetInt32 (L"Age") == -2147483647);
            CPPUNIT_ASSERT_MESSAGE ("incorrect area value", reader->IsNull(L"Area"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->IsNull(L"Vacant"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect birthday year value", reader->IsNull (L"Birthday"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", reader->IsNull (L"Geometry"));
        }
        reader->Close ();

        // Update some values:
        /////////////////////////////////////////////////////////

        FdoPtr<FdoIUpdate> update = (FdoIUpdate*)mConnection->CreateCommand (FdoCommandType_Update);
        update->SetFeatureClassName (L"TheSchema:Test");
        wchar_t filter[1024];
        FdoCommonOSUtil::swprintf (filter, ELEMENTS(filter), L"%ls = %d", L"FeatId", featid);
        update->SetFilter (FdoPtr<FdoFilter>(FdoFilter::Parse (filter)));
        values = update->GetPropertyValues ();
        value = FdoPropertyValue::Create ();
        value->SetName (L"Age");
        value->SetValue (L"2147483646");
        values->Add (value);
        value = FdoPropertyValue::Create ();
        value->SetName (L"Id");
        //Leave NULL: value->SetValue ( ... );
        values->Add (value);
        if (1 != update->Execute ())
            CPPUNIT_FAIL ("update execute failed");


        // Select back some values
        /////////////////////////////////////////////////////////

        FdoPtr<FdoISelect> select = (FdoISelect*)mConnection->CreateCommand (FdoCommandType_Select);
        select->SetFeatureClassName (L"TheSchema:Test");
        reader = select->Execute ();
        while (reader->ReadNext ())
        {
            CPPUNIT_ASSERT_MESSAGE ("incorrect featid value", featid == reader->GetInt32 (L"FeatId"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect id value", reader->IsNull (L"Id"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect age value", !reader->IsNull (L"Age"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect area value", reader->IsNull(L"Area"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect vacant value", reader->IsNull(L"Vacant"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect birthday year value", reader->IsNull (L"Birthday"));
            CPPUNIT_ASSERT_MESSAGE ("incorrect geometry value", reader->IsNull (L"Geometry"));
        }
        reader->Close ();


        // Select back some values with int32 filter
        /////////////////////////////////////////////////////////

        select->SetFilter(L"Age = 2147483646");
        reader = select->Execute ();
        CPPUNIT_ASSERT_MESSAGE("Int32 Filter failed", reader->ReadNext() );
        reader->Close ();

        select->SetFilter(L"Age = 55");
        reader = select->Execute ();
        CPPUNIT_ASSERT_MESSAGE("Int32 Filter failed", !reader->ReadNext() );
        reader->Close ();
    }
    catch (FdoException* ge) 
    {
        TestCommonFail (ge);
    }
}

