SQLite open performance-issue - c++

I am writing a desktop application under windows,
I am using sqlite to store information,
I created a db with index on string column, insert a lot of informations, the db size about 16M,
If I restart Windows, and open my application.
It takes about 9-10 secodes to open the sqlite db.
The code is as follow:
int nRet;
nRet = sqlite3_open16(szFile, &mpDB);
if (nRet != SQLITE_OK)
{
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPCTSTR)szError, DONT_DELETE_MSG);
}
setBusyTimeout(mnBusyTimeoutMs);
Is it possible to accelerate it ?
Many Thanks!

YOu can use sqlite3 command line utility to check your database.
Or you can recreate your tables with data (dump/restore).

Related

SQLITE_CANTOPEN - windows c++

I am trying to create an Sqlite database in the selected folder but can`t do this.
Operating System - Windows, editor - Visual studio, progect encoding is unicode. Encoding of input string with database connection unknown. Language - C++
The problem:
I can't create database when I use following connection string: file:C:/Users/Public/Desktop/testDb.sqlite
I am always getting error 14 (SQLITE_CANTOPEN).
I use following function to create database:
CSqliteManager::CSqliteManager(const char* dbName)
{
db = nullptr;
int rc = sqlite3_open(dbName, &db);
if (rc != SQLITE_OK)
{
db = nullptr;
}
}
How should me change connection string to create database fo the sollowing pass:
C://Users/Public/Desctop/MyBD.sqlite
You can't use URI style filenames with sqlite3_open() as they're disabled by default (I'm assuming you didn't enable them globally). Instead you need to use sqlite3_open_v2() with the appropriate option (SQLITE_OPEN_URI). Details and more details.
(Or just not use a URI, of course)

Is it possible to switch READ_ONLY database to WAL journaling mode in sqlite3

I have opened a database connection in READ_ONLY mode. Is it possible to switch the database connection to journaling mode = WAL in runtime?
I am using below code to switch to WAL mode
sqlite3* ppDb;
int res = sqlite3_open_v2("test.db",&ppDb,SQLITE_OPEN_READONLY,NULL,NULL, 0, NULL);
if(SQLITE_OK==res)
{
rc = sqlite3_exec(m_dbHandle, "PRAGMA zipvfs_journal_mode=wal;", NULL,NULL, NULL))
}
I am getting Disk I/O error after sqlite3_exec statement.
Can anyone please help me with this.
Thanks in advance.
The documentation says:
It is not possible to open read-only WAL databases. The opening process must have write privileges for "-shm" wal-index shared memory file associated with the database, if that file exists, or else write access on the directory containing the database file if the "-shm" file does not exist.
The same write privileges are needed if you re-open a database in WAL mode.

C++ Qt sql lite database connection issue

The following code is used by me to connect to a database using Qt IDE. And if it successfully connects to the database Connected to db is printed on a label. But the issue is if I even given a wrong database path it returns Connected to db on the label how can i correct this issue?
QSqlDatabase mydb= QSqlDatabase::addDatabase("QSQLITE");
mydb.setDatabaseName("x");
if(!mydb.open()){
ui->label->setText("Failed to open the db");
}
else{
ui->label->setText("Connected to db");
}
Even though in the above code i put "x" which is not a valid database path I get "Connected to db' in the label when I run the program!
How can i correct this issue?
Qt uses as SQLite backend uses the sqlite library, so you will use one of the functions to open the database:
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
According to the docs:
These routines open an SQLite database file as specified by the
filename argument. The filename argument is interpreted as UTF-8 for
sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
order for sqlite3_open16(). A database connection handle is usually
returned in *ppDb, even if an error occurs. The only exception is that
if SQLite is unable to allocate memory to hold the sqlite3 object, a
NULL will be written into *ppDb instead of a pointer to the sqlite3
object. If the database is opened (and/or created) successfully, then
SQLITE_OK is returned. Otherwise an error code is returned. The
sqlite3_errmsg() or sqlite3_errmsg16() routines can be used to obtain
an English language description of the error following a failure of
any of the sqlite3_open() routines.
From which we conclude that if the database does not exist this will create it, it will only generate the error in creating it if there are problems to allocate memory.

Creating a registry key - access denied

Hi I am trying to create a registry key in C++ but I keep getting the error 5 which googling told me it was access denied but I don't know to do get the correct privileges. I'm using windows 7 and here's my code. Thanks
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR szValueBuf = NULL;
char szProductName[MAX_PATH];
LPSECURITY_ATTRIBUTES lpsa;
HKEY hOrchKey;
DWORD dwOpenStatus,
dwType;
char szProuductKey[MAX_PATH];
hr = WcaInitialize(hInstall, "CreateProductKey");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
if (!(lpsa = default_sa()))
return FALSE;
hr = WcaGetProperty(L"PRODUCTNAME",&szValueBuf);
ExitOnFailure(hr, "failed to get Product Name");
wcstombs(szProductName, szValueBuf, 260);
sprintf(szProuductKey,"SOFTWARE\\Company\\%s",szProductName);
// Open the registery Orchestrator key
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
szProuductKey,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE,
lpsa,
&hOrchKey,
&dwOpenStatus) != ERROR_SUCCESS )
return FALSE;
OS_RegCloseKey(hOrchKey);
return TRUE;
Run as administrator to run it with elevated access.
You must access the registry key HKEY_LOCAL_MACHINE as administrator in order to edit values. (e.g. If you wanted to edit the key via the Registry Editor application, then you would have to right click and select "run as administrator") Since you want to write the values in code, so you need to set your compiler to have administrator rights when you run it. In Visual Studio 2008 this can be done in the Properties Page of your solution, you set it to run as admin.
Heres how to do it; Right click your solution in the Solution Explorer and select Properties; Go to Configuration Properties->Linker->Manifest File; Set UAC Execution Level as "requireAdministrator".
Next time you hit run, it should prompt you to open it as admin, and then it'll allow you to change the key. I'm not sure how to do this with other compilers, but it should be relatively the same. However, it will always ask you for admin rights, even in the release, not ideal for most programs. If this is an installer or something, then Id say that'd be fine, but if this is an app that'll be run a lot, Id suggest using HKEY_LOCAL_USER, it doesn't require admin rights. I recently went through all that malarkey and the registry is a bitch to get right, so I'd suggest avoiding it as much as possible!
Hope that helps!

How can I create a local database inside a Microsoft Visual C++ 2010 Express project?

How can I create a local database inside a Microsoft Visual C++ 2010 Express project?
I can't find this simple answer in the web. The only answer I've found is for Visual Studio: using project > add new item > local database. But this option isn't available in Visual c++ 2010 Express edition.
I tried installing "Microsoft SQL Server Compact 4" and "Microsoft SQL Server Denali", and updating "Microsoft Visual C++ 2010 Express" from "Windows Update".
Ok, I got a solution at last. Regrettably I must answer my own question...
I used SQLite library (http://www.sqlite.org/). It was a little complicated because the sqlite documentation is a bit vague, but I did as follows:
Download sqlitedll*.zip - extract .def and .dll files somewhere.
Generate the lib file with a command like "c:\program
files\micros~1\vc98\bin\lib" /def:sqlite3.def". Do that from a command
prompt, in the directory with the .def file in, with the appropriate
path to your lib.exe. You may need to run vcvars32.bat first, which is
also in the bin directory. Copy the resulting .lib to an appropriate
place, and set that as a library directory in VC++. (Or do it on a
per-project basis.)
Download the sqlite-source*.zip file, and extract the sqlite3.h file
from within to a suitable directory. Set that as an include directory
in VC++. (Again, you could do it on a per-project basis.)
In your project, #include as required, add sqlite3.lib
to your project, copy the sqlite3.dll to your executable's directory
or working directory, and you should be ready to go.
Then, is easy to use no-out queries, but if you want to use a SQL "SELECT" for example, you could use this code:
std::string queries;
// A prepered statement for fetching tables
sqlite3_stmt *stmt;
// Create a handle for database connection, create a pointer to sqlite3
sqlite3 *handle;
// try to create the database. If it doesnt exist, it would be created
// pass a pointer to the pointer to sqlite3, in short sqlite3**
int retval = sqlite3_open("local.db",&handle);
// If connection failed, handle returns NULL
if(retval){
System::Windows::Forms::MessageBox::Show("Database connection failed");
return;
}
// Create the SQL query for creating a table
char create_table[100] = "CREATE TABLE IF NOT EXISTS users (uname TEXT PRIMARY KEY,pass TEXT NOT NULL,activated INTEGER)";
// Execute the query for creating the table
retval = sqlite3_exec(handle,create_table,0,0,0);
// Insert first row and second row
queries = "INSERT INTO users VALUES('manish','manish',1)";
retval = sqlite3_exec(handle,queries.c_str(),0,0,0);
queries = "INSERT INTO users VALUES('mehul','pulsar',0)";
retval = sqlite3_exec(handle,queries.c_str(),0,0,0);
// select those rows from the table
queries = "SELECT * from users";
retval = sqlite3_prepare_v2(handle,queries.c_str(),-1,&stmt,0);
if(retval){
System::Windows::Forms::MessageBox::Show("Selecting data from DB Failed");
return ;
}
// Read the number of rows fetched
int cols = sqlite3_column_count(stmt);
while(1){
// fetch a row’s status
retval = sqlite3_step(stmt);
if(retval == SQLITE_ROW){
// SQLITE_ROW means fetched a row
// sqlite3_column_text returns a const void* , typecast it to const char*
for(int col=0 ; col<cols;col++){
const char *val = (const char*)sqlite3_column_text(stmt,col);
System::Windows::Forms::MessageBox::Show(stdstr2systemstr(sqlite3_column_name(stmt,col))+" = "+stdstr2systemstr(val));
}
}
else
if(retval == SQLITE_DONE){
// All rows finished
System::Windows::Forms::MessageBox::Show("All rows fetched");
break;
}
else{
// Some error encountered
System::Windows::Forms::MessageBox::Show("Some error encountered");
return ;
}
}
// Close the handle to free memory
sqlite3_close(handle);
I expect this info be useful!
Sources:
http://www.gamedev.net/topic/332251-sqlite3-and-visual-c/page_p_3157685#entry3157685
http://milky.manishsinha.net/2009/03/30/sqlite-with-c/