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 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "vfkreader.h"
14 : #include "vfkreaderp.h"
15 :
16 : #include "cpl_conv.h"
17 : #include "cpl_error.h"
18 :
19 : /*!
20 : \brief VFKFeatureSQLite constructor (from DB)
21 :
22 : Read VFK feature from DB
23 :
24 : \param poDataBlock pointer to related IVFKDataBlock
25 : */
26 0 : VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock)
27 : : IVFKFeature(poDataBlock),
28 : // Starts at 1.
29 0 : m_iRowId(static_cast<int>(poDataBlock->GetFeatureCount() + 1)),
30 0 : m_hStmt(nullptr)
31 : {
32 : // Set FID from DB.
33 0 : SetFIDFromDB(); // -> m_nFID
34 0 : }
35 :
36 : /*!
37 : \brief VFKFeatureSQLite constructor
38 :
39 : \param poDataBlock pointer to related IVFKDataBlock
40 : \param iRowId feature DB rowid (starts at 1)
41 : \param nFID feature id
42 : */
43 688 : VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock, int iRowId,
44 688 : GIntBig nFID)
45 688 : : IVFKFeature(poDataBlock), m_iRowId(iRowId), m_hStmt(nullptr)
46 : {
47 688 : m_nFID = nFID;
48 688 : }
49 :
50 : /*!
51 : \brief Read FID from DB
52 : */
53 0 : OGRErr VFKFeatureSQLite::SetFIDFromDB()
54 : {
55 0 : CPLString osSQL;
56 :
57 : osSQL.Printf("SELECT %s FROM %s WHERE rowid = %d", FID_COLUMN,
58 0 : m_poDataBlock->GetName(), m_iRowId);
59 0 : if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
60 0 : return OGRERR_FAILURE;
61 :
62 0 : m_nFID = sqlite3_column_int(m_hStmt, 0);
63 :
64 0 : FinalizeSQL();
65 :
66 0 : return OGRERR_NONE;
67 : }
68 :
69 : /*!
70 : \brief Set DB row id
71 :
72 : \param iRowId row id to be set
73 : */
74 196 : void VFKFeatureSQLite::SetRowId(int iRowId)
75 : {
76 196 : m_iRowId = iRowId;
77 196 : }
78 :
79 : /*!
80 : \brief Finalize SQL statement
81 : */
82 31 : void VFKFeatureSQLite::FinalizeSQL()
83 : {
84 31 : sqlite3_finalize(m_hStmt);
85 31 : m_hStmt = nullptr;
86 31 : }
87 :
88 : /*!
89 : \brief Execute SQL (select) statement
90 :
91 : \param pszSQLCommand SQL command string
92 :
93 : \return OGRERR_NONE on success or OGRERR_FAILURE on error
94 : */
95 27 : OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
96 : {
97 : VFKReaderSQLite *poReader =
98 27 : cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader());
99 27 : sqlite3 *poDB = poReader->m_poDB;
100 :
101 27 : int rc = sqlite3_prepare_v2(poDB, pszSQLCommand, -1, &m_hStmt, nullptr);
102 27 : if (rc != SQLITE_OK)
103 : {
104 0 : CPLError(CE_Failure, CPLE_AppDefined,
105 : "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n %s",
106 : pszSQLCommand, sqlite3_errmsg(poDB));
107 :
108 0 : if (m_hStmt != nullptr)
109 : {
110 0 : FinalizeSQL();
111 : }
112 0 : return OGRERR_FAILURE;
113 : }
114 27 : rc = sqlite3_step(m_hStmt);
115 27 : if (rc != SQLITE_ROW)
116 : {
117 0 : CPLError(CE_Failure, CPLE_AppDefined,
118 : "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszSQLCommand,
119 : sqlite3_errmsg(poDB));
120 :
121 0 : if (m_hStmt)
122 : {
123 0 : FinalizeSQL();
124 : }
125 :
126 0 : return OGRERR_FAILURE;
127 : }
128 :
129 27 : return OGRERR_NONE;
130 : }
131 :
132 : /*!
133 : \brief VFKFeatureSQLite constructor (derived from VFKFeature)
134 :
135 : Read VFK feature from VFK file and insert it into DB
136 : */
137 0 : VFKFeatureSQLite::VFKFeatureSQLite(const VFKFeature *poVFKFeature)
138 0 : : IVFKFeature(poVFKFeature->m_poDataBlock),
139 : // Starts at 1.
140 : m_iRowId(
141 0 : static_cast<int>(poVFKFeature->m_poDataBlock->GetFeatureCount() + 1)),
142 0 : m_hStmt(nullptr)
143 : {
144 0 : m_nFID = poVFKFeature->m_nFID;
145 0 : }
146 :
147 : /*!
148 : \brief Load geometry (point layers)
149 :
150 : \todo Implement (really needed?)
151 :
152 : \return true on success or false on failure
153 : */
154 0 : bool VFKFeatureSQLite::LoadGeometryPoint()
155 : {
156 0 : return false;
157 : }
158 :
159 : /*!
160 : \brief Load geometry (linestring SBP layer)
161 :
162 : \todo Implement (really needed?)
163 :
164 : \return true on success or false on failure
165 : */
166 0 : bool VFKFeatureSQLite::LoadGeometryLineStringSBP()
167 : {
168 0 : return false;
169 : }
170 :
171 : /*!
172 : \brief Load geometry (linestring HP/DPM layer)
173 :
174 : \todo Implement (really needed?)
175 :
176 : \return true on success or false on failure
177 : */
178 0 : bool VFKFeatureSQLite::LoadGeometryLineStringHP()
179 : {
180 0 : return false;
181 : }
182 :
183 : /*!
184 : \brief Load geometry (polygon BUD/PAR layers)
185 :
186 : \todo Implement (really needed?)
187 :
188 : \return true on success or false on failure
189 : */
190 0 : bool VFKFeatureSQLite::LoadGeometryPolygon()
191 : {
192 0 : return false;
193 : }
194 :
195 : /*!
196 : \brief Load feature properties from DB
197 :
198 : \param poFeature pointer to OGR feature
199 :
200 : \return OGRERR_NONE on success or OGRERR_FAILURE on failure
201 : */
202 31 : OGRErr VFKFeatureSQLite::LoadProperties(OGRFeature *poFeature)
203 : {
204 : sqlite3_stmt *hStmt =
205 31 : cpl::down_cast<VFKDataBlockSQLite *>(m_poDataBlock)->m_hStmt;
206 31 : if (hStmt == nullptr)
207 : {
208 : /* random access */
209 27 : CPLString osSQL;
210 :
211 : osSQL.Printf("SELECT * FROM %s WHERE rowid = %d",
212 27 : m_poDataBlock->GetName(), m_iRowId);
213 27 : if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
214 0 : return OGRERR_FAILURE;
215 :
216 27 : hStmt = m_hStmt;
217 : }
218 : else
219 : {
220 : /* sequential access */
221 : VFKReaderSQLite *poReader =
222 4 : cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader());
223 4 : if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
224 : {
225 0 : cpl::down_cast<VFKDataBlockSQLite *>(m_poDataBlock)->m_hStmt =
226 : nullptr;
227 0 : return OGRERR_FAILURE;
228 : }
229 : }
230 :
231 31 : int nPropertyCount = m_poDataBlock->GetPropertyCount();
232 469 : for (int iField = 0; iField < nPropertyCount; iField++)
233 : {
234 438 : if (sqlite3_column_type(hStmt, iField) ==
235 : SQLITE_NULL) /* skip null values */
236 127 : continue;
237 : OGRFieldType fType =
238 311 : poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
239 311 : switch (fType)
240 : {
241 116 : case OFTInteger:
242 116 : poFeature->SetField(iField, sqlite3_column_int(hStmt, iField));
243 116 : break;
244 129 : case OFTInteger64:
245 129 : poFeature->SetField(iField,
246 : sqlite3_column_int64(hStmt, iField));
247 129 : break;
248 26 : case OFTReal:
249 26 : poFeature->SetField(iField,
250 : sqlite3_column_double(hStmt, iField));
251 26 : break;
252 40 : default:
253 80 : poFeature->SetField(
254 40 : iField, (const char *)sqlite3_column_text(hStmt, iField));
255 40 : break;
256 : }
257 : }
258 :
259 31 : if (m_poDataBlock->GetReader()->HasFileField())
260 : {
261 : /* open option FILE_FIELD=YES specified, append extra
262 : * attribute */
263 1 : poFeature->SetField(
264 : nPropertyCount,
265 1 : CPLGetFilename(m_poDataBlock->GetReader()->GetFilename()));
266 : }
267 :
268 31 : FinalizeSQL();
269 :
270 31 : return OGRERR_NONE;
271 : }
|