Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
15.4k
    : IVFKFeature(poDataBlock), m_iRowId(iRowId), m_hStmt(nullptr)
46
15.4k
{
47
15.4k
    m_nFID = nFID;
48
15.4k
}
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
3.71k
{
76
3.71k
    m_iRowId = iRowId;
77
3.71k
}
78
79
/*!
80
  \brief Finalize SQL statement
81
*/
82
void VFKFeatureSQLite::FinalizeSQL()
83
12.3k
{
84
12.3k
    sqlite3_finalize(m_hStmt);
85
12.3k
    m_hStmt = nullptr;
86
12.3k
}
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
856
{
97
856
    VFKReaderSQLite *poReader =
98
856
        cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader());
99
856
    sqlite3 *poDB = poReader->m_poDB;
100
101
856
    int rc = sqlite3_prepare_v2(poDB, pszSQLCommand, -1, &m_hStmt, nullptr);
102
856
    if (rc != SQLITE_OK)
103
856
    {
104
856
        CPLError(CE_Failure, CPLE_AppDefined,
105
856
                 "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s",
106
856
                 pszSQLCommand, sqlite3_errmsg(poDB));
107
108
856
        if (m_hStmt != nullptr)
109
0
        {
110
0
            FinalizeSQL();
111
0
        }
112
856
        return OGRERR_FAILURE;
113
856
    }
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
318
{
156
318
    return false;
157
318
}
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
1.26k
{
168
1.26k
    return false;
169
1.26k
}
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.18k
{
180
2.18k
    return false;
181
2.18k
}
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
975
{
192
975
    return false;
193
975
}
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
13.2k
{
204
13.2k
    sqlite3_stmt *hStmt =
205
13.2k
        cpl::down_cast<VFKDataBlockSQLite *>(m_poDataBlock)->m_hStmt;
206
13.2k
    if (hStmt == nullptr)
207
856
    {
208
        /* random access */
209
856
        CPLString osSQL;
210
211
856
        osSQL.Printf("SELECT * FROM %s WHERE rowid = %d",
212
856
                     m_poDataBlock->GetName(), m_iRowId);
213
856
        if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
214
856
            return OGRERR_FAILURE;
215
216
0
        hStmt = m_hStmt;
217
0
    }
218
12.3k
    else
219
12.3k
    {
220
        /* sequential access */
221
12.3k
        VFKReaderSQLite *poReader =
222
12.3k
            cpl::down_cast<VFKReaderSQLite *>(m_poDataBlock->GetReader());
223
12.3k
        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
12.3k
    }
230
231
12.3k
    int nPropertyCount = m_poDataBlock->GetPropertyCount();
232
136k
    for (int iField = 0; iField < nPropertyCount; iField++)
233
123k
    {
234
123k
        if (sqlite3_column_type(hStmt, iField) ==
235
123k
            SQLITE_NULL) /* skip null values */
236
31.0k
            continue;
237
92.6k
        OGRFieldType fType =
238
92.6k
            poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
239
92.6k
        switch (fType)
240
92.6k
        {
241
24.7k
            case OFTInteger:
242
24.7k
                poFeature->SetField(iField, sqlite3_column_int(hStmt, iField));
243
24.7k
                break;
244
42.7k
            case OFTInteger64:
245
42.7k
                poFeature->SetField(iField,
246
42.7k
                                    sqlite3_column_int64(hStmt, iField));
247
42.7k
                break;
248
5.37k
            case OFTReal:
249
5.37k
                poFeature->SetField(iField,
250
5.37k
                                    sqlite3_column_double(hStmt, iField));
251
5.37k
                break;
252
19.7k
            default:
253
19.7k
                poFeature->SetField(
254
19.7k
                    iField, (const char *)sqlite3_column_text(hStmt, iField));
255
19.7k
                break;
256
92.6k
        }
257
92.6k
    }
258
259
12.3k
    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
12.3k
    FinalizeSQL();
269
270
12.3k
    return OGRERR_NONE;
271
12.3k
}