/src/gdal/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
Line | Count | Source |
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 | | VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock) |
27 | 0 | : IVFKFeature(poDataBlock), |
28 | | // Starts at 1. |
29 | 0 | m_iRowId(static_cast<int>(poDataBlock->GetFeatureCount() + 1)), |
30 | 0 | m_hStmt(nullptr) |
31 | 0 | { |
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 | | VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock, int iRowId, |
44 | | GIntBig nFID) |
45 | 21.2k | : IVFKFeature(poDataBlock), m_iRowId(iRowId), m_hStmt(nullptr) |
46 | 21.2k | { |
47 | 21.2k | m_nFID = nFID; |
48 | 21.2k | } |
49 | | |
50 | | /*! |
51 | | \brief Read FID from DB |
52 | | */ |
53 | | OGRErr VFKFeatureSQLite::SetFIDFromDB() |
54 | 0 | { |
55 | 0 | CPLString osSQL; |
56 | |
|
57 | 0 | 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 | 0 | } |
68 | | |
69 | | /*! |
70 | | \brief Set DB row id |
71 | | |
72 | | \param iRowId row id to be set |
73 | | */ |
74 | | void VFKFeatureSQLite::SetRowId(int iRowId) |
75 | 4.07k | { |
76 | 4.07k | m_iRowId = iRowId; |
77 | 4.07k | } |
78 | | |
79 | | /*! |
80 | | \brief Finalize SQL statement |
81 | | */ |
82 | | void VFKFeatureSQLite::FinalizeSQL() |
83 | 14.9k | { |
84 | 14.9k | sqlite3_finalize(m_hStmt); |
85 | 14.9k | m_hStmt = nullptr; |
86 | 14.9k | } |
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 | | OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand) |
96 | 960 | { |
97 | 960 | VFKReaderSQLite *poReader = |
98 | 960 | cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader()); |
99 | 960 | sqlite3 *poDB = poReader->m_poDB; |
100 | | |
101 | 960 | int rc = sqlite3_prepare_v2(poDB, pszSQLCommand, -1, &m_hStmt, nullptr); |
102 | 960 | if (rc != SQLITE_OK) |
103 | 960 | { |
104 | 960 | CPLError(CE_Failure, CPLE_AppDefined, |
105 | 960 | "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n %s", |
106 | 960 | pszSQLCommand, sqlite3_errmsg(poDB)); |
107 | | |
108 | 960 | if (m_hStmt != nullptr) |
109 | 0 | { |
110 | 0 | FinalizeSQL(); |
111 | 0 | } |
112 | 960 | return OGRERR_FAILURE; |
113 | 960 | } |
114 | 0 | rc = sqlite3_step(m_hStmt); |
115 | 0 | if (rc != SQLITE_ROW) |
116 | 0 | { |
117 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
118 | 0 | "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszSQLCommand, |
119 | 0 | sqlite3_errmsg(poDB)); |
120 | |
|
121 | 0 | if (m_hStmt) |
122 | 0 | { |
123 | 0 | FinalizeSQL(); |
124 | 0 | } |
125 | |
|
126 | 0 | return OGRERR_FAILURE; |
127 | 0 | } |
128 | | |
129 | 0 | return OGRERR_NONE; |
130 | 0 | } |
131 | | |
132 | | /*! |
133 | | \brief VFKFeatureSQLite constructor (derived from VFKFeature) |
134 | | |
135 | | Read VFK feature from VFK file and insert it into DB |
136 | | */ |
137 | | 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 | 0 | { |
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 | | bool VFKFeatureSQLite::LoadGeometryPoint() |
155 | 1.86k | { |
156 | 1.86k | return false; |
157 | 1.86k | } |
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 | | bool VFKFeatureSQLite::LoadGeometryLineStringSBP() |
167 | 2.06k | { |
168 | 2.06k | return false; |
169 | 2.06k | } |
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 | | bool VFKFeatureSQLite::LoadGeometryLineStringHP() |
179 | 2.19k | { |
180 | 2.19k | return false; |
181 | 2.19k | } |
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 | | bool VFKFeatureSQLite::LoadGeometryPolygon() |
191 | 1.42k | { |
192 | 1.42k | return false; |
193 | 1.42k | } |
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 | | OGRErr VFKFeatureSQLite::LoadProperties(OGRFeature *poFeature) |
203 | 15.8k | { |
204 | 15.8k | sqlite3_stmt *hStmt = |
205 | 15.8k | cpl::down_cast<VFKDataBlockSQLite *>(m_poDataBlock)->m_hStmt; |
206 | 15.8k | if (hStmt == nullptr) |
207 | 960 | { |
208 | | /* random access */ |
209 | 960 | CPLString osSQL; |
210 | | |
211 | 960 | osSQL.Printf("SELECT * FROM %s WHERE rowid = %d", |
212 | 960 | m_poDataBlock->GetName(), m_iRowId); |
213 | 960 | if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE) |
214 | 960 | return OGRERR_FAILURE; |
215 | | |
216 | 0 | hStmt = m_hStmt; |
217 | 0 | } |
218 | 14.9k | else |
219 | 14.9k | { |
220 | | /* sequential access */ |
221 | 14.9k | VFKReaderSQLite *poReader = |
222 | 14.9k | cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader()); |
223 | 14.9k | if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE) |
224 | 0 | { |
225 | 0 | cpl::down_cast<VFKDataBlockSQLite *>(m_poDataBlock)->m_hStmt = |
226 | 0 | nullptr; |
227 | 0 | return OGRERR_FAILURE; |
228 | 0 | } |
229 | 14.9k | } |
230 | | |
231 | 14.9k | int nPropertyCount = m_poDataBlock->GetPropertyCount(); |
232 | 171k | for (int iField = 0; iField < nPropertyCount; iField++) |
233 | 157k | { |
234 | 157k | if (sqlite3_column_type(hStmt, iField) == |
235 | 157k | SQLITE_NULL) /* skip null values */ |
236 | 36.9k | continue; |
237 | 120k | OGRFieldType fType = |
238 | 120k | poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType(); |
239 | 120k | switch (fType) |
240 | 120k | { |
241 | 37.7k | case OFTInteger: |
242 | 37.7k | poFeature->SetField(iField, sqlite3_column_int(hStmt, iField)); |
243 | 37.7k | break; |
244 | 52.4k | case OFTInteger64: |
245 | 52.4k | poFeature->SetField(iField, |
246 | 52.4k | sqlite3_column_int64(hStmt, iField)); |
247 | 52.4k | break; |
248 | 11.0k | case OFTReal: |
249 | 11.0k | poFeature->SetField(iField, |
250 | 11.0k | sqlite3_column_double(hStmt, iField)); |
251 | 11.0k | break; |
252 | 18.8k | default: |
253 | 18.8k | poFeature->SetField( |
254 | 18.8k | iField, (const char *)sqlite3_column_text(hStmt, iField)); |
255 | 18.8k | break; |
256 | 120k | } |
257 | 120k | } |
258 | | |
259 | 14.9k | if (m_poDataBlock->GetReader()->HasFileField()) |
260 | 0 | { |
261 | | /* open option FILE_FIELD=YES specified, append extra |
262 | | * attribute */ |
263 | 0 | poFeature->SetField( |
264 | 0 | nPropertyCount, |
265 | 0 | CPLGetFilename(m_poDataBlock->GetReader()->GetFilename())); |
266 | 0 | } |
267 | | |
268 | 14.9k | FinalizeSQL(); |
269 | | |
270 | 14.9k | return OGRERR_NONE; |
271 | 14.9k | } |