Coverage Report

Created: 2025-11-15 08:43

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
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
}