Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#if SQLITE_VERSION_NUMBER < 3040000
16typedef const char *sqlite3_filename;
17#endif
18
19namespace {
20struct Vfs : sqlite3_vfs {
21 sqlite3_vfs *pVfs;
22 sqlite3_io_methods ioMethods;
23};
24
25struct File : sqlite3_file {
26 class QtFile : public QFile {
27 public:
28 QtFile(const QString &name, bool removeOnClose)
29 : QFile(name)
30 , removeOnClose(removeOnClose)
31 {}
32
33 ~QtFile() override
34 {
35 if (removeOnClose)
36 remove();
37 }
38 private:
39 bool removeOnClose;
40 };
41 QtFile *pFile;
42};
43
44
45int xClose(sqlite3_file *sfile)
46{
47 auto file = static_cast<File *>(sfile);
48 delete file->pFile;
49 file->pFile = nullptr;
50 return SQLITE_OK;
51}
52
53int xRead(sqlite3_file *sfile, void *ptr, int iAmt, sqlite3_int64 iOfst)
54{
55 auto file = static_cast<File *>(sfile);
56 if (!file->pFile->seek(iOfst))
57 return SQLITE_IOERR_READ;
58
59 auto sz = file->pFile->read(static_cast<char *>(ptr), iAmt);
60 if (sz < iAmt) {
61 memset(static_cast<char *>(ptr) + sz, 0, size_t(iAmt - sz));
62 return SQLITE_IOERR_SHORT_READ;
63 }
64 return SQLITE_OK;
65}
66
67int xWrite(sqlite3_file *sfile, const void *data, int iAmt, sqlite3_int64 iOfst)
68{
69 auto file = static_cast<File *>(sfile);
70 if (!file->pFile->seek(iOfst))
71 return SQLITE_IOERR_SEEK;
72 return file->pFile->write(reinterpret_cast<const char*>(data), iAmt) == iAmt ? SQLITE_OK : SQLITE_IOERR_WRITE;
73}
74
75int xTruncate(sqlite3_file *sfile, sqlite3_int64 size)
76{
77 auto file = static_cast<File *>(sfile);
78 return file->pFile->resize(size) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
79}
80
81int xSync(sqlite3_file *sfile, int /*flags*/)
82{
83 static_cast<File *>(sfile)->pFile->flush();
84 return SQLITE_OK;
85}
86
87int xFileSize(sqlite3_file *sfile, sqlite3_int64 *pSize)
88{
89 auto file = static_cast<File *>(sfile);
90 *pSize = file->pFile->size();
91 return SQLITE_OK;
92}
93
94// No lock/unlock for QFile, QLockFile doesn't work for me
95
96int xLock(sqlite3_file *, int) { return SQLITE_OK; }
97
98int xUnlock(sqlite3_file *, int) { return SQLITE_OK; }
99
100int xCheckReservedLock(sqlite3_file *, int *pResOut)
101{
102 *pResOut = 0;
103 return SQLITE_OK;
104}
105
106int xFileControl(sqlite3_file *, int, void *) { return SQLITE_NOTFOUND; }
107
108int xSectorSize(sqlite3_file *)
109{
110 return 4096;
111}
112
113int xDeviceCharacteristics(sqlite3_file *)
114{
115 return 0; // no SQLITE_IOCAP_XXX
116}
117
118int xOpen(sqlite3_vfs *svfs, sqlite3_filename zName, sqlite3_file *sfile,
119 int flags, int *pOutFlags)
120{
121 auto vfs = static_cast<Vfs *>(svfs);
122 auto file = static_cast<File *>(sfile);
123 memset(file, 0, sizeof(File));
124 QIODeviceBase::OpenMode mode = QIODeviceBase::NotOpen;
125 if (!zName || (flags & SQLITE_OPEN_MEMORY))
126 return SQLITE_PERM;
127 if ((flags & SQLITE_OPEN_READONLY) &&
128 !(flags & SQLITE_OPEN_READWRITE) &&
129 !(flags & SQLITE_OPEN_CREATE) &&
130 !(flags & SQLITE_OPEN_DELETEONCLOSE)) {
132 } else {
133 /*
134 ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
135 ** with the [SQLITE_OPEN_CREATE] flag, which are both directly
136 ** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
137 ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
138 ** SQLITE_OPEN_CREATE, is used to indicate that file should always
139 ** be created, and that it is an error if it already exists.
140 ** It is <i>not</i> used to indicate the file should be opened
141 ** for exclusive access.
142 */
143 if ((flags & SQLITE_OPEN_CREATE) && (flags & SQLITE_OPEN_EXCLUSIVE))
145
146 if (flags & SQLITE_OPEN_READWRITE)
148 }
149
150 file->pMethods = &vfs->ioMethods;
151 file->pFile = new File::QtFile(QString::fromUtf8(zName), bool(flags & SQLITE_OPEN_DELETEONCLOSE));
152 if (!file->pFile->open(mode))
153 return SQLITE_CANTOPEN;
154 if (pOutFlags)
155 *pOutFlags = flags;
156
157 return SQLITE_OK;
158}
159
160int xDelete(sqlite3_vfs *, const char *zName, int)
161{
162 return QFile::remove(QString::fromUtf8(zName)) ? SQLITE_OK : SQLITE_ERROR;
163}
164
165int xAccess(sqlite3_vfs */*svfs*/, const char *zName, int flags, int *pResOut)
166{
167 *pResOut = 0;
168 switch (flags) {
169 case SQLITE_ACCESS_EXISTS:
170 case SQLITE_ACCESS_READ:
171 *pResOut = QFile::exists(QString::fromUtf8(zName));
172 break;
173 default:
174 break;
175 }
176 return SQLITE_OK;
177}
178
179int xFullPathname(sqlite3_vfs *, const char *zName, int nOut, char *zOut)
180{
181 if (!zName)
182 return SQLITE_ERROR;
183
184 int i = 0;
185 for (;zName[i] && i < nOut; ++i)
186 zOut[i] = zName[i];
187
188 if (i >= nOut)
189 return SQLITE_ERROR;
190
191 zOut[i] = '\0';
192 return SQLITE_OK;
193}
194
195int xRandomness(sqlite3_vfs *svfs, int nByte, char *zOut)
196{
197 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
198 return vfs->xRandomness(vfs, nByte, zOut);
199}
200
201int xSleep(sqlite3_vfs *svfs, int microseconds)
202{
203 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
204 return vfs->xSleep(vfs, microseconds);
205}
206
207int xCurrentTime(sqlite3_vfs *svfs, double *zOut)
208{
209 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
210 return vfs->xCurrentTime(vfs, zOut);
211}
212
213int xGetLastError(sqlite3_vfs *, int, char *)
214{
215 return 0;
216}
217
218int xCurrentTimeInt64(sqlite3_vfs *svfs, sqlite3_int64 *zOut)
219{
220 auto vfs = static_cast<Vfs *>(svfs)->pVfs;
221 return vfs->xCurrentTimeInt64(vfs, zOut);
222}
223} // namespace {
224
226{
227 static Vfs vfs;
228 memset(&vfs, 0, sizeof(Vfs));
229 vfs.iVersion = 1;
230 vfs.szOsFile = sizeof(File);
231 vfs.mxPathname = PATH_MAX;
232 vfs.zName = "QtVFS";
233 vfs.xOpen = &xOpen;
234 vfs.xDelete = &xDelete;
235 vfs.xAccess = &xAccess;
236 vfs.xFullPathname = &xFullPathname;
237 vfs.xRandomness = &xRandomness;
238 vfs.xSleep = &xSleep;
239 vfs.xCurrentTime = &xCurrentTime;
240 vfs.xGetLastError = &xGetLastError;
241 vfs.xCurrentTimeInt64 = &xCurrentTimeInt64;
242 vfs.pVfs = sqlite3_vfs_find(nullptr);
243 vfs.ioMethods.iVersion = 1;
244 vfs.ioMethods.xClose = &xClose;
245 vfs.ioMethods.xRead = &xRead;
246 vfs.ioMethods.xWrite = &xWrite;
247 vfs.ioMethods.xTruncate = &xTruncate;
248 vfs.ioMethods.xSync = &xSync;
249 vfs.ioMethods.xFileSize = &xFileSize;
250 vfs.ioMethods.xLock = &xLock;
251 vfs.ioMethods.xUnlock = &xUnlock;
252 vfs.ioMethods.xCheckReservedLock = &xCheckReservedLock;
253 vfs.ioMethods.xFileControl = &xFileControl;
254 vfs.ioMethods.xSectorSize = &xSectorSize;
255 vfs.ioMethods.xDeviceCharacteristics = &xDeviceCharacteristics;
256
257 sqlite3_vfs_register(&vfs, 0);
258}
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
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
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:1179
bool resize(qint64 sz) override
\reimp
Definition qfile.cpp:1103
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:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
static ControlElement< T > * ptr(QWidget *widget)
GLenum mode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLbitfield flags
GLuint name
const char * sqlite3_filename
void register_qt_vfs()
#define PATH_MAX
decltype(openFileForWriting({})) File
Definition main.cpp:76
QFile file
[0]
settings remove("monkey")