1 /*****************************************************************************
2 *
3 * Project: DB2 Spatial driver
4 * Purpose: Implements OGRDB2SelectLayer class, layer access to the results
5 * of a SELECT statement executed via ExecuteSQL().
6 * Author: David Adler, dadler at adtechgeospatial dot com
7 *
8 *****************************************************************************
9 * Copyright (c) 2010, Tamas Szekeres
10 * Copyright (c) 2015, David Adler
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "cpl_conv.h"
32 #include "ogr_db2.h"
33
34 CPL_CVSID("$Id: ogrdb2selectlayer.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
35
36 /************************************************************************/
37 /* OGRDB2SelectLayer() */
38 /************************************************************************/
39
OGRDB2SelectLayer(OGRDB2DataSource * poDSIn,OGRDB2Statement * poStmtIn)40 OGRDB2SelectLayer::OGRDB2SelectLayer( OGRDB2DataSource *poDSIn,
41 OGRDB2Statement * poStmtIn )
42
43 {
44
45 SQLCHAR szTableName[256];
46 SQLCHAR szSchemaName[256];
47 SQLSMALLINT nNameLength = 0;
48 OGRDB2Layer *poBaseLayer = nullptr;
49 poDS = poDSIn;
50
51 iNextShapeId = 0;
52 nSRSId = -1;
53 poFeatureDefn = nullptr;
54
55 m_poStmt = poStmtIn;
56 pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
57 CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer", "SQL: '%s'",
58 pszBaseStatement);
59
60 pszGeomColumn = nullptr;
61
62 /* get schema and table names for first column, column 1 */
63 SQLColAttribute(m_poStmt->GetStatement(), (SQLSMALLINT)(1),
64 SQL_DESC_SCHEMA_NAME,
65 szSchemaName, sizeof(szSchemaName),
66 &nNameLength, nullptr);
67 /* The schema name is sometimes right padded with blanks */
68 /* Replace blanks with nulls to terminate string for sprintf below */
69 for (int i = 0; i < nNameLength; i++) {
70 if (szSchemaName[i] == ' ') szSchemaName[i] = 0;
71 };
72 SQLColAttribute(m_poStmt->GetStatement(), (SQLSMALLINT)(1),
73 SQL_DESC_TABLE_NAME,
74 szTableName, sizeof(szTableName),
75 &nNameLength, nullptr);
76 CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
77 "szSchemaName: '%s'; szTableName: '%s'",
78 szSchemaName, szTableName);
79 if (nNameLength > 0)
80 {
81 char szLayerName[512];
82 snprintf(szLayerName, sizeof(szLayerName), "%s.%s",szSchemaName, szTableName);
83 poBaseLayer = (OGRDB2Layer *) poDS->GetLayerByName((const char*)
84 szLayerName);
85 if (poBaseLayer != nullptr)
86 CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
87 "base geom col: '%s'", poBaseLayer->GetGeometryColumn());
88 else CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
89 "base layer not found");
90 }
91
92 /* identify the geometry column */
93 for ( int iColumn = 0; iColumn < m_poStmt->GetColCount(); iColumn++ )
94 {
95 if ( EQUAL(m_poStmt->GetColTypeName( iColumn ), "CLOB") ||
96 EQUAL(m_poStmt->GetColTypeName( iColumn ),
97 "VARCHAR () FOR BIT DATA"))
98 {
99 if (poBaseLayer != nullptr
100 && EQUAL(poBaseLayer->GetGeometryColumn(),
101 m_poStmt->GetColName(iColumn)))
102 {
103 pszGeomColumn = CPLStrdup(m_poStmt->GetColName(iColumn));
104 /* copy spatial reference */
105 if (!poSRS && poBaseLayer->GetSpatialRef())
106 poSRS = poBaseLayer->GetSpatialRef()->Clone();
107 nSRSId = poBaseLayer->GetSRSId();
108 break;
109 }
110 }
111 }
112
113 BuildFeatureDefn( "SELECT", m_poStmt );
114
115 if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
116 poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
117 }
118
119 /************************************************************************/
120 /* ~OGRDB2SelectLayer() */
121 /************************************************************************/
122
~OGRDB2SelectLayer()123 OGRDB2SelectLayer::~OGRDB2SelectLayer()
124
125 {
126 ClearStatement();
127 CPLFree(pszBaseStatement);
128 }
129
130 /************************************************************************/
131 /* ClearStatement() */
132 /************************************************************************/
133
ClearStatement()134 void OGRDB2SelectLayer::ClearStatement()
135
136 {
137 if( m_poStmt != nullptr )
138 {
139 delete m_poStmt;
140 m_poStmt = nullptr;
141 }
142 }
143
144 /************************************************************************/
145 /* GetStatement() */
146 /************************************************************************/
147
GetStatement()148 OGRDB2Statement *OGRDB2SelectLayer::GetStatement()
149
150 {
151 if( m_poStmt == nullptr )
152 ResetStatement();
153
154 return m_poStmt;
155 }
156
157 /************************************************************************/
158 /* ResetStatement() */
159 /************************************************************************/
160
ResetStatement()161 OGRErr OGRDB2SelectLayer::ResetStatement()
162
163 {
164 ClearStatement();
165
166 iNextShapeId = 0;
167
168 CPLDebug( "OGR_DB2SelectLayer::ResetStatement", "Recreating statement." );
169 m_poStmt = new OGRDB2Statement( poDS->GetSession() );
170 m_poStmt->Append( pszBaseStatement );
171
172 if( m_poStmt->ExecuteSQL() )
173 return OGRERR_NONE;
174 else
175 {
176 delete m_poStmt;
177 m_poStmt = nullptr;
178 return OGRERR_FAILURE;
179 }
180 }
181
182 /************************************************************************/
183 /* ResetReading() */
184 /************************************************************************/
185
ResetReading()186 void OGRDB2SelectLayer::ResetReading()
187
188 {
189 if( iNextShapeId != 0 )
190 ClearStatement();
191
192 OGRDB2Layer::ResetReading();
193 }
194
195 /************************************************************************/
196 /* GetFeature() */
197 /************************************************************************/
198
GetFeature(GIntBig nFeatureId)199 OGRFeature *OGRDB2SelectLayer::GetFeature( GIntBig nFeatureId )
200
201 {
202 return OGRDB2Layer::GetFeature( nFeatureId );
203 }
204
205 /************************************************************************/
206 /* TestCapability() */
207 /************************************************************************/
208
TestCapability(const char * pszCap)209 int OGRDB2SelectLayer::TestCapability( const char * pszCap )
210
211 {
212 return OGRDB2Layer::TestCapability( pszCap );
213 }
214
215 /************************************************************************/
216 /* GetExtent() */
217 /* */
218 /* Since SELECT layers currently cannot ever have geometry, we */
219 /* can optimize the GetExtent() method! */
220 /************************************************************************/
221
GetExtent(OGREnvelope *,int)222 OGRErr OGRDB2SelectLayer::GetExtent(OGREnvelope *, int )
223
224 {
225 return OGRERR_FAILURE;
226 }
227
228 /************************************************************************/
229 /* GetFeatureCount() */
230 /* */
231 /* If a spatial filter is in effect, we turn control over to */
232 /* the generic counter. Otherwise we return the total count. */
233 /* Eventually we should consider implementing a more efficient */
234 /* way of counting features matching a spatial query. */
235 /************************************************************************/
236
GetFeatureCount(int bForce)237 GIntBig OGRDB2SelectLayer::GetFeatureCount( int bForce )
238
239 {
240 return OGRDB2Layer::GetFeatureCount( bForce );
241 }
242