I´ve already compiled SQLCipher for windows and encrypt/decrypt a database file using SQLCipher at command line. The problem is at the last part of this tutorial when I use SQLCipher in Visual Studio.
It looks like the application skips this code line, because it is not encrypting neither decrypting, i'm not getting any error.
if (sqlite3_exec(db, (const char*)"PRAGMA key ='password'", NULL, NULL, NULL) == SQLITE_OK){
printf("Accepted Key\n");
};
Can anyone tell me what's wrong? or provide some sample C code?
Thanks in advance.
There are a couple of items to address here. First, checking for SQLITE_OK as a status code from sqlite3_exec does not mean that the provided password is valid for the database. In order to validate that, once the database has been keyed, we recommend you perform a query such as:
SELECT count(*) FROM sqlite_master;
This table will always be present, regardless of the state of your application schema.
Next, to verify that you have properly integrated the SQLCipher library within your application, we can query the database for the PRAGMA cipher_version; reported by the library. Below is a sample for doing so:
int rc;
sqlite3 *db;
sqlite3_stmt *stmt;
rc = sqlite3_open(":memory:", &db);
if(rc != SQLITE_OK){
printf("failed to open database\n");
}
rc = sqlite3_prepare(db, "PRAGMA cipher_version;", -1, &stmt, NULL);
rc = sqlite3_step(stmt);
if(rc == SQLITE_ROW){
printf("SQLCipher version:%s\n", sqlite3_column_text(stmt, 0));
}
sqlite3_finalize(stmt);
if(db != NULL){
sqlite3_close(db);
}
Related
I have an sqlite3 database open. I attach a second database, check whether the first and second database have the same value in a table, and then detach the second database. The detach command gives the error "database db2 is locked".
The process is not multi-threaded. There are no other processes accessing the databases. I get the same results on NFS and the local disk. I tried inserting a delay before the detach in case the lock mentioned in the error is related to the file system.
If I comment out the SELECT statement in the code below, the detach works. So basically, attach then detach works, but if I execute SQL code before the detach I receive SQLITE_ERROR return status and the error message shown above.
SQLite version 3.22.0.1
BTW, I realize I could SELECT count(s.id) instead of looping over each row returned from SELECT *, but other posts talk about making sure sqlite3_step() is called until SQLITE_DONE is returned and I wanted to try everything before posting here.
sqlite3_stmt *stmt;
char *errMsg;
const char *zLeftover;
int count = 0;
// DB declared as:
// sqlite3 *DB;
// opened as:
// sqlite3_open(":memory:", &DB);
sqlret = sqlite3_exec(DB, "ATTACH DATABASE foo.db AS db2;", NULL, 0, &errMsg);
assert(sqlret == SQLITE_OK);
sqlret = sqlite3_prepare_v2(DB,
"SELECT * FROM sessions s INNER JOIN db2.sessions s2 ON s2.id=s.id;",
-1, &stmt, &zLeftover);
assert(sqlret == SQLITE_OK);
sqlret = sqlite3_step(stmt);
while (sqlret == SQLITE_ROW) {
++count;
sqlret = sqlite3_step(stmt);
}
sqlret = sqlite3_finalize(stmt);
assert(sqlret == SQLITE_OK);
sqlret = sqlite3_exec(DB, "DETACH DATABASE db2", NULL, 0, &errMsg);
// This assert fails with SQLITE_ERROR
assert(sqlret == SQLITE_OK);
I expect the sqlite3_finalize(stmt) call to remove any internal locking on the attached database. Is there another call or additional SQL that must be executed before the detach? A pragma setting? A configuration option on the lib?
I've searched the usual places with no luck. Thanks in advance for you help.
when I try to select with QSqlQuery:
select mwst, sum(in), sum(out) from costs group by mwst
I got the error: QSqlQuery::value: not positioned on a valid record
In SQLite Database Browser tool the select runs without error.
Thanks for help!
have you used bool QSqlQuery::next() to set the query on a valid value (if the query succeeded, you should get results
like:
QSqlQuery qry("select * from table");
while (qry.next())
{
qDebug() << qry.value(0).toString();
}
I've made a button that removes all the objects in my array, which is shown in my tableView. Then it reloads data and the tableview is empty. But how can I delete all the data from my SQLite database as well, and not just the array? Now the data occurs when I restart. I have tried this:
Button void:
- (void) deleteAllButton_Clicked:(id)sender {
[appDelegate removeAllBooks:nil];
[self.tableView reloadData];
}
Appdelegate void:
-(void) removeAllBooks:(Book *)bookObj {
//Delete it from the database.
[bookObj deleteAllBooks];
//Remove it from the array.
[bookArray removeAllObjects];
}
Delete syntax in Book.m
- (void) deleteAllBooks {
if(deleteStmt == nil) {
const char *sql = "WHAT DO I HAVE TO DO TO DELETE ALL THE ROWS?";
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
}
//When binding parameters, index starts from 1 and not zero.
sqlite3_bind_int(deleteStmt, 1, bookID);
if (SQLITE_DONE != sqlite3_step(deleteStmt))
NSAssert1(0, #"Error while deleting. '%s'", sqlite3_errmsg(database));
sqlite3_reset(deleteStmt);
}
Well, the normal SQL syntax would be:
DELETE FROM tablename
If you have a standard primary id column (and you should) you can do
DELETE FROM tablename WHERE id > -1;
And this will delete all rows in the table since there is no id less than 0.
DELETE FROM tablename did not work for me. I was using a sqlite3 database on iPhone, which I assume the poster was, as well. For me to get this to work, I needed to:
DROP table tablename
followed by a CREATE statement, if I wanted the table to still exist (without any rows).
Of course, that requires knowing the right CREATE statement. Using the SQLManager plugin for Firefox quickly reverse-engineered for me the correct CREATE statement to use. I never figured out why DELETE FROM tablename didn't work, but it definitely didn't, in my case.
I am creating a SQLite database from qt like this:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", mConnectionName);
db.setDatabaseName("myDattabse.DB");
if (!db.open()) {
return false;
}
When trying to insert Macedonian characters in the SQLite database, the characters are inserted as ???.
According to this link http://www.qtcentre.org/threads/26202-SQLite-connection-and-encoding?highlight=unicode+and+sqllite , I need to create my database with utf-16 encoding to solve my problem. SQLite default encoding is utf-8. How can I do that? Where to specify this option in my code?
From my understanding you should be fine with UTF8, pls, check if an example below would work for you:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if( !db.open() )
{
qDebug() << db.lastError();
qFatal( "Failed to connect." );
}
QSqlQuery query;
query.prepare("CREATE TABLE IF NOT EXISTS names (id INTEGER UNIQUE PRIMARY KEY, test_field VARCHAR(30))");
query.exec();
query.prepare(QObject::trUtf8("INSERT INTO names (id, test_field) VALUES (1, 'тест1')"));
query.exec();
query.prepare(QObject::trUtf8("INSERT INTO names (id, test_field) VALUES (2, 'тест2')"));
query.exec();
QSqlQuery select("SELECT test_field FROM names");
while (select.next())
{
qDebug() << select.value(0).toString();
}
output should be:
"тест1"
"тест2"
now back to your original question, I believe you can have you sqlite database in UTF-16 as default encoding if the database is opened with sqlite3_open16 function. According to QT source code (qsql_sqlite.cpp QSQLiteDriver) they are using sqlite3_open_v2 function to open the connection to database which is UTF-8, but again, there is nothing wrong with it for working correctly with Cyrillic characters.
hope this helps, regards
I'm trying to make an insertion from one database called suspension to the table called Notification in the ANimals database. My stored procedure is this:
ALTER PROCEDURE [dbo].[spCreateNotification]
-- Add the parameters for the stored procedure here
#notRecID int,
#notName nvarchar(50),
#notRecStatus nvarchar(1),
#notAdded smalldatetime,
#notByWho int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO Animals.dbo.Notification
(
NotRecID,
NotName,
NotRecStatus,
NotAdded,
NotByWho
)
values (#notRecID, #notName, #notRecStatus, #notAdded, #notByWho);
END
The null inserting is to replenish one column that otherwise will not be filled, I've tried different ways, like using also the names for the columns after the name of the table and then only indicate in values the fields I've got. I know it is not a problem of the stored procedure because I executed it from the sql server management studio and it works introducing the parameters. Then I guess the problem must be in the repository when I call the stored procedure:
public void createNotification(Notification not)
{
try
{
DB.spCreateNotification(not.NotRecID, not.NotName, not.NotRecStatus,
(DateTime)not.NotAdded, (int)not.NotByWho);
}
catch
{
return;
}
}
And I call the method here:
public void createNotifications(IList<TemporalNotification> notifications)
{
foreach (var TNot in notifications)
{
var ts = RepositoryService._suspension.getTemporalSuspensionForNotificationID(TNot.TNotRecID);
Notification notification = new Notification();
if (ts.Count != 0)
{
notification.NotName = TNot.TNotName;
notification.NotRecID = TNot.TNotRecID;
notification.NotRecStatus = TNot.TNotRecStatus;
notification.NotAdded = TNot.TNotAdded;
notification.NotByWho = TNot.TNotByWho;
if (TNot.TNotToReplace != 0)
{
var suspensions = RepositoryService._suspension.getSuspensionsAttached((int)TNot.TNotToReplace);
foreach (var sus in suspensions)
{
sus.CtsEndDate = TNot.TNotAdded;
sus.CtsEndNotRecID = TNot.TNotRecID;
DB.spModifySuspensionWhenNotificationIsReplaced((int)TNot.TNotToReplace, (int)sus.CtsEndNotRecID, (DateTime) sus.CtsEndDate);
}
DB.spReplaceNotification((int)TNot.TNotToReplace, DateTime.Now);
createNotification(notification);
}
else
{
createNotification(notification);
}
}
}
deleteTemporalNotifications(notifications);
}
It does not record the value in the database. I've been debugging and getting mad about this, because it works when I execute it manually, but not when I automatize the proccess in my application. Does anyone see anything wrong with my code?
Thank you
EDIT: Added more code. It still doesn't work changing that, I mean, the procedure works if I execute it, so I don't know what could be the error. In fact, I don't get any error. Could it be a matter of writin in a table that is not in the database where you have your stored procedure?
I would specify your column names and DONT incude the NULL at all for that column. Just let SQL Server deal with it.
INSERT INTO Animals.dbo.Notification
(
RecID,
[Name],
RecStatus,
Added,
ByWho
)
values (#notRecID, #notName, #notRecStatus, #notAdded, #notByWho);
Run profiler when you try to run it from the application and see what values it realy is sending. That will tell you if the application is creating the correct exec statment to exec the proc.
Also it may be a permissions problem.
Specify your column names:
INSERT INTO Animals.dbo.Notification
(RecID, Name, RecStatus, Added, ByWho)
VALUES
(#notRecID, #notName, #notRecStatus, #notAdded, #notByWho);
"Could it be a matter of writin in a table that is not in the database where you have your stored procedure?"
That may be the problem. You could try adding the "WITH EXECUTE AS OWNER" clause to your stored procedure so that it executes as the owner of the stored procedure. Or grant write permissions for the executing user to the table.
http://msdn.microsoft.com/en-us/library/ms188354.aspx
ok, I finally found out what noone realized lol. It was a very stupid error but got me really mad till I found the problem. It wasn't a problem of permissions, the problem was that I was not executing the procedure from my application, so where I wrote this:
DB.spCreateNotification(not.NotRecID, not.NotName, not.NotRecStatus,
(DateTime)not.NotAdded, (int)not.NotByWho);
When I had to write:
DB.spCreateNotification(not.NotRecID, not.NotName, not.NotRecStatus,
(DateTime)not.NotAdded, (int)not.NotByWho).Execute();
so as you see I was focusing my efforts in much more complex things and I wasn't even executing it...lol.
Thank you all for your answers anyway:)