Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: VFK Reader - Feature definition (SQLite)
4 : * Purpose: Implements VFKFeatureSQLite class.
5 : * Author: Martin Landa, landa.martin gmail.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2018, Martin Landa <landa.martin gmail.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person
11 : * obtaining a copy of this software and associated documentation
12 : * files (the "Software"), to deal in the Software without
13 : * restriction, including without limitation the rights to use, copy,
14 : * modify, merge, publish, distribute, sublicense, and/or sell copies
15 : * of the Software, and to permit persons to whom the Software is
16 : * furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be
19 : * included in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 : * SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "vfkreader.h"
32 : #include "vfkreaderp.h"
33 :
34 : #include "cpl_conv.h"
35 : #include "cpl_error.h"
36 :
37 : /*!
38 : \brief VFKFeatureSQLite constructor (from DB)
39 :
40 : Read VFK feature from DB
41 :
42 : \param poDataBlock pointer to related IVFKDataBlock
43 : */
44 0 : VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock)
45 : : IVFKFeature(poDataBlock),
46 : // Starts at 1.
47 0 : m_iRowId(static_cast<int>(poDataBlock->GetFeatureCount() + 1)),
48 0 : m_hStmt(nullptr)
49 : {
50 : // Set FID from DB.
51 0 : SetFIDFromDB(); // -> m_nFID
52 0 : }
53 :
54 : /*!
55 : \brief VFKFeatureSQLite constructor
56 :
57 : \param poDataBlock pointer to related IVFKDataBlock
58 : \param iRowId feature DB rowid (starts at 1)
59 : \param nFID feature id
60 : */
61 688 : VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock, int iRowId,
62 688 : GIntBig nFID)
63 688 : : IVFKFeature(poDataBlock), m_iRowId(iRowId), m_hStmt(nullptr)
64 : {
65 688 : m_nFID = nFID;
66 688 : }
67 :
68 : /*!
69 : \brief Read FID from DB
70 : */
71 0 : OGRErr VFKFeatureSQLite::SetFIDFromDB()
72 : {
73 0 : CPLString osSQL;
74 :
75 : osSQL.Printf("SELECT %s FROM %s WHERE rowid = %d", FID_COLUMN,
76 0 : m_poDataBlock->GetName(), m_iRowId);
77 0 : if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
78 0 : return OGRERR_FAILURE;
79 :
80 0 : m_nFID = sqlite3_column_int(m_hStmt, 0);
81 :
82 0 : FinalizeSQL();
83 :
84 0 : return OGRERR_NONE;
85 : }
86 :
87 : /*!
88 : \brief Set DB row id
89 :
90 : \param iRowId row id to be set
91 : */
92 196 : void VFKFeatureSQLite::SetRowId(int iRowId)
93 : {
94 196 : m_iRowId = iRowId;
95 196 : }
96 :
97 : /*!
98 : \brief Finalize SQL statement
99 : */
100 31 : void VFKFeatureSQLite::FinalizeSQL()
101 : {
102 31 : sqlite3_finalize(m_hStmt);
103 31 : m_hStmt = nullptr;
104 31 : }
105 :
106 : /*!
107 : \brief Execute SQL (select) statement
108 :
109 : \param pszSQLCommand SQL command string
110 :
111 : \return OGRERR_NONE on success or OGRERR_FAILURE on error
112 : */
113 27 : OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
114 : {
115 27 : VFKReaderSQLite *poReader = (VFKReaderSQLite *)m_poDataBlock->GetReader();
116 27 : sqlite3 *poDB = poReader->m_poDB;
117 :
118 27 : int rc = sqlite3_prepare_v2(poDB, pszSQLCommand, -1, &m_hStmt, nullptr);
119 27 : if (rc != SQLITE_OK)
120 : {
121 0 : CPLError(CE_Failure, CPLE_AppDefined,
122 : "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n %s",
123 : pszSQLCommand, sqlite3_errmsg(poDB));
124 :
125 0 : if (m_hStmt != nullptr)
126 : {
127 0 : FinalizeSQL();
128 : }
129 0 : return OGRERR_FAILURE;
130 : }
131 27 : rc = sqlite3_step(m_hStmt);
132 27 : if (rc != SQLITE_ROW)
133 : {
134 0 : CPLError(CE_Failure, CPLE_AppDefined,
135 : "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszSQLCommand,
136 : sqlite3_errmsg(poDB));
137 :
138 0 : if (m_hStmt)
139 : {
140 0 : FinalizeSQL();
141 : }
142 :
143 0 : return OGRERR_FAILURE;
144 : }
145 :
146 27 : return OGRERR_NONE;
147 : }
148 :
149 : /*!
150 : \brief VFKFeatureSQLite constructor (derived from VFKFeature)
151 :
152 : Read VFK feature from VFK file and insert it into DB
153 : */
154 0 : VFKFeatureSQLite::VFKFeatureSQLite(const VFKFeature *poVFKFeature)
155 0 : : IVFKFeature(poVFKFeature->m_poDataBlock),
156 : // Starts at 1.
157 : m_iRowId(
158 0 : static_cast<int>(poVFKFeature->m_poDataBlock->GetFeatureCount() + 1)),
159 0 : m_hStmt(nullptr)
160 : {
161 0 : m_nFID = poVFKFeature->m_nFID;
162 0 : }
163 :
164 : /*!
165 : \brief Load geometry (point layers)
166 :
167 : \todo Implement (really needed?)
168 :
169 : \return true on success or false on failure
170 : */
171 0 : bool VFKFeatureSQLite::LoadGeometryPoint()
172 : {
173 0 : return false;
174 : }
175 :
176 : /*!
177 : \brief Load geometry (linestring SBP layer)
178 :
179 : \todo Implement (really needed?)
180 :
181 : \return true on success or false on failure
182 : */
183 0 : bool VFKFeatureSQLite::LoadGeometryLineStringSBP()
184 : {
185 0 : return false;
186 : }
187 :
188 : /*!
189 : \brief Load geometry (linestring HP/DPM layer)
190 :
191 : \todo Implement (really needed?)
192 :
193 : \return true on success or false on failure
194 : */
195 0 : bool VFKFeatureSQLite::LoadGeometryLineStringHP()
196 : {
197 0 : return false;
198 : }
199 :
200 : /*!
201 : \brief Load geometry (polygon BUD/PAR layers)
202 :
203 : \todo Implement (really needed?)
204 :
205 : \return true on success or false on failure
206 : */
207 0 : bool VFKFeatureSQLite::LoadGeometryPolygon()
208 : {
209 0 : return false;
210 : }
211 :
212 : /*!
213 : \brief Load feature properties from DB
214 :
215 : \param poFeature pointer to OGR feature
216 :
217 : \return OGRERR_NONE on success or OGRERR_FAILURE on failure
218 : */
219 31 : OGRErr VFKFeatureSQLite::LoadProperties(OGRFeature *poFeature)
220 : {
221 31 : sqlite3_stmt *hStmt = ((VFKDataBlockSQLite *)m_poDataBlock)->m_hStmt;
222 31 : if (hStmt == nullptr)
223 : {
224 : /* random access */
225 27 : CPLString osSQL;
226 :
227 : osSQL.Printf("SELECT * FROM %s WHERE rowid = %d",
228 27 : m_poDataBlock->GetName(), m_iRowId);
229 27 : if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
230 0 : return OGRERR_FAILURE;
231 :
232 27 : hStmt = m_hStmt;
233 : }
234 : else
235 : {
236 : /* sequential access */
237 : VFKReaderSQLite *poReader =
238 4 : (VFKReaderSQLite *)m_poDataBlock->GetReader();
239 4 : if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
240 : {
241 0 : ((VFKDataBlockSQLite *)m_poDataBlock)->m_hStmt = nullptr;
242 0 : return OGRERR_FAILURE;
243 : }
244 : }
245 :
246 31 : int nPropertyCount = m_poDataBlock->GetPropertyCount();
247 469 : for (int iField = 0; iField < nPropertyCount; iField++)
248 : {
249 438 : if (sqlite3_column_type(hStmt, iField) ==
250 : SQLITE_NULL) /* skip null values */
251 127 : continue;
252 : OGRFieldType fType =
253 311 : poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
254 311 : switch (fType)
255 : {
256 116 : case OFTInteger:
257 116 : poFeature->SetField(iField, sqlite3_column_int(hStmt, iField));
258 116 : break;
259 129 : case OFTInteger64:
260 129 : poFeature->SetField(iField,
261 : sqlite3_column_int64(hStmt, iField));
262 129 : break;
263 26 : case OFTReal:
264 26 : poFeature->SetField(iField,
265 : sqlite3_column_double(hStmt, iField));
266 26 : break;
267 40 : default:
268 80 : poFeature->SetField(
269 40 : iField, (const char *)sqlite3_column_text(hStmt, iField));
270 40 : break;
271 : }
272 : }
273 :
274 31 : if (m_poDataBlock->GetReader()->HasFileField())
275 : {
276 : /* open option FILE_FIELD=YES specified, append extra
277 : * attribute */
278 1 : poFeature->SetField(
279 : nPropertyCount,
280 1 : CPLGetFilename(m_poDataBlock->GetReader()->GetFilename()));
281 : }
282 :
283 31 : FinalizeSQL();
284 :
285 31 : return OGRERR_NONE;
286 : }
|