1 : /******************************************************************************
2 : * $Id: ogrgftresultlayer.cpp 22115 2011-04-03 22:27:42Z 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 22115 2011-04-03 22:27:42Z rouault $");
33 :
34 : /************************************************************************/
35 : /* OGRGFTResultLayer() */
36 : /************************************************************************/
37 :
38 0 : OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
39 0 : const char* pszSQL) : OGRGFTLayer(poDS)
40 :
41 : {
42 0 : osSQL = PatchSQL(pszSQL);
43 :
44 0 : bGotAllRows = FALSE;
45 :
46 0 : poFeatureDefn = new OGRFeatureDefn( "result" );
47 0 : poFeatureDefn->Reference();
48 0 : poFeatureDefn->SetGeomType( wkbUnknown );
49 0 : }
50 :
51 : /************************************************************************/
52 : /* ~OGRGFTResultLayer() */
53 : /************************************************************************/
54 :
55 0 : OGRGFTResultLayer::~OGRGFTResultLayer()
56 :
57 : {
58 0 : }
59 :
60 : /************************************************************************/
61 : /* ResetReading() */
62 : /************************************************************************/
63 :
64 0 : void OGRGFTResultLayer::ResetReading()
65 :
66 : {
67 0 : nNextInSeq = 0;
68 0 : nOffset = 0;
69 0 : if (!bGotAllRows)
70 : {
71 0 : aosRows.resize(0);
72 0 : bEOF = FALSE;
73 : }
74 0 : }
75 :
76 : /************************************************************************/
77 : /* FetchNextRows() */
78 : /************************************************************************/
79 :
80 0 : int OGRGFTResultLayer::FetchNextRows()
81 : {
82 0 : if (!((EQUALN(osSQL.c_str(), "SELECT", 6) ||
83 : EQUALN(osSQL.c_str(), "select", 6))))
84 0 : return FALSE;
85 :
86 0 : aosRows.resize(0);
87 :
88 0 : CPLString osChangedSQL(osSQL);
89 0 : if (strstr(osSQL.c_str(), " OFFSET ") == NULL &&
90 : strstr(osSQL.c_str(), " offset ") == NULL &&
91 : strstr(osSQL.c_str(), " LIMIT ") == NULL &&
92 : strstr(osSQL.c_str(), " limit ") == NULL )
93 : {
94 : osChangedSQL += CPLSPrintf(" OFFSET %d LIMIT %d",
95 0 : nOffset, GetFeaturesToFetch());
96 : }
97 :
98 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
99 0 : CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
100 0 : CPLPopErrorHandler();
101 :
102 0 : if (psResult == NULL)
103 : {
104 0 : bEOF = TRUE;
105 0 : return FALSE;
106 : }
107 :
108 0 : char* pszLine = (char*) psResult->pabyData;
109 0 : if (pszLine == NULL ||
110 : psResult->pszErrBuf != NULL)
111 : {
112 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
113 0 : CPLHTTPDestroyResult(psResult);
114 0 : bEOF = TRUE;
115 0 : return FALSE;
116 : }
117 :
118 0 : pszLine = OGRGFTGotoNextLine(pszLine);
119 0 : if (pszLine == NULL)
120 : {
121 0 : CPLHTTPDestroyResult(psResult);
122 0 : bEOF = TRUE;
123 0 : return FALSE;
124 : }
125 :
126 0 : ParseCSVResponse(pszLine, aosRows);
127 :
128 0 : CPLHTTPDestroyResult(psResult);
129 :
130 0 : bEOF = (int)aosRows.size() < GetFeaturesToFetch();
131 :
132 0 : return TRUE;
133 : }
134 :
135 : /************************************************************************/
136 : /* OGRGFTExtractTableID() */
137 : /************************************************************************/
138 :
139 0 : static CPLString OGRGFTExtractTableID(const char* pszTableID,
140 : CPLString& osReminder)
141 : {
142 0 : CPLString osTableId(pszTableID);
143 0 : if (osTableId.size() > 1 &&
144 : (osTableId[0] == '"' || osTableId[0] == '\''))
145 : {
146 0 : char chFirstChar = osTableId[0];
147 0 : osTableId.erase(0, 1);
148 0 : for(int i=0;i<(int)osTableId.size();i++)
149 : {
150 0 : if (osTableId[i] == chFirstChar)
151 : {
152 0 : osReminder = osTableId.substr(i+1);
153 0 : osTableId.resize(i);
154 0 : break;
155 : }
156 : }
157 : }
158 : else
159 : {
160 0 : for(int i=0;i<(int)osTableId.size();i++)
161 : {
162 0 : if (osTableId[i] == ' ')
163 : {
164 0 : osReminder = osTableId.substr(i);
165 0 : osTableId.resize(i);
166 0 : break;
167 : }
168 : }
169 : }
170 0 : return osTableId;
171 : }
172 :
173 : /************************************************************************/
174 : /* RunSQL() */
175 : /************************************************************************/
176 :
177 0 : int OGRGFTResultLayer::RunSQL()
178 : {
179 0 : CPLString osChangedSQL(osSQL);
180 0 : int bHasSetLimit = FALSE;
181 0 : OGRGFTTableLayer* poTableLayer = NULL;
182 0 : OGRFeatureDefn* poTableDefn = NULL;
183 0 : CPLString osTableId;
184 0 : if (EQUALN(osSQL.c_str(), "SELECT", 6))
185 : {
186 0 : const char* pszFROM = strstr(osSQL.c_str(), " FROM ");
187 0 : if (pszFROM == NULL)
188 0 : pszFROM = strstr(osSQL.c_str(), " from ");
189 0 : if (pszFROM == NULL)
190 : {
191 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed. Missing FROM in SELECT");
192 0 : return FALSE;
193 : }
194 0 : CPLString osReminder;
195 0 : int nPosFROM = pszFROM - osSQL.c_str() + 6;
196 0 : osTableId = OGRGFTExtractTableID(pszFROM + 6, osReminder);
197 0 : pszFROM = NULL;
198 :
199 0 : poTableLayer = (OGRGFTTableLayer*) poDS->GetLayerByName(osTableId);
200 0 : if (poTableLayer != NULL)
201 0 : poTableDefn = poTableLayer->GetLayerDefn();
202 :
203 0 : if (poTableLayer != NULL &&
204 : poTableLayer->GetTableId().size() &&
205 : !EQUAL(osTableId, poTableLayer->GetTableId()))
206 : {
207 0 : osChangedSQL = osSQL;
208 0 : osChangedSQL.resize(nPosFROM);
209 0 : osChangedSQL += poTableLayer->GetTableId();
210 0 : osChangedSQL += osReminder;
211 0 : osSQL = osChangedSQL;
212 : CPLDebug("GFT", "Patching table name (%s) to table id (%s)",
213 0 : osTableId.c_str(), poTableLayer->GetTableId().c_str());
214 : }
215 :
216 0 : int nFeaturesToFetch = GetFeaturesToFetch();
217 0 : if (strstr(osSQL.c_str(), " OFFSET ") == NULL &&
218 : strstr(osSQL.c_str(), " offset ") == NULL &&
219 : strstr(osSQL.c_str(), " LIMIT ") == NULL &&
220 : strstr(osSQL.c_str(), " limit ") == NULL &&
221 : nFeaturesToFetch > 0)
222 : {
223 0 : osChangedSQL += CPLSPrintf(" LIMIT %d", nFeaturesToFetch);
224 0 : bHasSetLimit = TRUE;
225 0 : }
226 : }
227 : else
228 : {
229 0 : bGotAllRows = bEOF = TRUE;
230 0 : poFeatureDefn->SetGeomType( wkbNone );
231 : }
232 :
233 0 : CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
234 :
235 0 : if (psResult == NULL)
236 0 : return FALSE;
237 :
238 0 : char* pszLine = (char*) psResult->pabyData;
239 0 : if (pszLine == NULL ||
240 : psResult->pszErrBuf != NULL)
241 : {
242 0 : CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
243 0 : CPLHTTPDestroyResult(psResult);
244 0 : return FALSE;
245 : }
246 :
247 0 : if (EQUALN(osSQL.c_str(), "SELECT", 6) ||
248 : EQUAL(osSQL.c_str(), "SHOW TABLES") ||
249 : EQUALN(osSQL.c_str(), "DESCRIBE", 8))
250 : {
251 0 : ParseCSVResponse(pszLine, aosRows);
252 0 : if (aosRows.size() > 0)
253 : {
254 0 : char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
255 0 : for(int i=0;papszTokens && papszTokens[i];i++)
256 : {
257 0 : CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
258 0 : int iIndex = (poTableDefn) ? poTableDefn->GetFieldIndex(osLaunderedColName) : -1;
259 0 : if (iIndex >= 0)
260 : {
261 0 : poFeatureDefn->AddFieldDefn(poTableDefn->GetFieldDefn(iIndex));
262 0 : if (iIndex == poTableLayer->GetGeometryFieldIndex())
263 0 : iGeometryField = i;
264 0 : if (iIndex == poTableLayer->GetLatitudeFieldIndex())
265 0 : iLatitudeField = i;
266 0 : if (iIndex == poTableLayer->GetLongitudeFieldIndex())
267 0 : iLongitudeField = i;
268 : }
269 : else
270 : {
271 0 : OGRFieldType eType = OFTString;
272 0 : if (EQUAL(osLaunderedColName, "COUNT()"))
273 0 : eType = OFTInteger;
274 0 : OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
275 0 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
276 : }
277 : }
278 0 : CSLDestroy(papszTokens);
279 :
280 0 : aosRows.erase(aosRows.begin());
281 : }
282 :
283 0 : if (iLatitudeField >= 0 && iLongitudeField >= 0)
284 : {
285 0 : iGeometryField = iLatitudeField;
286 0 : poFeatureDefn->SetGeomType( wkbPoint );
287 : }
288 :
289 0 : if (bHasSetLimit)
290 0 : bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
291 : else
292 0 : bGotAllRows = bEOF = TRUE;
293 : }
294 :
295 0 : CPLHTTPDestroyResult(psResult);
296 :
297 0 : return TRUE;
298 : }
|