Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsql_sqlite_vfs.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsql_sqlite_vfs_p.h"
5
6#include <QFile>
7
8#include <limits.h> // defines PATH_MAX on unix
9#include <sqlite3.h>
10#include <stdio.h> // defines FILENAME_MAX everywhere
11
12#ifndef PATH_MAX
13# define PATH_MAX FILENAME_MAX
14#endif
15
16namespace {
17struct Vfs : sqlite3_vfs {
18 sqlite3_vfs *pVfs;
19 sqlite3_io_methods ioMethods;
20};
21
22struct File : sqlite3_file {
23 class QtFile : public QFile {
24 public:
25 QtFile(const QString &name, bool removeOnClose)
26 : QFile(name)
27 , removeOnClose(removeOnClose)
28 {}
29
30 ~QtFile() override
31 {
32 if (removeOnClose)
33 remove();
34 }
35 private:
36 bool removeOnClose;
37 };
38 QtFile *pFile;
39};
40
41
42int xClose(sqlite3_file *sfile)
43{
44 auto file = static_cast<File *>(sfile);
45 delete file->pFile;
46 file->pFile = nullptr;
47 return SQLITE_OK;
48}
49
50int xRead(sqlite3_file *sfile, void *ptr, int iAmt, sqlite3_int64 iOfst)
51{
52 auto file = static_cast<File *>(sfile);
53 if (!file->pFile->seek(iOfst))
54 return SQLITE_IOERR_READ;
55
56 auto sz = file->pFile->read(static_cast<char *>(ptr), iAmt);
57 if (sz < iAmt) {
58 memset(static_cast<char *>(ptr) + sz, 0, size_t(iAmt - sz));
59 return SQLITE_IOERR_SHORT_READ;
60 }
61 return SQLITE_OK;
62}
63
64int xWrite(sqlite3_file *sfile, const void *data, int iAmt, sqlite3_int64 iOfst)
65{
66 auto file = static_cast<File *>(sfile);
67 if (!file->pFile->seek(iOfst))
68 return SQLITE_IOERR_SEEK;
69 return file->pFile->write(reinterpret_cast<const char*>(data), iAmt) == iAmt ? SQLITE_OK : SQLITE_IOERR_WRITE;
70}
71
72int xTruncate(sqlite3_file *sfile, sqlite3_int64 size)
73{
74 auto file = static_cast<File *>(sfile);
75 return file->pFile->resize(size) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
76}
77
78int xSync(sqlite3_file *sfile, int /*flags*/)
79{
80 static_cast<File *>(sfile)->pFile->flush();
81 return SQLITE_OK;
82}
83
84int xFileSize(sqlite3_file *sfile, sqlite3_int64 *pSize)
85{
86 auto file = static_cast<File *>(sfile);
87 *pSize = file->pFile->size();
88 return SQLITE_OK;
89}
90
91// No lock/unlock for QFile, QLockFile doesn't work for me
92
93int xLock(sqlite3_file *, int) { return SQLITE_OK; }
94
95int xUnlock(sqlite3_file *, int) { return SQLITE_OK; }
96
97int xCheckReservedLock(sqlite3_file *, int *pResOut)
98{
99 *pResOut = 0;
100 return SQLITE_OK;
101}
102
103int xFileControl(sqlite3_file *, int, void *) { return SQLITE_NOTFOUND; }
104
105int xSectorSize(sqlite3_file *)
106{
107 return 4096;
108}
109
110int xDeviceCharacteristics(sqlite3_file *)
111{
112 return 0; // no SQLITE_IOCAP_XXX
113}
114
115int xOpen(sqlite3_vfs *svfs, sqlite3_filename zName, sqlite3_file *sfile,
116 int flags, int *pOutFlags)
117{
118 auto vfs = static_cast<Vfs *>(svfs);
119 auto file = static_cast<File *>(sfile);
120 memset(file, 0, sizeof(File));
121 QIODeviceBase::OpenMode mode = QIODeviceBase::NotOpen;
122 if (!zName || (flags & SQLITE_OPEN_MEMORY))
123 return SQLITE_PERM;
124 if ((flags & SQLITE_OPEN_READONLY) &&
125 !(flags & SQLITE_OPEN_READWRITE) &&
126 !(flags & SQLITE_OPEN_CREATE) &&
127 !(flags & SQLITE_OPEN_DELETEONCLOSE)) {
129 } else {
130 /*
131 ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
132 ** with the [SQLITE_OPEN_CREATE] flag, which are both directly
133 ** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
134 ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
135 ** SQLITE_OPEN_CREATE, is used to indicate that file should always
136 ** be created, and that it is an error if it already exists.
137 ** It is <i>not</i> used to indicate the file should be opened
138 ** for exclusive access.
139 */
140 if ((flags & SQLITE_OPEN_CREATE) && (flags & SQLITE_OPEN_EXCLUSIVE))
142
143 if (flags & SQLITE_OPEN_READWRITE)
145 }
146
147 file->pMethods = &vfs->ioMethods;
148 file->pFile = new File::QtFile(QString::fromUtf8(zName), bool(flags & SQLITE_OPEN_DELETEONCLOSE));
149 if (!file->pFile->open(mode))
150 return SQLITE_CANTOPEN;
151 if (pOutFlags)
152 *pOutFlags = flags;
153
154 return SQLITE_OK;
155}
156
157int xDelete(sqlite3_vfs *, const char *zName, int)
158{
159 return QFile::remove(QString::fromUtf8(zName)) ? SQLITE_OK : SQLITE_ERROR;
160}
161
162int xAccess(sqlite3_vfs */*svfs*/, const char *zName, int flags, int *pResOut)
163{
164 *pResOut = 0;
165 switch (flags) {
166 case SQLITE_ACCESS_EXISTS:
167 case SQLITE_ACCESS_READ:
168 *pResOut = QFile::exists(QString::fromUtf8(zName));
169 break;
170 default:
171 break;
172 }
173 return SQLITE_OK;
174}
175
176int xFullPathname(sqlite3_vfs *, const char *zName, int nOut, char *zOut)
177{
178 if (!zName)
179 return SQLITE_ERROR;
180
181 int i = 0;
182 for (;zName[i] && i < nOut; ++i)
183 zOut[i] = zName[i];
184
185 if (i >= nOut)
186 return SQLITE_ERROR;
187
188 zOut[i] = '\0';
189 return SQLITE_OK;
190}
191
192int xRandomness(sqlite3_vfs *svfs, int nByte, char *zOut)
193{
194 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
195 return vfs->xRandomness(vfs, nByte, zOut);
196}
197
198int xSleep(sqlite3_vfs *svfs, int microseconds)
199{
200 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
201 return vfs->xSleep(vfs, microseconds);
202}
203
204int xCurrentTime(sqlite3_vfs *svfs, double *zOut)
205{
206 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
207 return vfs->xCurrentTime(vfs, zOut);
208}
209
210int xGetLastError(sqlite3_vfs *, int, char *)
211{
212 return 0;
213}
214
215int xCurrentTimeInt64(sqlite3_vfs *svfs, sqlite3_int64 *zOut)
216{
217 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
218 return vfs->xCurrentTimeInt64(vfs, zOut);
219}
220} // namespace {
221
223{
224 static Vfs vfs;
225 memset(&vfs, 0, sizeof(Vfs));
226 vfs.iVersion = 1;
227 vfs.szOsFile = sizeof(File);
228 vfs.mxPathname = PATH_MAX;
229 vfs.zName = "QtVFS";
230 vfs.xOpen = &xOpen;
231 vfs.xDelete = &xDelete;
232 vfs.xAccess = &xAccess;
233 vfs.xFullPathname = &xFullPathname;
234 vfs.xRandomness = &xRandomness;
235 vfs.xSleep = &xSleep;
236 vfs.xCurrentTime = &xCurrentTime;
237 vfs.xGetLastError = &xGetLastError;
238 vfs.xCurrentTimeInt64 = &xCurrentTimeInt64;
239 vfs.pVfs = sqlite3_vfs_find(nullptr);
240 vfs.ioMethods.iVersion = 1;
241 vfs.ioMethods.xClose = &xClose;
242 vfs.ioMethods.xRead = &xRead;
243 vfs.ioMethods.xWrite = &xWrite;
244 vfs.ioMethods.xTruncate = &xTruncate;
245 vfs.ioMethods.xSync = &xSync;
246 vfs.ioMethods.xFileSize = &xFileSize;
247 vfs.ioMethods.xLock = &xLock;
248 vfs.ioMethods.xUnlock = &xUnlock;
249 vfs.ioMethods.xCheckReservedLock = &xCheckReservedLock;
250 vfs.ioMethods.xFileControl = &xFileControl;
251 vfs.ioMethods.xSectorSize = &xSectorSize;
252 vfs.ioMethods.xDeviceCharacteristics = &xDeviceCharacteristics;
253
254 sqlite3_vfs_register(&vfs, 0);
255}
bool seek(qint64 offset) override
For random-access devices, this function sets the current position to pos, returning true on success,...
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
bool remove()
Removes the file specified by fileName().
Definition qfile.cpp:419
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
qint64 size() const override
\reimp
Definition qfile.cpp:1156
bool resize(qint64 sz) override
\reimp
Definition qfile.cpp:1080
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
static ControlElement< T > * ptr(QWidget *widget)
GLenum mode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
void register_qt_vfs()
#define PATH_MAX
QFile file
[0]
settings remove("monkey")