SQLITE_CANTOPEN - windows c++ - 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)

Related

Cannot make connection to SQL Server via ODBC

In the past, I have used ADO to access SQL Server, the connection string for the ADO connection object is:
Provider=sqloledb;Data Source=MYPC;Integrated Security=SSPI;
where MYPC is the name of my computer, and SQL Server is installed on my computer as the default instance.
The above connection string works well.
However, now it is said that ADO is outdated and ODBC is recommended again by Microsoft (see https://blogs.msdn.microsoft.com/sqlnativeclient/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access/ ), so I have to modify my code to use ODBC instead.
So I changed the connection to SQL Server to the following code:
CDatabase Database;
// Provider=sqloledb;Data Source=MYPC;Integrated Security=SSPI;
Database.OpenEx(_T("Driver = {SQL Native Client}; Server = MYPC; Trusted_Connection = yes;"), CDatabase::noOdbcDialog);
Database.ExecuteSQL(_T("create database [MyDB2019] on primary (name=[MyDB2019_File],filename='F:\\MyDB2019.mdf')"));
Database.Close();
However, this code does not work. After executing Database.OpenEx, there will be a CDBException indicating
Data source name not found and no default driver specified.
Why?
Note: I am using Visual C++ 2008 and ADO
The error/exception is pointing to the problem (albeit it seems a bit generic at first).
"Data source name not found and no default driver specified"
Data source name not found --> You did not specify a DSN, you do not
want to use a DSN, ignore this part
.
and no default driver specified --> You intend to use a driver, so this part of the error most likely applies to you.
The connection string appears syntactically correct: "Driver={Driver Name}...", so the next
step is to check whether the driver you try to use, named SQL Native Client, exists
on your machine.
"SQL Native Client" was/is the driver name for SQL Server 2005.
From SQL2008 the driver name got a version descriptor.
Driver={SQL Native Client} ,sql2005
Driver={SQL Server Native Client 10.0} ,sql2008
Driver={SQL Server Native Client 11.0} ,sql2012 and later
Driver={ODBC Driver 11 for SQL Server} ,sql2012 and later, odbc appears in the name
Driver={ODBC Driver 13 for SQL Server}
Driver={ODBC Driver 17 for SQL Server}
An easy way to find the installed 'SQL Native' and 'ODBC Driver for SQL Server' drivers on your machine, would be to run the ODBC Data Source Administrator. Type Odbc data sources in your search box or odbcad32.exe in the command/address bar (for 64bit: %windir%\system32\odbcad32.exe)
When in ODBC Data Source Administrator, switch to the Drivers tab and there you will find all the available/installed drivers, at your disposal.
Here is a powershell script that opens a connection to localhost using odbc. Adjust accordingly to your installed driver(s)
cls
$conn = new-object system.data.odbc.odbcconnection
$conn.connectionstring =
# all these installed on my pc and working
#"Driver={SQL Server Native Client 11.0};Server=localhost; Database=master;Trusted_Connection=yes;"
#"Driver={SQL Server};Server=localhost; Database=master;Trusted_Connection=yes;"
#"Driver={ODBC Driver 11 for SQL Server};Server=localhost; Database=master;Trusted_Connection=yes;"
"Driver={ODBC Driver 17 for SQL Server};Server=localhost; Database=master;Trusted_Connection=yes;"
$conn.Open()
$conn.State
$conn.Close();
..and an mfc button
void CMFCDBTestDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CDatabase database;
CString connectionstring = _T("Driver={SQL Server Native Client 10.0};Server=localhost;Trusted_Connection=yes;");
CString messagetext;
TRY{
//database.Open(NULL, FALSE, FALSE, connectionstring, FALSE); //ok
database.OpenEx(connectionstring, CDatabase::noOdbcDialog); //ok
if (database.IsOpen()){
messagetext = _T("open, database:") + database.GetDatabaseName();
database.Close();
}
}CATCH(CDBException, e) {
messagetext = _T("Database error: ")+e->m_strError;
}
END_CATCH;
AfxMessageBox(messagetext, 0, 0);
}
Create a file with udl extension. Example: test.udl
Double click the file. Use the GUI to connect to your database. Once done, open the UDL file using notepad and extract the connection string.
See https://www.dmxzone.com/go/312/how-to-generate-an-ado-connection-string/
The problem comes from the extra spaces in the connection string, after removing extra spaces from:
"Driver = {SQL Native Client}; Server = MYPC; Trusted_Connection = yes;"
to(and change the driver name as well):
"Driver={SQL Server Native Client 10.0};Server=MYPC;Trusted_Connection=yes;"
The connection will succeed.

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.

Use mysql embedded and --local-infile=1 with c++?

I am connecting to a mysql database using the embedding server (linking against mysqld) in c++. I have the following code:
static char *server_options[] = \
{ (char *)"mysql_test",
(char *)"--datadir=/home/cquiros/temp/mysql/db2",
(char *)"--default-storage-engine=MyISAM",
(char *)"--loose-innodb=0",
(char *)"--local-infile=1",
(char *)"--skip-grant-tables=1",
(char *)"--myisam-recover=FORCE",
(char *)"--key_buffer_size=16777216",
(char *)"--character-set-server=utf8",
(char *)"--collation-server=utf8_bin",
NULL };
int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
mysql_library_init(num_elements, server_options, NULL);
m_mysql = mysql_init(NULL);
char enable_load_infile = 1;
if (mysql_options(m_mysql,MYSQL_OPT_LOCAL_INFILE, (const char *)&(enable_load_infile)))
qDebug() << "Error setting option";
mysql_real_connect(m_mysql, NULL,NULL,NULL, "database1", 0,NULL,0);
The connection works and I can query and create tables however, when I try to execute "load data local infile ..." I always get "The used command is not allowed with this MySQL version" even though I am setting --local-infile=1 in the server options or setting it in code in:
char enable_load_infile = 1;
if (mysql_options(m_mysql,MYSQL_OPT_LOCAL_INFILE, (const char *)&(enable_load_infile)))
qDebug() << "Error setting option";
Any idea what I am doing wrong and how to fix it?
Many thanks for your help.
Carlos.
#QLands I realize its over a year since you've asked this question, but I figured I'd reply just for posterity in case others like me are googling for solutions.
I'm having the same issue, I can get LOAD DATA LOCAL INFILE statements to work from the Linux mysql CLI after I explicitly enabled it in the /etc/mysql/my.cfg file. However I CANNOT get it to work with the MySQL C++ connector -- I also get the error "The used command is not allowed with this MySQL version" when I try and run a LOAD DATA LOCAL INFILE command through the MySQL C++ connector. wtf right?
After much diligent googling and finding some back alley tech support posts I've come to conclude that the MySQL C++ connector did not (for whatever reason) decide to implement the ability for developers to be able to allow the local-infile=1 option. Apparently some people have been able to hack/fork the MySQL C++ connector to expose the functionality, but no one posted their source code -- only said it worked. Apparently there is a workaround in the MySQL C API after you initialize the connection you would use this:
mysql_options( &mysql, MYSQL_OPT_LOCAL_INFILE, 1 );
Here are some reference articles that lead me to this conclusion:
1.)
How can I get the native C API connection structure from MySQL Connector/C++?
2.)
Mysql 5.5 LOAD DATA INFILE Permissions
3.)
http://osdir.com/ml/db.mysql.c++/2004-04/msg00097.html
Essentially if you want the ability to use the LOAD DATA LOCAL INFILE functionality -- you have to use the mysql C API or execute it from the command line or hack/fork the existing mysql C++ api to expose the connection structure
:(

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/

SQLite open performance-issue

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).