void CGwsPreparedFeatureQuery::PrepareInternal ()
{
    CGwsFdoCommand::PrepareNonKeyProperties ();
    if(m_selectList->GetCount() > 0)
    {
        //add in the select ilst, along with the identity properties, revision number
        WSTRARRAY strNames;
        bool     bFoundRevision = false;
        for (FdoInt32 idx = 0; m_identity != NULL && idx < m_identity->GetCount(); idx ++)
        {
            FdoPtr<FdoDataPropertyDefinition> pPropdef = m_identity->GetItem(idx);
            FdoString*                        pName = pPropdef->GetName();
            bool                              bFound = false;

            for (int i = 0; i < m_selectList->GetCount(); i++)
            {
                FdoPtr<FdoIdentifier> selProp = m_selectList->GetItem(i);
                FdoString * selectName = selProp->GetName();
                if(wcscmp(pName,selectName) == 0)
                    bFound = true;
                if(idx==0 && wcscmp(m_revisionprop.c_str (), selectName) == 0)
                    bFoundRevision = true;
            }
            if(!bFound)
                strNames.push_back(pName);
        }
        if(!bFoundRevision && !m_revisionprop.empty())
            strNames.push_back(m_revisionprop.c_str());

        FdoPtr<FdoIdentifierCollection> lst = ((FdoIBaseSelect*)m_pCommand.p)->GetPropertyNames();
        if (lst != NULL)
        {
            lst->Clear();
            if(!m_bIsSelectDistinct)
            {
                //add identity properties
                for (unsigned int i = 0; i < strNames.size(); i++)
                {
                    FdoPtr<FdoIdentifier> pIdent = FdoIdentifier::Create (strNames[i].c_str());
                    lst->Add(pIdent);
                }
            }
            for (int i = 0; i < m_selectList->GetCount(); i++)
            {
                FdoPtr<FdoIdentifier> pIdent = m_selectList->GetItem(i);
                lst->Add(pIdent);
            }
        }
    }
}
void CGwsQueryResultDescriptors::appendPropertyNames (
    FdoIdentifierCollection       * propnamestoadd,
    FdoClassDefinition        * classDef,
    FdoStringCollection       * propnames,
    std::vector<CGwsPropertyDesc> & propdsc
)
{
    FdoPtr<FdoPropertyDefinitionCollection> properties;

    FdoPtr<FdoClassDefinition> baseClass = classDef->GetBaseClass ();
    if (baseClass != NULL) {
        appendPropertyNames (propnamestoadd, baseClass, propnames, propdsc);

    }

    properties = classDef->GetProperties ();
    if (properties == NULL)
        return;
    for (int i = 0; i < properties->GetCount (); i ++) {
        FdoPtr<FdoPropertyDefinition>   pFdoProperty = properties->GetItem (i);
        if (propnamestoadd == NULL ||
            propnamestoadd->IndexOf (pFdoProperty->GetName ()) >= 0)
            pushPropDefinition (pFdoProperty, propnames,propdsc);
    }
}
void GwsBinaryFeatureWriter::WriteAssociationProperty(FdoAssociationPropertyDefinition* apd,
                                                      FdoIFeatureReader* reader)
{
    if( apd->GetIsReadOnly() )
        return;

    FdoPtr<FdoDataPropertyDefinitionCollection> idents = apd->GetIdentityProperties();
    if( idents->GetCount() == 0 )
    {
        // Search for property values with names build from the association property name and the
        // associated class identity properties. For example if the associated class identifier is "Id" and the
        // association property name is "AssocProp", then we should search for a property value with
        // name: "AssocProp.Id". If that property value is found and set, then that means an association
        // exists between the new object(we are about to insert) and the object identified by the value
        // of the property value(AssocProp.Id)
        FdoPtr<FdoClassDefinition> cls = apd->GetAssociatedClass();
        idents = cls->GetIdentityProperties();
    }
    if( reader->IsNull( apd->GetName() ) )
        return;

    FdoPtr<FdoIFeatureReader> loc_reader = reader->GetFeatureObject( apd->GetName() );
    if( ! loc_reader->ReadNext() )
        return;
    for(int i=0; i<idents->GetCount(); i++ )
    {
        FdoPtr<FdoDataPropertyDefinition> prop = idents->GetItem( i );
        if( ! loc_reader->IsNull( prop->GetName() ) )
            WriteProperty( prop, loc_reader);
    }
}
void FdoImportExportTest::Test8 ()
{
    try {
        FdoIoStreamP configStream = FdoIoMemoryStream::Create();

        CreateConfigBadWkt( configStream );

        // Test 8 tries adding a spatial context whose WKT differs
        // from what Oracle defines for its coordinate system.
        // This test should fail for Oracle and pass for the others.
        printf( "Test8 (junk WKT) ... \n" );

        printf( "\tOpening Source Connection ... \n" );
        FdoPtr<FdoIConnection> connection = UnitTestUtil::CreateConnection(
		    true,
		    true,
            DB_NAME_SRC_SUFFIX,
            NULL,
            NULL,
            0
	    );

        FdoPtr<FdoIConnectionCapabilities> cap = connection->GetConnectionCapabilities();

        // Import from the input XML document
        printf( "\tImporting ...\n" );

        Import(
            connection, 
            configStream,
            NULL,
            true,
            false
        );

        FdoPtr<FdoIGetSpatialContexts> cmd = (FdoIGetSpatialContexts*) connection->CreateCommand( FdoCommandType_GetSpatialContexts );
        cmd->SetActiveOnly(false);

        FdoPtr<FdoISpatialContextReader> reader = cmd->Execute();

        while ( reader->ReadNext() ) {
            // Skip default spatial context if not writing it.
            if ( wcscmp(reader->GetName(), L"Manhole1") == 0 ) {
                if ( cap->SupportsCSysWKTFromCSysName() )
                    CPPUNIT_ASSERT( wcscmp(reader->GetCoordinateSystemWkt(), L"LOCAL_CS [ \"Non-Earth (Meter)\", LOCAL_DATUM [\"Local Datum\", 0], UNIT [\"Meter\", 1.0], AXIS [\"X\", EAST], AXIS[\"Y\", NORTH]]") == 0 );
                else
                    CPPUNIT_ASSERT( wcscmp(reader->GetCoordinateSystemWkt(), L"nonsense wkt") == 0 );
            }
        }
    }
	catch ( FdoException* e ) 
	{
		UnitTestUtil::FailOnException( e );
    }

	printf( "Done\n" );
}
Beispiel #5
0
bool GwsCommonFdoUtils::GetGeometryName (FdoClassDefinition *pClassDef, std::wstring &name)
{
    if(pClassDef == NULL)
        return false;

    if(pClassDef->GetClassType() == FdoClassType_FeatureClass)
    {
        FdoFeatureClass* pFeatClass = dynamic_cast<FdoFeatureClass*>(pClassDef);
        if(!pFeatClass)
        {
            assert(false);
            return false;
        }

        FdoPtr<FdoGeometricPropertyDefinition> pgDef = pFeatClass->GetGeometryProperty();
        if (pgDef != NULL) {
            name = pgDef->GetName();
            return true;
        }
    }
    FdoInt32 idx;

    FdoPtr<FdoClassDefinition>  classDef = pClassDef;
    FDO_SAFE_ADDREF(pClassDef);
    for (; classDef != NULL ; classDef = classDef->GetBaseClass ())
    {
        FdoPtr<FdoPropertyDefinitionCollection> propdsc = classDef->GetProperties ();
        // discover geometric property name. Use the first one if there are many.
        for (idx = 0; idx < propdsc->GetCount(); idx ++) {
            FdoPtr<FdoPropertyDefinition>   prop;
            prop = propdsc->GetItem(idx);
            if (prop->GetPropertyType () == FdoPropertyType_GeometricProperty)
            {
                name = prop->GetName ();
                return true;
            }
        }
    }
    return false;
}
Beispiel #6
0
WSTR GwsCommonFdoUtils::GetRevisionProperty (FdoClassDefinition * classdef)
{
    WSTR revision;

    // discover revision property. Revision property is defined
    // for a given class
    FdoPtr<FdoReadOnlyPropertyDefinitionCollection> pBaseProperties = classdef->GetBaseProperties();

    // See if property with this name already exists:
    for (int idx=0; pBaseProperties != NULL && idx < pBaseProperties->GetCount(); idx++)
    {
        FdoPtr<FdoPropertyDefinition> pBaseProperty;
        pBaseProperty = (FdoPropertyDefinition*)pBaseProperties->GetItem(idx);
        if (! _wcsicmp (pBaseProperty->GetName(), REVISIONNUMBER_PROPNAME))
        {
            revision = pBaseProperty->GetName();
            break;
        }
    }

    return revision;
}
Beispiel #7
0
EGwsStatus GwsCommonFdoUtils::DescribeSC (
    FdoIConnection               * conn,
    FdoString                    * scname,
    GwsSpatialContextDescription & scdesc
)
{

    FdoPtr<FdoIGetSpatialContexts>   cmd;
    FdoPtr<FdoISpatialContextReader> reader;
    scdesc.SetClassName (GWSQualifiedName ());
    scdesc.SetPropertyName (NULL);
    scdesc.SetSpatialContextName (NULL);
    scdesc.SetSpatialContextDesc (NULL);
    scdesc.SetCsNameWkt (NULL);

    if (scname == NULL || * scname == 0)
        return eGwsOk;

    try {
        cmd = (FdoIGetSpatialContexts *) conn->CreateCommand (FdoCommandType_GetSpatialContexts);
        reader = cmd->Execute ();
        while (reader->ReadNext ()) {
            if (wcscmp (reader->GetName (), scname) == 0) {
                FdoString * cswkt = reader->GetCoordinateSystemWkt ();
                FdoString * desc  = reader->GetDescription ();
                double xytol = reader->GetXYTolerance();
                scdesc.SetCsNameWkt (cswkt);
                scdesc.SetSpatialContextDesc (desc);
                scdesc.SetSpatialContextName (scname);
                scdesc.SetXYTolerance(xytol);

                FdoPtr<FdoByteArray> pByteArray = reader->GetExtent();
                if (pByteArray) {
                    FdoPtr<FdoFgfGeometryFactory> pAwkbFactory = FdoFgfGeometryFactory::GetInstance();
                    FdoPtr<FdoIGeometry> pGeometry = pAwkbFactory->CreateGeometryFromFgf(pByteArray);
                    FdoPtr<FdoIEnvelope> pEnvelope = pGeometry->GetEnvelope();
                    scdesc.SetExtents (pEnvelope);
                }

                return eGwsOk;
            }
        }
        return eGwsSCNotFound;

    } catch (FdoException * fdoEx) {
        fdoEx->Release ();
    }
    // in case when exception thrown, assume that sc are not
    // supported.
    return eGwsNotSupported;
}
bool GwsBinaryFeatureWriter::WriteAssociationProperty(FdoAssociationPropertyDefinition* apd,
                                                      FdoPropertyValueCollection* pvc)
{
    bool  errorIfSet = apd->GetIsReadOnly();
    bool  oneIdentIsNull = false;
    bool  written = false;

    FdoPtr<FdoDataPropertyDefinitionCollection> idents = apd->GetIdentityProperties();
    if( idents->GetCount() == 0 )
    {
        // Search for property values with names build from the association property name and the
        // associated class identity properties. For example if the associated class identifier is "Id" and the
        // association property name is "AssocProp", then we should search for a property value with
        // name: "AssocProp.Id". If that property value is found and set, then that means an association
        // exists between the new object(we are about to insert) and the object identified by the value
        // of the property value(AssocProp.Id)
        FdoPtr<FdoClassDefinition> cls = apd->GetAssociatedClass();
        idents = cls->GetIdentityProperties();
    }

    for(int i=0; i<idents->GetCount(); i++ )
    {
        FdoPtr<FdoDataPropertyDefinition> prop = idents->GetItem( i );
        std::wstring wstr = apd->GetName();
        wstr += L".";
        wstr += prop->GetName();
        FdoPtr<FdoPropertyValue> pv = pvc->FindItem( wstr.c_str() );
        if(pv != NULL)
        {
            if( errorIfSet )
                GWS_THROW(eGwsFailed); //cannot add readonly association property value

            if( oneIdentIsNull )
                GWS_THROW(eGwsFailed); //one of the identity properties is null

            WriteProperty(prop, pv, true);
            written = true;
            oneIdentIsNull = false;
        }
        else
        {
            if( written ) // we already written one or more identity and this one is null
                GWS_THROW(eGwsFailed);
            oneIdentIsNull = true;
        }
    }

    return written;
}
Beispiel #9
0
void CGwsFlatGwsIterator::DescribeFeature(IGWSExtendedFeatureDescription ** ppResDesc)
{
    if (ppResDesc == NULL)
        GWS_THROW (eGwsNullPointer);
    if (m_fdsc == NULL) {

        FdoPtr<FdoClassDefinition> classDef = GetClassDefinition ();

        CGwsQueryResultDescriptors * resdsc =
                new CGwsQueryResultDescriptors (classDef, classDef->GetName (), NULL, NULL, true, NULL);
        resdsc->AddRef ();
        m_fdsc = resdsc;
    }
    * ppResDesc = m_fdsc;
    if (* ppResDesc)
        (* ppResDesc)->AddRef ();
}
void MgServerGetFeatureProviders::CreateFeatureProvidersDocument()
{
    CHECKNULL(m_fdoProviderCol, L"MgServerGetFeatureProviders.CreateFeatureProvidersDocument");

    INT32 cnt = m_fdoProviderCol->GetCount();
    for (INT32 i = 0; i < cnt; i++)
    {
        FdoPtr<FdoProvider> fdoProvider = m_fdoProviderCol->GetItem(i);

        // Get ProviderName
        FdoString* providerName = fdoProvider->GetName();

        const char *name        = MgUtil::WideCharToMultiByte(providerName);
        const char *dispname    = MgUtil::WideCharToMultiByte(fdoProvider->GetDisplayName());
        const char *description = MgUtil::WideCharToMultiByte(fdoProvider->GetDescription());
        const char *version     = MgUtil::WideCharToMultiByte(fdoProvider->GetVersion());
        const char *fdoversion  = MgUtil::WideCharToMultiByte(fdoProvider->GetFeatureDataObjectsVersion());

        // Add Feature Provider element
        DOMElement* rootElem = m_xmlUtil->GetRootNode();
        DOMElement* featureProviderElem = m_xmlUtil->AddChildNode(rootElem, "FeatureProvider" /* NOXLATE */);

        // Add Provider Name
        m_xmlUtil->AddTextNode(featureProviderElem, "Name" /* NOXLATE */, name);
        // Display Name
        m_xmlUtil->AddTextNode(featureProviderElem, "DisplayName" /* NOXLATE */, dispname);
        // Description
        m_xmlUtil->AddTextNode(featureProviderElem, "Description" /* NOXLATE */, description);
        // Version
        m_xmlUtil->AddTextNode(featureProviderElem, "Version" /* NOXLATE */, version);
        // FDO version
        m_xmlUtil->AddTextNode(featureProviderElem, "FeatureDataObjectsVersion" /* NOXLATE */, fdoversion);

        delete[] name;
        delete[] dispname;
        delete[] description;
        delete[] version;
        delete[] fdoversion;

        AddConnectionProperties(featureProviderElem, providerName);
    }
}
void SpatialContextTest::testXmlNesting()
{
    try {
        // Create an XML document with Spatial Contexts nested 2 levels down from
        // root element.

        FdoIoMemoryStreamP stream = FdoIoMemoryStream::Create();
        FdoXmlWriterP writer = FdoXmlWriter::Create( stream );

        // Create 2 Level1 elements under the root element.

        writer->WriteStartElement( L"Level1" );
        writer->WriteStartElement( L"Level2" );
        writer->WriteEndElement();
        writer->WriteStartElement( L"Level2" );
        writer->WriteEndElement();
        writer->WriteEndElement();

        // The Spatial Contexts are under the second Level1 element.

        writer->WriteStartElement( L"Level1" );

        // Mix them up with some other elements that should be skipped.
        writer->WriteStartElement( L"Level2" );
        writer->WriteEndElement();

        FdoXmlSpatialContextWriterP SCWriter =
            FdoXmlSpatialContextWriter::Create( writer );
        SCWriter->SetName( L"Embedded1" );
        FdoByteArray* extent = SerializeExtent( 0, 0, 15000, 10000 );
        SCWriter->SetExtent( extent );
        extent->Release();
        SCWriter->WriteSpatialContext();
        SCWriter = NULL;

        writer->WriteStartElement( L"Level2" );
        writer->WriteEndElement();

        SCWriter =
            FdoXmlSpatialContextWriter::Create( writer );
        SCWriter->SetName( L"Embedded2" );
        extent = SerializeExtent( 0, 0, 15000, 10000 );
        SCWriter->SetExtent( extent );
        extent->Release();
        SCWriter->WriteSpatialContext();
        SCWriter = NULL;

        writer->WriteStartElement( L"Level2" );
        writer->WriteEndElement();
        writer = NULL;

        stream->Reset();

        FdoIoFileStreamP fileStream = FdoIoFileStream::Create( L"sc_nested.xml", L"w+");
        XmlFormatter formatter1(stream, fileStream);
        formatter1.Format();
        stream->Reset();

        FdoPtr<NestedReader> reader = NestedReader::Create(stream);

        // Read the spatial contexts. Should get both of them
        reader->ReadNext();
        FDO_CPPUNIT_ASSERT( wcscmp(reader->GetName(), L"Embedded1") == 0 );

        reader->ReadNext();
        FDO_CPPUNIT_ASSERT( wcscmp(reader->GetName(), L"Embedded2") == 0 );

        // Shouldn't be any more spatial contexts at this point.
        FDO_CPPUNIT_ASSERT( reader->ReadNext() == false );
    }
    catch ( FdoException* e ) {
		UnitTestUtil::FailOnException( e );
    }
}
Beispiel #12
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;
}
FdoXmlLpSchemaCollection* FdoXmlSchemaManager::_schemas() {
    if (m_lpSchemas == NULL) {
        m_lpSchemas = FdoXmlLpSchemaCollection::Create(this);
        FdoInt32 count = m_fdoSchemas->GetCount();
        FdoPtr<FdoPhysicalSchemaMappingCollection> mappings = m_flags->GetSchemaMappings();
        if ( mappings == NULL ) 
            mappings = m_fdoSchemas->GetXmlSchemaMappings();

        FdoInt32 count1 = mappings->GetCount();
        FdoPtr<FdoXmlSchemaMapping> tempXmlMapping = FdoXmlSchemaMapping::Create(L"temp");
        for (int i = 0; i < count; i++) {
            FdoPtr<FdoFeatureSchema> schema = m_fdoSchemas->GetItem(i);
            FdoPtr<FdoXmlSchemaMapping> mapping = static_cast<FdoXmlSchemaMapping*>(mappings->GetItem(tempXmlMapping->GetProvider(), schema->GetName()));
            FdoPtr<FdoXmlLpSchema> lpSchema = FdoXmlLpSchema::Create(schema, mapping);
            m_lpSchemas->Add(lpSchema);
        }
    }
    return m_lpSchemas.p;

}
Beispiel #14
0
//serializes a collection of property values into a byte array
//This function differs from WriteFeature() in that
//it will merge property values specified in the given PropertyValueCollection
//with property values in the given FeatureReader. The PropertyValueCollection
//represents properties to be updated in an old feature record represented by
//the given FeatureReader.
void GwsBinaryFeatureWriter::WriteFeature(FdoClassDefinition* fc,  FdoString* fcName,
                                          FdoPropertyValueCollection* pvc,
                                          FdoIFeatureReader* reader)
{
    FdoPtr<FdoReadOnlyPropertyDefinitionCollection> bpdc = fc->GetBaseProperties();
    FdoPtr<FdoPropertyDefinitionCollection> pdc = fc->GetProperties();

    //find number of properties we will store into the data record
    //we will use this number to save an offset into the data records for each property
    //at the beginning of the data record
    int numProps = bpdc->GetCount() + pdc->GetCount();// - idpdc->GetCount();

    //now generate the data value -- write all property values, except for the ones
    //we already wrote to the key -- we have to check if each one is in the ID prop
    //collection

    //write feature class ID
    m_wrtr.WriteString(fcName);
    int fcNameLen = m_wrtr.GetPosition();

    //reserve space for offsets into property values in data record
    for (int i=0; i<numProps; i++)
        m_wrtr.WriteInt32(0);

    int index = 0;

    //base properties first
    for (int i=0; i<bpdc->GetCount(); i++)
    {
        FdoPtr<FdoPropertyDefinition> pd = (FdoPropertyDefinition*)bpdc->GetItem(i);

        //save offset of property data to the reserved position at the
        //beginning of the record
        //TODO: endian
        ((int*)(m_wrtr.GetData() + fcNameLen))[index++] = m_wrtr.GetPosition();

        //if property is autogenerated, do not write
        //anything. We use the record number as autogen property value
        //so we can obtain it at read time
        //if (!pi->IsPropAutoGen(pd->GetName()))
        //{
        if (pvc)
        {
            if( pd->GetPropertyType() == FdoPropertyType_AssociationProperty )
            {
                if( ! WriteAssociationProperty((FdoAssociationPropertyDefinition*)pd.p, pvc) )
                    WriteAssociationProperty((FdoAssociationPropertyDefinition*)pd.p, reader);
            }
            else
            {
                FdoPtr<FdoPropertyValue> pv((FdoPropertyValue*)pvc->FindItem(pd->GetName()));
                if(pv != NULL)
                    WriteProperty(pd, pv);
                else
                    WriteProperty(pd, reader);
            }
        }
        else
        {
            WriteProperty(pd, reader);
        }
        //}
    }

    //class properties
    for (int i=0; i<pdc->GetCount(); i++)
    {
        FdoPtr<FdoPropertyDefinition> pd = (FdoPropertyDefinition*)pdc->GetItem(i);

        //save offset of property data to the reserved position at the
        //beginning of the record
        //TODO: endian
        ((int*)(m_wrtr.GetData() + fcNameLen))[index++] = m_wrtr.GetPosition();


        //if property is autogenerated, do not write
        //anything. We use the record number as autogen property value
        //so we can obtain it at read time
        //if (!pi->IsPropAutoGen(pd->GetName()))
        //{
        if (pvc)
        {
            if( pd->GetPropertyType() == FdoPropertyType_AssociationProperty )
            {
                if( ! WriteAssociationProperty((FdoAssociationPropertyDefinition*)pd.p, pvc) )
                    WriteAssociationProperty((FdoAssociationPropertyDefinition*)pd.p, reader);
            }
            else
            {

                FdoPtr<FdoPropertyValue> pv((FdoPropertyValue*)pvc->GetItem(pd->GetName()));
                if(pv != NULL)
                    WriteProperty(pd, pv);
                else
                    WriteProperty(pd, reader);
            }
        }
        else
        {
            WriteProperty(pd, reader);
        }
        //}
    }
}
FdoIFeatureReader *FdoRdbmsSelectCommand::Execute( bool distinct, FdoInt16 callerId  )
{
    if (!mConnection || !mFdoConnection || mFdoConnection->GetConnectionState() != FdoConnectionState_Open)
        throw FdoCommandException::Create(NlsMsgGet(FDORDBMS_13, "Connection not established"));
    // Flush out any outstanding modifications before selecting; so that the select
    // sees a current picture of the RDBMS.
    mIConnection->Flush();
    int                 qid = -1;
    bool                res = false;
    bool delStatement = true;
    GdbiStatement* statement = NULL;

    const FdoSmLpClassDefinition *classDefinition = mConnection->GetSchemaUtil()->GetClass(this->GetClassNameRef()->GetText());

    bool isFeatureClass = ( classDefinition != NULL &&  classDefinition->GetClassType() == FdoClassType_FeatureClass );
    bool isForUpdate = HasLobProperty( classDefinition );

    bool doNotUseSimpleSelect = mHasObjectProps && (mIdentifiers == NULL || mIdentifiers->GetCount() == 0);

    try
    {
        // for now we support only select with joins
        if (callerId == (FdoInt16)FdoCommandType_Select && !doNotUseSimpleSelect && !mHasObjectProps)
        {
            FdoPtr<FdoRdbmsSqlBuilder> sqlBuilder = mFdoConnection->GetSqlBuilder();
            if (sqlBuilder)
            {
                std::vector<NameOrderingPair> ordering;
                FdoPtr<FdoParameterValueCollection> params = GetParameterValues();
                FdoPtr<FdoJoinCriteriaCollection> jcColl = GetJoinCriteria();
                sqlBuilder->SetParameterValues(params);
                if (mOrderingIdentifiers && mOrderingIdentifiers->GetCount())
                {
                    for (int i=0; i<mOrderingIdentifiers->GetCount(); i++)
                    {
                        FdoPtr<FdoIdentifier> id = mOrderingIdentifiers->GetItem(i);
                        ordering.push_back(NameOrderingPair(id.p, ((int)mOrderingOptions.size() != mOrderingIdentifiers->GetCount()) ? mOrderingOption : mOrderingOptions[id->GetName()])); 
                    }
                }

                FdoString* sqlString = sqlBuilder->ToSelectSqlString(GetClassNameRef(), mAliasName, GetFilterRef(), mIdentifiers, ordering, jcColl);
                if (sqlString != NULL && *sqlString != '\0')
                {
                    statement = mConnection->GetGdbiConnection()->Prepare( sqlString );

                    std::vector< std::pair< FdoLiteralValue*, FdoInt64 > >* paramsUsed = sqlBuilder->GetUsedParameterValues();

                    if (paramsUsed != NULL && paramsUsed->size())
                    {
                        if (mBindParamsHelper == NULL)
                            mBindParamsHelper = new FdoRdbmsPropBindHelper(mConn);

                        mBindParamsHelper->BindParameters(statement, paramsUsed);
                    }

                    GdbiQueryResult *queryRslt = statement->ExecuteQuery();

                    delete statement;

                    if (mBindParamsHelper != NULL)
                        mBindParamsHelper->Clear();

                    // statement will be deleted in the reader.
                    delStatement = false;

                    return FdoRdbmsSimpleFeatureReader::Create(mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers);
                }
            }
        }

        FdoPtr<FdoRdbmsFilterProcessor>flterProcessor = mFdoConnection->GetFilterProcessor();
        FdoPtr<FdoParameterValueCollection> params = GetParameterValues();
        flterProcessor->SetParameterValues(params);

        FdoRdbmsFilterUtilConstrainDef filterConstrain;
        filterConstrain.distinct = distinct;
        filterConstrain.orderingOption = mOrderingOption;
        filterConstrain.selectedProperties = mIdentifiers;
        filterConstrain.groupByProperties = mGroupingCol;
        filterConstrain.orderByProperties = mOrderingIdentifiers;

   		// Verify if this is a special case we can optimize (no filter, no grouping filter,
		// and only aggregate functions Count() and/or SpatialExtents())
        FdoRdbmsFeatureReader *reader = GetOptimizedFeatureReader( classDefinition );
        if ( reader )
            return reader;

        // FDO supports expression functions that may not have native support in the
        // underlying system. If this is the case then the request has to be handled
        // by the Expression Engine.

        bool isValidFilter = true,
             isValidSelectList = true;

        if ( this->GetFilterRef() != NULL )
            isValidFilter = flterProcessor->IsValidExpression( this->GetFilterRef() );
        isValidSelectList = flterProcessor->IsValidExpression( mIdentifiers );

        if ( ( !isValidFilter ) || ( !isValidSelectList ) )
        {
            // Either the selected property list of the the filter is invalid. In any case
            // create a SQL statement that selects all properties for the current class.
            // If the filter is valid it is used to narrow the selected amount of data.

            FdoString *sqlStatement =
                    flterProcessor->FilterToSql( ((isValidFilter)
                                                        ? this->GetFilterRef()
                                                        : NULL),
                                                 this->GetClassNameRef()->GetText() );

            GdbiQueryResult *queryRslt = mConnection->GetGdbiConnection()->ExecuteQuery( sqlStatement );
            FdoPtr<FdoIFeatureReader> featureReader = new FdoRdbmsFeatureReader( mFdoConnection,
                                                                                 queryRslt,
                                                                                 isFeatureClass,
                                                                                 classDefinition,
                                                                                 NULL,
                                                                                 NULL,
                                                                                 0,
                                                                                 NULL );

            // The Expression Engine cannot work with the class definition of type
            // "FdoSmLpClassDefinition". Instead it is necessary to get the corresponding
            // definition of type "FdoClassDefinition". This is done next.

            const FdoSmLpSchema* schema = mConnection->GetSchema( this->GetClassNameRef()->GetText() );
            FdoFeatureSchemasP fdoFeatureSchemas = mFdoConnection->GetSchemaManager()->GetFdoSchemas( schema->GetName() );
            FdoClassesP classCol = (FdoClassCollection *)fdoFeatureSchemas->FindClass( this->GetClassNameRef()->GetText() );
            FdoClassDefinitionP classDef = classCol->GetItem(0);

			// Create the collection of custom functions.
			FdoSmLpSchemasP	schemas = ((FdoSmLpSchema *) schema)->GetSchemas();

			FdoExpressionEngineFunctionCollection *userDefinedFunctions = GetUserDefinedFunctions( schemas->GetSpatialContextMgr()->GetSpatialContexts(), classDef );

			return FdoExpressionEngineUtilFeatureReader::Create(
                                                        classDef,
                                                        featureReader, 
                                                        this->GetFilterRef(),
                                                        mIdentifiers,
                                                        userDefinedFunctions);
		}

        // The selected properties and the filter are both valid. Do the normal processing.

		// Validate the filter
		if ( this->GetFilterRef() != NULL )
		{
			FdoPtr<FdoIFilterCapabilities> filterCaps = mFdoConnection->GetFilterCapabilities();
	
			FdoExpressionEngine::ValidateFilter( NULL, this->GetFilterRef(), NULL, filterCaps);
		}

        // Call FilterToSql just to populate the filter's list of geometric conditions;
        FdoString * sqlString = flterProcessor->FilterToSql( this->GetFilterRef(),
                                                             this->GetClassNameRef()->GetText(),
                                                             SqlCommandType_Select,
                                                             FdoCommandType_Select,
                                                             &filterConstrain,
                                                             isForUpdate,
                                                             callerId );

        FdoPtr<FdoRdbmsFilterProcessor::BoundGeometryCollection> boundGeometries = flterProcessor->GetBoundGeometryValues();
        FdoPtr<FdoRdbmsSecondarySpatialFilterCollection> geometricConditions = flterProcessor->GetGeometricConditions();
   		vector<int> * logicalOps = flterProcessor->GetFilterLogicalOps();

        FdoPtr<FdoIdentifierCollection> idsWithGeoms = FdoIdentifierCollection::Create();

        if (( mIdentifiers && mIdentifiers->GetCount() > 0) )
        {
            // Make sure that the properties are listed for any geometric conditions that require secondary filtering.
            if (geometricConditions != NULL)
            {
                for (FdoInt32 i=0;  i < geometricConditions->GetCount();  i++)
                {
                    FdoPtr<FdoRdbmsSpatialSecondaryFilter> ssf = geometricConditions->GetItem(i);
                    FdoString * ssfPropertyName = ssf->GetPropertyName();
                    FdoPtr<FdoIdentifier> ssfId = mIdentifiers->FindItem(ssfPropertyName);
                    if (ssfId == NULL)
                    {
                        // Property wasn't selected by the caller.
                        ssfId = FdoIdentifier::Create(ssfPropertyName);
                        idsWithGeoms->Add(ssfId);
                    }
                }
                // Convert to SQL again if we added geometric properties.
                if (idsWithGeoms->GetCount() > 0)
                {
                    // Make our own copy of the original list, to avoid a side effect of changing
                    // mIdentifiers, which the user can effectively see.  Perserve original order,
                    // effectively creating a new list that appends the geometry names.
                    for (FdoInt32 i = mIdentifiers->GetCount()-1;  i >= 0;  i--)
                    {
                        FdoPtr<FdoIdentifier> id = mIdentifiers->GetItem(i);
                        idsWithGeoms->Insert(0, id);
                    }
                    filterConstrain.selectedProperties = idsWithGeoms;
                    sqlString = flterProcessor->FilterToSql( this->GetFilterRef(),
                                                             this->GetClassNameRef()->GetText(),
                                                             SqlCommandType_Select,
                                                             FdoCommandType_Select,
                                                             &filterConstrain,
                                                             isForUpdate,
                                                             callerId );
                }
            }
            if (callerId == FdoCommandType_SelectAggregates)
            {
                FdoSchemaManagerP pschemaManager = mConnection->GetSchemaUtil()->GetSchemaManager();
                FdoPtr<FdoFeatureSchemaCollection> schemas = pschemaManager->GetFdoSchemas(L"");
                FdoPtr<FdoCommonExpressionExecutor> expVer = FdoCommonExpressionExecutor::Create(schemas, GetClassNameRef());
                FdoPtr<FdoIExpressionCapabilities> expCap = mFdoConnection->GetExpressionCapabilities();
                expVer->ValidateIdentifiers(mIdentifiers, expCap);
            }
        }

        statement = mConnection->GetGdbiConnection()->Prepare( sqlString );

        std::vector< std::pair< FdoLiteralValue*, FdoInt64 > >* paramsUsed = flterProcessor->GetUsedParameterValues();

        if (paramsUsed != NULL && paramsUsed->size())
        {
            if (mBindParamsHelper == NULL)
                mBindParamsHelper = new FdoRdbmsPropBindHelper(mConn);

            mBindParamsHelper->BindParameters(statement, paramsUsed);
        }

        GdbiQueryResult *queryRslt = statement->ExecuteQuery();

        delete statement;

        if (mBindParamsHelper != NULL)
            mBindParamsHelper->Clear();

        // statement will be deleted in the reader.
        delStatement = false;

        // For now only SQL Spatial Server supports SupportsSimpleReader, later (after we add some unit tests) we can extend it to other providers
        if (!flterProcessor->ContainsCustomObjects() && flterProcessor->SupportsSimpleReader() && geometricConditions == NULL && callerId == (FdoInt16)FdoCommandType_Select && !doNotUseSimpleSelect)
        {
            return FdoRdbmsSimpleFeatureReader::Create(mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers);
        }
        else
        {
            if (( mIdentifiers && mIdentifiers->GetCount() > 0))
                return new FdoRdbmsFeatureSubsetReader (mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, mIdentifiers, geometricConditions, logicalOps );
            else
                return new FdoRdbmsFeatureReader (mFdoConnection, queryRslt, isFeatureClass, classDefinition, NULL, NULL, 0, geometricConditions, logicalOps ); // The feature reader should free the queryRslt
        }
    }

    catch (FdoCommandException *ex)
    {
        if (delStatement)
            delete statement;
        ex;
        SELECT_CLEANUP;
        throw;
    }
    catch (FdoException *ex)
    {
        if (delStatement)
            delete statement;
        SELECT_CLEANUP;
        // Wrap in FdoPtr to remove original reference to original exception
        throw FdoCommandException::Create(ex->GetExceptionMessage(), FdoPtr<FdoException>(ex), ex->GetNativeErrorCode());
    }

    catch ( ... )
    {
        if (delStatement)
            delete statement;
        SELECT_CLEANUP;
        throw;
    }
}