Exemple #1
0
OGRFeature *OGRGFTLayer::BuildFeatureFromSQL(const char* pszLine)
{
    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);

    char** papszTokens = OGRGFTCSVSplitLine(pszLine, ',');
    int nTokens = CSLCount(papszTokens);
    CPLString osFID;

    int nAttrOffset = 0;
    int iROWID = -1;
    if (bFirstTokenIsFID)
    {
        osFID = papszTokens[0];
        nAttrOffset = 1;
    }
    else
    {
        iROWID = poFeatureDefn->GetFieldIndex("rowid");
        if (iROWID < 0)
            iROWID = poFeatureDefn->GetFieldIndex("ROWID");
    }

    int nFieldCount = poFeatureDefn->GetFieldCount();
    if (nTokens == nFieldCount + bHiddenGeometryField + nAttrOffset)
    {
        for(int i=0;i<nFieldCount+bHiddenGeometryField;i++)
        {
            const char* pszVal = papszTokens[i+nAttrOffset];
            if (pszVal[0])
            {
                if (i<nFieldCount)
                    poFeature->SetField(i, pszVal);

                if (i == iGeometryField && i != iLatitudeField)
                {
                    if (pszVal[0] == '-' || (pszVal[0] >= '0' && pszVal[0] <= '9'))
                    {
                        char** papszLatLon = CSLTokenizeString2(pszVal, " ,", 0);
                        if (CSLCount(papszLatLon) == 2 &&
                            CPLGetValueType(papszLatLon[0]) != CPL_VALUE_STRING &&
                            CPLGetValueType(papszLatLon[1]) != CPL_VALUE_STRING)
                        {
                            OGRPoint* poPoint = new OGRPoint(CPLAtof( papszLatLon[1]),
                                                            CPLAtof( papszLatLon[0]));
                            poPoint->assignSpatialReference(poSRS);
                            poFeature->SetGeometryDirectly(poPoint);
                        }
                        CSLDestroy(papszLatLon);
                    }
                    else if (strstr(pszVal, "<Point>") ||
                             strstr(pszVal, "<LineString>") ||
                             strstr(pszVal, "<Polygon>"))
                    {
                        OGRGeometry* poGeom = ParseKMLGeometry(pszVal);
                        if (poGeom)
                        {
                            poGeom->assignSpatialReference(poSRS);
                            poFeature->SetGeometryDirectly(poGeom);
                        }
                    }
                }
                else if (i == iROWID)
                {
                    osFID = pszVal;
                }
            }
        }

        if (iLatitudeField >= 0 && iLongitudeField >= 0)
        {
            const char* pszLat = papszTokens[iLatitudeField+nAttrOffset];
            const char* pszLong = papszTokens[iLongitudeField+nAttrOffset];
            if (pszLat[0] != 0 && pszLong[0] != 0 &&
                CPLGetValueType(pszLat) != CPL_VALUE_STRING &&
                CPLGetValueType(pszLong) != CPL_VALUE_STRING)
            {
                OGRPoint* poPoint = new OGRPoint(CPLAtof(pszLong), CPLAtof(pszLat));
                poPoint->assignSpatialReference(poSRS);
                poFeature->SetGeometryDirectly(poPoint);
            }
        }
    }
    else
    {
        CPLDebug("GFT", "Only %d columns for feature %s", nTokens, osFID.c_str());
    }
    CSLDestroy(papszTokens);

    int nFID = atoi(osFID);
    if (strcmp(CPLSPrintf("%d", nFID), osFID.c_str()) == 0)
        poFeature->SetFID(nFID);
    else
        poFeature->SetFID(nNextInSeq);

    return poFeature;
}
Exemple #2
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;
    }

    CPLHTTPDestroyResult(psResult);

    return TRUE;
}
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 ||
            !STARTS_WITH(pszLine, "column id,name,type"))        {
            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 unauthenticated case, we try to parse the first record to */
        /* auto-detect 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 &&
                        (STARTS_WITH(pszVal, "<Point>") ||
                         STARTS_WITH(pszVal, "<LineString>") ||
                         STARTS_WITH(pszVal, "<Polygon>") ||
                         STARTS_WITH(pszVal, "<MultiGeometry>")))
                    {
                        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;
}