Example #1
0
int OGRGFTResultLayer::RunSQL()
{
    CPLString osChangedSQL(osSQL);
    int bHasSetLimit = FALSE;
    OGRGFTTableLayer* poTableLayer = NULL;
    OGRFeatureDefn* poTableDefn = NULL;
    CPLString osTableId;
    if (EQUALN(osSQL.c_str(), "SELECT", 6))
    {
        size_t nPosFROM = osSQL.ifind(" FROM ");
        if (nPosFROM == std::string::npos)
        {
            CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed. Missing FROM in SELECT");
            return FALSE;
        }
        CPLString osReminder;
        nPosFROM += 6;
        osTableId = OGRGFTExtractTableID(osSQL.c_str() + nPosFROM, osReminder);

        poTableLayer = (OGRGFTTableLayer*) poDS->GetLayerByName(osTableId);
        if (poTableLayer != NULL)
            poTableDefn = poTableLayer->GetLayerDefn();

        if (poTableLayer != NULL &&
            poTableLayer->GetTableId().size() &&
            !EQUAL(osTableId, poTableLayer->GetTableId()))
        {
            osChangedSQL = osSQL;
            osChangedSQL.resize(nPosFROM);
            osChangedSQL += poTableLayer->GetTableId();
            osChangedSQL += osReminder;
            osSQL = osChangedSQL;
            CPLDebug("GFT", "Patching table name (%s) to table id (%s)",
                     osTableId.c_str(), poTableLayer->GetTableId().c_str());
        }

        int nFeaturesToFetch = GetFeaturesToFetch();
        if (osSQL.ifind(" OFFSET ") == std::string::npos &&
            osSQL.ifind(" LIMIT ") == std::string::npos &&
            nFeaturesToFetch > 0)
        {
            osChangedSQL += CPLSPrintf(" LIMIT %d", nFeaturesToFetch);
            bHasSetLimit = TRUE;
        }
    }
    else
    {
        bGotAllRows = bEOF = TRUE;
        poFeatureDefn->SetGeomType( wkbNone );
    }

    CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);

    if (psResult == NULL)
        return FALSE;

    char* pszLine = (char*) psResult->pabyData;
    if (pszLine == NULL ||
        psResult->pszErrBuf != NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
        CPLHTTPDestroyResult(psResult);
        return FALSE;
    }

    if (EQUALN(osSQL.c_str(), "SELECT", 6) ||
        EQUAL(osSQL.c_str(), "SHOW TABLES") ||
        EQUALN(osSQL.c_str(), "DESCRIBE", 8))
    {
        ParseCSVResponse(pszLine, aosRows);
        if (aosRows.size() > 0)
        {
            char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
            for(int i=0;papszTokens && papszTokens[i];i++)
            {
                CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
                int iIndex = (poTableDefn) ? poTableDefn->GetFieldIndex(osLaunderedColName) : -1;
                if (iIndex >= 0)
                {
                    poFeatureDefn->AddFieldDefn(poTableDefn->GetFieldDefn(iIndex));
                    if (iIndex == poTableLayer->GetGeometryFieldIndex())
                        iGeometryField = i;
                    if (iIndex == poTableLayer->GetLatitudeFieldIndex())
                        iLatitudeField = i;
                    if (iIndex == poTableLayer->GetLongitudeFieldIndex())
                        iLongitudeField = i;
                }
                else
                {
                    OGRFieldType eType = OFTString;
                    if (EQUAL(osLaunderedColName, "COUNT()"))
                        eType = OFTInteger;
                    OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
                }
            }
            CSLDestroy(papszTokens);

            aosRows.erase(aosRows.begin());
        }

        if (iLatitudeField >= 0 && iLongitudeField >= 0)
        {
            iGeometryField = iLatitudeField;
            poFeatureDefn->SetGeomType( wkbPoint );
        }

        if (bHasSetLimit)
            bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
        else
            bGotAllRows = bEOF = TRUE;
    }

    SetGeomFieldName();

    CPLHTTPDestroyResult(psResult);

    return TRUE;
}
Example #2
0
int OGRGFTTableLayer::FetchDescribe()
{
    poFeatureDefn = new OGRFeatureDefn( osTableName );
    poFeatureDefn->Reference();
    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);

    const CPLString& osAuth = poDS->GetAccessToken();
    std::vector<CPLString> aosHeaderAndFirstDataLine;
    if (osAuth.size())
    {
        CPLString osSQL("DESCRIBE ");
        osSQL += osTableId;
        CPLHTTPResult * psResult = poDS->RunSQL(osSQL);

        if (psResult == NULL)
            return FALSE;

        char* pszLine = (char*) psResult->pabyData;
        if (pszLine == NULL ||
            psResult->pszErrBuf != NULL ||
            strncmp(pszLine, "column id,name,type",
                    strlen("column id,name,type")) != 0)
        {
            CPLHTTPDestroyResult(psResult);
            return FALSE;
        }

        pszLine = OGRGFTGotoNextLine(pszLine);

        std::vector<CPLString> aosLines;
        ParseCSVResponse(pszLine, aosLines);
        for(int i=0;i<(int)aosLines.size();i++)
        {
            char** papszTokens = OGRGFTCSVSplitLine(aosLines[i], ',');
            if (CSLCount(papszTokens) == 3)
            {
                aosColumnInternalName.push_back(papszTokens[0]);

                //CPLDebug("GFT", "%s %s %s", papszTokens[0], papszTokens[1], papszTokens[2]);
                OGRFieldType eType = OFTString;
                if (EQUAL(papszTokens[2], "number"))
                    eType = OFTReal;
                else if (EQUAL(papszTokens[2], "datetime"))
                    eType = OFTDateTime;

                if (EQUAL(papszTokens[2], "location") && osGeomColumnName.size() == 0)
                {
                    if (iGeometryField < 0)
                        iGeometryField = poFeatureDefn->GetFieldCount();
                    else
                        CPLDebug("GFT", "Multiple geometry fields detected. "
                                         "Only first encountered one is handled");
                }

                CPLString osLaunderedColName(LaunderColName(papszTokens[1]));
                OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
                poFeatureDefn->AddFieldDefn(&oFieldDefn);
            }
            CSLDestroy(papszTokens);
        }

        CPLHTTPDestroyResult(psResult);
    }
    else
    {
        /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_guide.html#Exploring states */
        /* that DESCRIBE should work on public tables without authentication, but it is not true... */
        CPLString osSQL("SELECT * FROM ");
        osSQL += osTableId;
        osSQL += " OFFSET 0 LIMIT 1";

        CPLHTTPResult * psResult = poDS->RunSQL(osSQL);

        if (psResult == NULL)
            return FALSE;

        char* pszLine = (char*) psResult->pabyData;
        if (pszLine == NULL || psResult->pszErrBuf != NULL)
        {
            CPLHTTPDestroyResult(psResult);
            return FALSE;
        }

        ParseCSVResponse(pszLine, aosHeaderAndFirstDataLine);
        if (aosHeaderAndFirstDataLine.size() > 0)
        {
            char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[0], ',');
            for(int i=0;papszTokens && papszTokens[i];i++)
            {
                CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
                OGRFieldDefn oFieldDefn(osLaunderedColName, OFTString);
                poFeatureDefn->AddFieldDefn(&oFieldDefn);
            }
            CSLDestroy(papszTokens);
        }

        CPLHTTPDestroyResult(psResult);
    }
    
    if (osGeomColumnName.size() > 0)
    {
        iGeometryField = poFeatureDefn->GetFieldIndex(osGeomColumnName);
        if (iGeometryField < 0)
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                     "Cannot find column called %s", osGeomColumnName.c_str());
        }
    }

    for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
    {
        const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
        if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
            EQUAL(pszName, "latdec"))
            iLatitudeField = i;
        else if (EQUAL(pszName, "longitude") || EQUAL(pszName, "lon") ||
                 EQUAL(pszName, "londec") || EQUAL(pszName, "long"))
            iLongitudeField = i;
    }

    if (iLatitudeField >= 0 && iLongitudeField >= 0)
    {
        if (iGeometryField < 0)
            iGeometryField = iLatitudeField;
        poFeatureDefn->GetFieldDefn(iLatitudeField)->SetType(OFTReal);
        poFeatureDefn->GetFieldDefn(iLongitudeField)->SetType(OFTReal);
        poFeatureDefn->SetGeomType( wkbPoint );
    }
    else if (iGeometryField < 0 && osGeomColumnName.size() == 0)
    {
        iLatitudeField = iLongitudeField = -1;

        /* In the unauthentified case, we try to parse the first record to */
        /* autodetect the geometry field */
        OGRwkbGeometryType eType = wkbUnknown;
        if (aosHeaderAndFirstDataLine.size() == 2)
        {
            char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[1], ',');
            if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
            {
                for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
                {
                    const char* pszVal = papszTokens[i];
                    if (pszVal != NULL &&
                        (strncmp(pszVal, "<Point>", 7) == 0 ||
                         strncmp(pszVal, "<LineString>", 12) == 0 ||
                         strncmp(pszVal, "<Polygon>", 9) == 0 ||
                         strncmp(pszVal, "<MultiGeometry>", 15) == 0))
                    {
                        if (iGeometryField < 0)
                        {
                            iGeometryField = i;
                        }
                        else
                        {
                            CPLDebug("GFT", "Multiple geometry fields detected. "
                                     "Only first encountered one is handled");
                        }
                    }
                    else if (pszVal)
                    {
                        /* http://www.google.com/fusiontables/DataSource?dsrcid=423292 */
                        char** papszTokens2 = CSLTokenizeString2(pszVal, " ,", 0);
                        if (CSLCount(papszTokens2) == 2 &&
                            CPLGetValueType(papszTokens2[0]) == CPL_VALUE_REAL &&
                            CPLGetValueType(papszTokens2[1]) == CPL_VALUE_REAL &&
                            fabs(CPLAtof(papszTokens2[0])) <= 90 &&
                            fabs(CPLAtof(papszTokens2[1])) <= 180 )
                        {
                            if (iGeometryField < 0)
                            {
                                iGeometryField = i;
                                eType = wkbPoint;
                            }
                            else
                            {
                                CPLDebug("GFT", "Multiple geometry fields detected. "
                                         "Only first encountered one is handled");
                            }
                        }
                        CSLDestroy(papszTokens2);
                    }
                }
            }
            CSLDestroy(papszTokens);
        }
        
        if (iGeometryField < 0)
            poFeatureDefn->SetGeomType( wkbNone );
        else
            poFeatureDefn->SetGeomType( eType );
    }

    SetGeomFieldName();

    return TRUE;
}