1 : /******************************************************************************
2 : * $Id: ogrgftresultlayer.cpp 24343 2012-04-29 11:31:01Z rouault $
3 : *
4 : * Project: GFT Translator
5 : * Purpose: Implements OGRGFTResultLayer class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_gft.h"
31 :
32 : CPL_CVSID("$Id: ogrgftresultlayer.cpp 24343 2012-04-29 11:31:01Z rouault $");
33 :
34 : /************************************************************************/
35 : /* OGRGFTResultLayer() */
36 : /************************************************************************/
37 :
38 1 : OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
39 1 : const char* pszSQL) : OGRGFTLayer(poDS)
40 :
41 : {
42 1 : osSQL = PatchSQL(pszSQL);
43 :
44 1 : bGotAllRows = FALSE;
45 :
46 1 : poFeatureDefn = new OGRFeatureDefn( "result" );
47 1 : poFeatureDefn->Reference();
48 1 : poFeatureDefn->SetGeomType( wkbUnknown );
49 1 : }
50 :
51 : /************************************************************************/
52 : /* ~OGRGFTResultLayer() */
53 : /************************************************************************/
54 :
55 1 : OGRGFTResultLayer::~OGRGFTResultLayer()
56 :
57 : {
58 1 : }
59 :
60 : /************************************************************************/
61 : /* ResetReading() */
62 : /************************************************************************/
63 :
64 2 : void OGRGFTResultLayer::ResetReading()
65 :
66 : {
67 2 : nNextInSeq = 0;
68 2 : nOffset = 0;
69 2 : if (!bGotAllRows)
70 : {
71 0 : aosRows.resize(0);
72 0 : bEOF = FALSE;
73 : }
74 2 : }
75 :
76 : /************************************************************************/
77 : /* FetchNextRows() */
78 : /************************************************************************/
79 :
80 0 : int OGRGFTResultLayer::FetchNextRows()
81 : {
82 0 : if (!EQUALN(osSQL.c_str(), "SELECT", 6))
83 0 : return FALSE;
84 :
85 0 : aosRows.resize(0);
86 :
87 0 : CPLString osChangedSQL(osSQL);
88 0 : if (osSQL.ifind(" OFFSET ") == std::string::npos &&
89 : osSQL.ifind(" LIMIT ") == std::string::npos)
90 : {
91 : osChangedSQL += CPLSPrintf(" OFFSET %d LIMIT %d",
92 0 : nOffset, GetFeaturesToFetch());
93 : }
94 :
95 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
96 0 : CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
97 0 : CPLPopErrorHandler();
98 :
99 0 : if (psResult == NULL)
100 : {
101 0 : bEOF = TRUE;
102 0 : return FALSE;
103 : }
104 :
105 0 : char* pszLine = (char*) psResult->pabyData;
106 0 : if (pszLine == NULL ||
107 : psResult->pszErrBuf != NULL)
108 : {
109 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
110 0 : CPLHTTPDestroyResult(psResult);
111 0 : bEOF = TRUE;
112 0 : return FALSE;
113 : }
114 :
115 0 : pszLine = OGRGFTGotoNextLine(pszLine);
116 0 : if (pszLine == NULL)
117 : {
118 0 : CPLHTTPDestroyResult(psResult);
119 0 : bEOF = TRUE;
120 0 : return FALSE;
121 : }
122 :
123 0 : ParseCSVResponse(pszLine, aosRows);
124 :
125 0 : CPLHTTPDestroyResult(psResult);
126 :
127 0 : bEOF = (int)aosRows.size() < GetFeaturesToFetch();
128 :
129 0 : return TRUE;
130 : }
131 :
132 : /************************************************************************/
133 : /* OGRGFTExtractTableID() */
134 : /************************************************************************/
135 :
136 1 : static CPLString OGRGFTExtractTableID(const char* pszTableID,
137 : CPLString& osReminder)
138 : {
139 1 : CPLString osTableId(pszTableID);
140 1 : if (osTableId.size() > 1 &&
141 : (osTableId[0] == '"' || osTableId[0] == '\''))
142 : {
143 0 : char chFirstChar = osTableId[0];
144 0 : osTableId.erase(0, 1);
145 0 : for(int i=0;i<(int)osTableId.size();i++)
146 : {
147 0 : if (osTableId[i] == chFirstChar)
148 : {
149 0 : osReminder = osTableId.substr(i+1);
150 0 : osTableId.resize(i);
151 0 : break;
152 : }
153 : }
154 : }
155 : else
156 : {
157 7 : for(int i=0;i<(int)osTableId.size();i++)
158 : {
159 7 : if (osTableId[i] == ' ')
160 : {
161 1 : osReminder = osTableId.substr(i);
162 1 : osTableId.resize(i);
163 1 : break;
164 : }
165 : }
166 : }
167 0 : return osTableId;
168 : }
169 :
170 : /************************************************************************/
171 : /* RunSQL() */
172 : /************************************************************************/
173 :
174 1 : int OGRGFTResultLayer::RunSQL()
175 : {
176 1 : CPLString osChangedSQL(osSQL);
177 1 : int bHasSetLimit = FALSE;
178 1 : OGRGFTTableLayer* poTableLayer = NULL;
179 1 : OGRFeatureDefn* poTableDefn = NULL;
180 1 : CPLString osTableId;
181 1 : if (EQUALN(osSQL.c_str(), "SELECT", 6))
182 : {
183 1 : size_t nPosFROM = osSQL.ifind(" FROM ");
184 1 : if (nPosFROM == std::string::npos)
185 : {
186 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed. Missing FROM in SELECT");
187 0 : return FALSE;
188 : }
189 1 : CPLString osReminder;
190 1 : nPosFROM += 6;
191 1 : osTableId = OGRGFTExtractTableID(osSQL.c_str() + nPosFROM, osReminder);
192 :
193 1 : poTableLayer = (OGRGFTTableLayer*) poDS->GetLayerByName(osTableId);
194 1 : if (poTableLayer != NULL)
195 1 : poTableDefn = poTableLayer->GetLayerDefn();
196 :
197 1 : if (poTableLayer != NULL &&
198 : poTableLayer->GetTableId().size() &&
199 : !EQUAL(osTableId, poTableLayer->GetTableId()))
200 : {
201 0 : osChangedSQL = osSQL;
202 0 : osChangedSQL.resize(nPosFROM);
203 0 : osChangedSQL += poTableLayer->GetTableId();
204 0 : osChangedSQL += osReminder;
205 0 : osSQL = osChangedSQL;
206 : CPLDebug("GFT", "Patching table name (%s) to table id (%s)",
207 0 : osTableId.c_str(), poTableLayer->GetTableId().c_str());
208 : }
209 :
210 1 : int nFeaturesToFetch = GetFeaturesToFetch();
211 1 : if (osSQL.ifind(" OFFSET ") == std::string::npos &&
212 : osSQL.ifind(" LIMIT ") == std::string::npos &&
213 : nFeaturesToFetch > 0)
214 : {
215 1 : osChangedSQL += CPLSPrintf(" LIMIT %d", nFeaturesToFetch);
216 1 : bHasSetLimit = TRUE;
217 1 : }
218 : }
219 : else
220 : {
221 0 : bGotAllRows = bEOF = TRUE;
222 0 : poFeatureDefn->SetGeomType( wkbNone );
223 : }
224 :
225 1 : CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
226 :
227 1 : if (psResult == NULL)
228 0 : return FALSE;
229 :
230 1 : char* pszLine = (char*) psResult->pabyData;
231 1 : if (pszLine == NULL ||
232 : psResult->pszErrBuf != NULL)
233 : {
234 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
235 0 : CPLHTTPDestroyResult(psResult);
236 0 : return FALSE;
237 : }
238 :
239 1 : if (EQUALN(osSQL.c_str(), "SELECT", 6) ||
240 : EQUAL(osSQL.c_str(), "SHOW TABLES") ||
241 : EQUALN(osSQL.c_str(), "DESCRIBE", 8))
242 : {
243 1 : ParseCSVResponse(pszLine, aosRows);
244 1 : if (aosRows.size() > 0)
245 : {
246 1 : char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
247 3 : for(int i=0;papszTokens && papszTokens[i];i++)
248 : {
249 2 : CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
250 2 : int iIndex = (poTableDefn) ? poTableDefn->GetFieldIndex(osLaunderedColName) : -1;
251 2 : if (iIndex >= 0)
252 : {
253 2 : poFeatureDefn->AddFieldDefn(poTableDefn->GetFieldDefn(iIndex));
254 2 : if (iIndex == poTableLayer->GetGeometryFieldIndex())
255 1 : iGeometryField = i;
256 2 : if (iIndex == poTableLayer->GetLatitudeFieldIndex())
257 1 : iLatitudeField = i;
258 2 : if (iIndex == poTableLayer->GetLongitudeFieldIndex())
259 1 : iLongitudeField = i;
260 : }
261 : else
262 : {
263 0 : OGRFieldType eType = OFTString;
264 0 : if (EQUAL(osLaunderedColName, "COUNT()"))
265 0 : eType = OFTInteger;
266 0 : OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
267 0 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
268 : }
269 : }
270 1 : CSLDestroy(papszTokens);
271 :
272 1 : aosRows.erase(aosRows.begin());
273 : }
274 :
275 1 : if (iLatitudeField >= 0 && iLongitudeField >= 0)
276 : {
277 1 : iGeometryField = iLatitudeField;
278 1 : poFeatureDefn->SetGeomType( wkbPoint );
279 : }
280 :
281 1 : if (bHasSetLimit)
282 1 : bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
283 : else
284 0 : bGotAllRows = bEOF = TRUE;
285 : }
286 :
287 1 : CPLHTTPDestroyResult(psResult);
288 :
289 1 : return TRUE;
290 : }
|