Compare variable with SQLite values - xcode

I need to check if a variable has already been inserted on my SQLite db in order to change an image button, I tried to use this method but it's not working properly:
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &Preferiti) == SQLITE_OK)
{
NSString *checkSQL = [NSString stringWithFormat: #"SELECT * FROM ListaEventi WHERE idEvento=%#", [DettagliEvento objectAtIndex:7]];
const char *insert_stmt = [checkSQL UTF8String];
sqlite3_prepare_v2(Preferiti, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
[_preferito setImage:[UIImage imageNamed:#"staroff.png"] forState:UIControlStateNormal];
_preferito.tag=0;
} else {
[_preferito setImage:[UIImage imageNamed:#"staron.png"] forState:UIControlStateNormal];
_preferito.tag=1;
}
sqlite3_finalize(statement);
sqlite3_close(Preferiti);
}
Is there any other way to write the statement to compare a variable with values inside my SQLite table?

Related

Error with Firebase/Messaging in iOS when create table

I have a error in iOS with xcode 12.5.1.
When I open the app it crashed.
This happens when execute line FirebaseApp.configure() in AppDelegate.swift class
pod 'Firebase/Messaging' - FirebaseMessaging (7.11.0)
Error: 2021-08-16 01:13:02.476120-0500 bm[7585:1201692] [logging] file
is not a database in "create TABLE IF NOT EXISTS incomingSyncMessages
(_id INTEGER PRIMARY KEY, rmq_id TEXT, expiration_ts INTEGER,
apns_recv INTEGER, mcs_recv INTEGER)"
2021-08-16 01:13:11.138855-0500 bm[7585:1201692] *** Assertion failure
in -[FIRMessagingRmqManager createTableWithName:command:],
FIRMessagingRmqManager.m:456
2021-08-16 01:13:11.140170-0500 bm[7585:1201692] *** Terminating app
due to uncaught exception 'NSInternalInconsistencyException', reason:
'Couldn't create table: create TABLE IF NOT EXISTS Couldn't create
table: create TABLE IF NOT EXISTS %#%# (_id INTEGER PRIMARY KEY,
rmq_id INTEGER, type INTEGER, ts INTEGER, data BLOB) file is not a
database34-62-25736 (_id INTEGER PRIMARY KEY, rmq_id INTEGER, type
INTEGER, ts INTEGER, data BLOB) file is not a database'
*** First throw call stack: (0x1a82b725c 0x1bc04c480 0x1a81c4c98 0x1a94fcef8 0x10510283c 0x1051030b0 0x108063ae8 0x10806532c
0x10806c38c 0x10806d010 0x108078820 0x1f07e95bc 0x1f07ec86c)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't create table:
create TABLE IF NOT EXISTS Couldn't create table: create TABLE IF NOT
EXISTS %#%# (_id INTEGER PRIMARY KEY, rmq_id INTEGER, type INTEGER, ts
INTEGER, data BLOB) file is not a database34-62-25736 (_id INTEGER
PRIMARY KEY, rmq_id INTEGER, type INTEGER, ts INTEGER, data BLOB) file
is not a database' terminating with uncaught exception of type
NSException
FIRMessagingRmqManager.m:
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FirebaseMessaging/Sources/FIRMessagingRmqManager.h"
#import <sqlite3.h>
#import "FirebaseMessaging/Sources/FIRMessagingConstants.h"
#import "FirebaseMessaging/Sources/FIRMessagingDefines.h"
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
#import "FirebaseMessaging/Sources/FIRMessagingPersistentSyncMessage.h"
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
#import "FirebaseMessaging/Sources/NSError+FIRMessaging.h"
#ifndef _FIRMessagingRmqLogAndExit
#define _FIRMessagingRmqLogAndExit(stmt, return_value) \
do { \
[self logErrorAndFinalizeStatement:stmt]; \
return return_value; \
} while (0)
#endif
#ifndef FIRMessagingRmqLogAndReturn
#define FIRMessagingRmqLogAndReturn(stmt) \
do { \
[self logErrorAndFinalizeStatement:stmt]; \
return; \
} while (0)
#endif
#ifndef FIRMessaging_MUST_NOT_BE_MAIN_THREAD
#define FIRMessaging_MUST_NOT_BE_MAIN_THREAD() \
do { \
NSAssert(![NSThread isMainThread], #"Must not be executing on the main thread."); \
} while (0);
#endif
// table names
NSString *const kTableOutgoingRmqMessages = #"outgoingRmqMessages";
NSString *const kTableLastRmqId = #"lastrmqid";
NSString *const kOldTableS2DRmqIds = #"s2dRmqIds";
NSString *const kTableS2DRmqIds = #"s2dRmqIds_1";
// Used to prevent de-duping of sync messages received both via APNS and MCS.
NSString *const kTableSyncMessages = #"incomingSyncMessages";
static NSString *const kTablePrefix = #"";
// create tables
static NSString *const kCreateTableOutgoingRmqMessages = #"create TABLE IF NOT EXISTS %#%# "
#"(_id INTEGER PRIMARY KEY, "
#"rmq_id INTEGER, "
#"type INTEGER, "
#"ts INTEGER, "
#"data BLOB)";
static NSString *const kCreateTableLastRmqId = #"create TABLE IF NOT EXISTS %#%# "
#"(_id INTEGER PRIMARY KEY, "
#"rmq_id INTEGER)";
static NSString *const kCreateTableS2DRmqIds = #"create TABLE IF NOT EXISTS %#%# "
#"(_id INTEGER PRIMARY KEY, "
#"rmq_id TEXT)";
static NSString *const kCreateTableSyncMessages = #"create TABLE IF NOT EXISTS %#%# "
#"(_id INTEGER PRIMARY KEY, "
#"rmq_id TEXT, "
#"expiration_ts INTEGER, "
#"apns_recv INTEGER, "
#"mcs_recv INTEGER)";
static NSString *const kDropTableCommand = #"drop TABLE if exists %#%#";
// table infos
static NSString *const kRmqIdColumn = #"rmq_id";
static NSString *const kDataColumn = #"data";
static NSString *const kProtobufTagColumn = #"type";
static NSString *const kIdColumn = #"_id";
static NSString *const kOutgoingRmqMessagesColumns = #"rmq_id, type, data";
// Sync message columns
static NSString *const kSyncMessagesColumns = #"rmq_id, expiration_ts, apns_recv, mcs_recv";
// Message time expiration in seconds since 1970
static NSString *const kSyncMessageExpirationTimestampColumn = #"expiration_ts";
static NSString *const kSyncMessageAPNSReceivedColumn = #"apns_recv";
static NSString *const kSyncMessageMCSReceivedColumn = #"mcs_recv";
// Utility to create an NSString from a sqlite3 result code
NSString *_Nonnull FIRMessagingStringFromSQLiteResult(int result) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
const char *errorStr = sqlite3_errstr(result);
#pragma clang diagnostic pop
NSString *errorString = [NSString stringWithFormat:#"%d - %s", result, errorStr];
return errorString;
}
#interface FIRMessagingRmqManager () {
sqlite3 *_database;
/// Serial queue for database read/write operations.
dispatch_queue_t _databaseOperationQueue;
}
#property(nonatomic, readwrite, strong) NSString *databaseName;
// map the category of an outgoing message with the number of messages for that category
// should always have two keys -- the app, gcm
#property(nonatomic, readwrite, strong) NSMutableDictionary *outstandingMessages;
// Outgoing RMQ persistent id
#property(nonatomic, readwrite, assign) int64_t rmqId;
#end
#implementation FIRMessagingRmqManager
- (instancetype)initWithDatabaseName:(NSString *)databaseName {
self = [super init];
if (self) {
_databaseOperationQueue =
dispatch_queue_create("com.google.firebase.messaging.database.rmq", DISPATCH_QUEUE_SERIAL);
_databaseName = [databaseName copy];
[self openDatabase];
_outstandingMessages = [NSMutableDictionary dictionaryWithCapacity:2];
_rmqId = -1;
}
return self;
}
- (void)dealloc {
sqlite3_close(_database);
}
#pragma mark - RMQ ID
- (void)loadRmqId {
if (self.rmqId >= 0) {
return; // already done
}
[self loadInitialOutgoingPersistentId];
if (self.outstandingMessages.count) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmqManager000, #"Outstanding categories %ld",
_FIRMessaging_UL(self.outstandingMessages.count));
}
}
/**
* Initialize the 'initial RMQ':
* - max ID of any message in the queue
* - if the queue is empty, stored value in separate DB.
*
* Stream acks will remove from RMQ, when we remove the highest message we keep track
* of its ID.
*/
- (void)loadInitialOutgoingPersistentId {
// we shouldn't always trust the lastRmqId stored in the LastRmqId table, because
// we only save to the LastRmqId table once in a while (after getting the lastRmqId sent
// by the server after reconnect, and after getting a rmq ack from the server). The
// rmq message with the highest rmq id tells the real story, so check against that first.
__block int64_t rmqId;
dispatch_sync(_databaseOperationQueue, ^{
rmqId = [self queryHighestRmqId];
});
if (rmqId == 0) {
dispatch_sync(_databaseOperationQueue, ^{
rmqId = [self queryLastRmqId];
});
}
self.rmqId = rmqId + 1;
}
/**
* This is called when we delete the largest outgoing message from queue.
*/
- (void)saveLastOutgoingRmqId:(int64_t)rmqID {
dispatch_async(_databaseOperationQueue, ^{
NSString *queryFormat = #"INSERT OR REPLACE INTO %# (%#, %#) VALUES (?, ?)";
NSString *query = [NSString stringWithFormat:queryFormat,
kTableLastRmqId, // table
kIdColumn, kRmqIdColumn]; // columns
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(self->_database, [query UTF8String], -1, &statement, NULL) !=
SQLITE_OK) {
FIRMessagingRmqLogAndReturn(statement);
}
if (sqlite3_bind_int(statement, 1, 1) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(statement);
}
if (sqlite3_bind_int64(statement, 2, rmqID) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(statement);
}
if (sqlite3_step(statement) != SQLITE_DONE) {
FIRMessagingRmqLogAndReturn(statement);
}
sqlite3_finalize(statement);
});
}
- (void)saveS2dMessageWithRmqId:(NSString *)rmqId {
dispatch_async(_databaseOperationQueue, ^{
NSString *insertFormat = #"INSERT INTO %# (%#) VALUES (?)";
NSString *insertSQL = [NSString stringWithFormat:insertFormat, kTableS2DRmqIds, kRmqIdColumn];
sqlite3_stmt *insert_statement;
if (sqlite3_prepare_v2(self->_database, [insertSQL UTF8String], -1, &insert_statement, NULL) !=
SQLITE_OK) {
FIRMessagingRmqLogAndReturn(insert_statement);
}
if (sqlite3_bind_text(insert_statement, 1, [rmqId UTF8String], (int)[rmqId length],
SQLITE_STATIC) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(insert_statement);
}
if (sqlite3_step(insert_statement) != SQLITE_DONE) {
FIRMessagingRmqLogAndReturn(insert_statement);
}
sqlite3_finalize(insert_statement);
});
}
#pragma mark - Query
- (int64_t)queryHighestRmqId {
NSString *queryFormat = #"SELECT %# FROM %# ORDER BY %# DESC LIMIT %d";
NSString *query = [NSString stringWithFormat:queryFormat,
kRmqIdColumn, // column
kTableOutgoingRmqMessages, // table
kRmqIdColumn, // order by column
1]; // limit
sqlite3_stmt *statement;
int64_t highestRmqId = 0;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(statement, highestRmqId);
}
if (sqlite3_step(statement) == SQLITE_ROW) {
highestRmqId = sqlite3_column_int64(statement, 0);
}
sqlite3_finalize(statement);
return highestRmqId;
}
- (int64_t)queryLastRmqId {
NSString *queryFormat = #"SELECT %# FROM %# ORDER BY %# DESC LIMIT %d";
NSString *query = [NSString stringWithFormat:queryFormat,
kRmqIdColumn, // column
kTableLastRmqId, // table
kRmqIdColumn, // order by column
1]; // limit
sqlite3_stmt *statement;
int64_t lastRmqId = 0;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, NULL) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(statement, lastRmqId);
}
if (sqlite3_step(statement) == SQLITE_ROW) {
lastRmqId = sqlite3_column_int64(statement, 0);
}
sqlite3_finalize(statement);
return lastRmqId;
}
#pragma mark - Sync Messages
- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID {
__block FIRMessagingPersistentSyncMessage *persistentMessage;
dispatch_sync(_databaseOperationQueue, ^{
NSString *queryFormat = #"SELECT %# FROM %# WHERE %# = '%#'";
NSString *query =
[NSString stringWithFormat:queryFormat,
kSyncMessagesColumns, // SELECT (rmq_id, expiration_ts,
// apns_recv, mcs_recv)
kTableSyncMessages, // FROM sync_rmq
kRmqIdColumn, // WHERE rmq_id
rmqID];
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(self->_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
[self logError];
sqlite3_finalize(stmt);
return;
}
const int rmqIDColumn = 0;
const int expirationTimestampColumn = 1;
const int apnsReceivedColumn = 2;
const int mcsReceivedColumn = 3;
int count = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
NSString *rmqID =
[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, rmqIDColumn)];
int64_t expirationTimestamp = sqlite3_column_int64(stmt, expirationTimestampColumn);
BOOL apnsReceived = sqlite3_column_int(stmt, apnsReceivedColumn);
BOOL mcsReceived = sqlite3_column_int(stmt, mcsReceivedColumn);
// create a new persistent message
persistentMessage =
[[FIRMessagingPersistentSyncMessage alloc] initWithRMQID:rmqID
expirationTime:expirationTimestamp];
persistentMessage.apnsReceived = apnsReceived;
persistentMessage.mcsReceived = mcsReceived;
count++;
}
sqlite3_finalize(stmt);
});
return persistentMessage;
}
- (void)deleteExpiredOrFinishedSyncMessages {
dispatch_async(_databaseOperationQueue, ^{
int64_t now = FIRMessagingCurrentTimestampInSeconds();
NSString *deleteSQL = #"DELETE FROM %# "
#"WHERE %# < %lld OR " // expirationTime < now
#"(%# = 1 AND %# = 1)"; // apns_received = 1 AND mcs_received = 1
NSString *query = [NSString
stringWithFormat:deleteSQL, kTableSyncMessages, kSyncMessageExpirationTimestampColumn, now,
kSyncMessageAPNSReceivedColumn, kSyncMessageMCSReceivedColumn];
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(self->_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
FIRMessagingRmqLogAndReturn(stmt);
}
sqlite3_finalize(stmt);
int deleteCount = sqlite3_changes(self->_database);
if (deleteCount > 0) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSyncMessageManager001,
#"Successfully deleted %d sync messages from store", deleteCount);
}
});
}
- (void)saveSyncMessageWithRmqID:(NSString *)rmqID expirationTime:(int64_t)expirationTime {
BOOL apnsReceived = YES;
BOOL mcsReceived = NO;
dispatch_async(_databaseOperationQueue, ^{
NSString *insertFormat = #"INSERT INTO %# (%#, %#, %#, %#) VALUES (?, ?, ?, ?)";
NSString *insertSQL =
[NSString stringWithFormat:insertFormat,
kTableSyncMessages, // Table name
kRmqIdColumn, // rmq_id
kSyncMessageExpirationTimestampColumn, // expiration_ts
kSyncMessageAPNSReceivedColumn, // apns_recv
kSyncMessageMCSReceivedColumn /* mcs_recv */];
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(self->_database, [insertSQL UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_bind_int64(stmt, 2, expirationTime) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_bind_int(stmt, 3, apnsReceived ? 1 : 0) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_bind_int(stmt, 4, mcsReceived ? 1 : 0) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(stmt);
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
FIRMessagingRmqLogAndReturn(stmt);
}
sqlite3_finalize(stmt);
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager004,
#"Added sync message to cache: %#", rmqID);
});
}
- (void)updateSyncMessageViaAPNSWithRmqID:(NSString *)rmqID {
dispatch_async(_databaseOperationQueue, ^{
if (![self updateSyncMessageWithRmqID:rmqID column:kSyncMessageAPNSReceivedColumn value:YES]) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager005,
#"Failed to update APNS state for sync message %#", rmqID);
}
});
}
- (BOOL)updateSyncMessageWithRmqID:(NSString *)rmqID column:(NSString *)column value:(BOOL)value {
FIRMessaging_MUST_NOT_BE_MAIN_THREAD();
NSString *queryFormat = #"UPDATE %# " // Table name
#"SET %# = %d " // column=value
#"WHERE %# = ?"; // condition
NSString *query = [NSString
stringWithFormat:queryFormat, kTableSyncMessages, column, value ? 1 : 0, kRmqIdColumn];
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(stmt, NO);
}
if (sqlite3_bind_text(stmt, 1, [rmqID UTF8String], (int)[rmqID length], NULL) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(stmt, NO);
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
_FIRMessagingRmqLogAndExit(stmt, NO);
}
sqlite3_finalize(stmt);
return YES;
}
#pragma mark - Database
- (NSString *)pathForDatabase {
return [[self class] pathForDatabaseWithName:_databaseName];
}
+ (NSString *)pathForDatabaseWithName:(NSString *)databaseName {
NSString *dbNameWithExtension = [NSString stringWithFormat:#"%#.sqlite", databaseName];
NSArray *paths =
NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), NSUserDomainMask, YES);
NSArray *components = #[ paths.lastObject, kFIRMessagingSubDirectoryName, dbNameWithExtension ];
return [NSString pathWithComponents:components];
}
- (void)createTableWithName:(NSString *)tableName command:(NSString *)command {
FIRMessaging_MUST_NOT_BE_MAIN_THREAD();
char *error;
NSString *createDatabase = [NSString stringWithFormat:command, kTablePrefix, tableName];
if (sqlite3_exec(self->_database, [createDatabase UTF8String], NULL, NULL, &error) != SQLITE_OK) {
// remove db before failing
[self removeDatabase];
NSString *errorMessage = [NSString
stringWithFormat:#"Couldn't create table: %# %#", kCreateTableOutgoingRmqMessages,
[NSString stringWithCString:error encoding:NSUTF8StringEncoding]];
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingTable, #"%#",
errorMessage);
NSAssert(NO, errorMessage);
}
}
- (void)dropTableWithName:(NSString *)tableName {
FIRMessaging_MUST_NOT_BE_MAIN_THREAD();
char *error;
NSString *dropTableSQL = [NSString stringWithFormat:kDropTableCommand, kTablePrefix, tableName];
if (sqlite3_exec(self->_database, [dropTableSQL UTF8String], NULL, NULL, &error) != SQLITE_OK) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore002,
#"Failed to remove table %#", tableName);
}
}
- (void)removeDatabase {
// Ensure database is removed in a sync queue as this sometimes makes test have race conditions.
dispatch_async(_databaseOperationQueue, ^{
NSString *path = [self pathForDatabase];
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
});
}
- (void)openDatabase {
dispatch_async(_databaseOperationQueue, ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *path = [self pathForDatabase];
BOOL didOpenDatabase = YES;
if (![fileManager fileExistsAtPath:path]) {
// We've to separate between different versions here because of backwards compatbility issues.
int result = sqlite3_open_v2(
[path UTF8String], &self -> _database,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FILEPROTECTION_NONE, NULL);
if (result != SQLITE_OK) {
NSString *errorString = FIRMessagingStringFromSQLiteResult(result);
NSString *errorMessage = [NSString
stringWithFormat:#"Could not open existing RMQ database at path %#, error: %#", path,
errorString];
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase,
#"%#", errorMessage);
NSAssert(NO, errorMessage);
return;
}
[self createTableWithName:kTableOutgoingRmqMessages command:kCreateTableOutgoingRmqMessages];
[self createTableWithName:kTableLastRmqId command:kCreateTableLastRmqId];
[self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds];
} else {
// Calling sqlite3_open should create the database, since the file doesn't exist.
int result = sqlite3_open_v2(
[path UTF8String], &self -> _database,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FILEPROTECTION_NONE, NULL);
if (result != SQLITE_OK) {
NSString *errorString = FIRMessagingStringFromSQLiteResult(result);
NSString *errorMessage =
[NSString stringWithFormat:#"Could not create RMQ database at path %#, error: %#", path,
errorString];
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase,
#"%#", errorMessage);
NSAssert(NO, errorMessage);
didOpenDatabase = NO;
} else {
[self updateDBWithStringRmqID];
}
}
if (didOpenDatabase) {
[self createTableWithName:kTableSyncMessages command:kCreateTableSyncMessages];
}
});
}
- (void)updateDBWithStringRmqID {
dispatch_async(_databaseOperationQueue, ^{
[self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds];
[self dropTableWithName:kOldTableS2DRmqIds];
});
}
#pragma mark - Private
- (BOOL)saveMessageWithRmqId:(int64_t)rmqId tag:(int8_t)tag data:(NSData *)data {
FIRMessaging_MUST_NOT_BE_MAIN_THREAD();
NSString *insertFormat = #"INSERT INTO %# (%#, %#, %#) VALUES (?, ?, ?)";
NSString *insertSQL =
[NSString stringWithFormat:insertFormat,
kTableOutgoingRmqMessages, // table
kRmqIdColumn, kProtobufTagColumn, kDataColumn /* columns */];
sqlite3_stmt *insert_statement;
if (sqlite3_prepare_v2(self->_database, [insertSQL UTF8String], -1, &insert_statement, NULL) !=
SQLITE_OK) {
_FIRMessagingRmqLogAndExit(insert_statement, NO);
}
if (sqlite3_bind_int64(insert_statement, 1, rmqId) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(insert_statement, NO);
}
if (sqlite3_bind_int(insert_statement, 2, tag) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(insert_statement, NO);
}
if (sqlite3_bind_blob(insert_statement, 3, [data bytes], (int)[data length], NULL) != SQLITE_OK) {
_FIRMessagingRmqLogAndExit(insert_statement, NO);
}
if (sqlite3_step(insert_statement) != SQLITE_DONE) {
_FIRMessagingRmqLogAndExit(insert_statement, NO);
}
sqlite3_finalize(insert_statement);
return YES;
}
- (void)deleteMessagesFromTable:(NSString *)tableName withRmqIds:(NSArray *)rmqIds {
dispatch_async(_databaseOperationQueue, ^{
BOOL isRmqIDString = NO;
// RmqID is a string only for outgoing messages
if ([tableName isEqualToString:kTableS2DRmqIds] ||
[tableName isEqualToString:kTableSyncMessages]) {
isRmqIDString = YES;
}
NSMutableString *delete =
[NSMutableString stringWithFormat:#"DELETE FROM %# WHERE ", tableName];
NSString *toDeleteArgument = [NSString stringWithFormat:#"%# = ? OR ", kRmqIdColumn];
int toDelete = (int)[rmqIds count];
if (toDelete == 0) {
return;
}
int maxBatchSize = 100;
int start = 0;
int deleteCount = 0;
while (start < toDelete) {
// construct the WHERE argument
int end = MIN(start + maxBatchSize, toDelete);
NSMutableString *whereArgument = [NSMutableString string];
for (int i = start; i < end; i++) {
[whereArgument appendString:toDeleteArgument];
}
// remove the last * OR * from argument
NSRange range = NSMakeRange([whereArgument length] - 4, 4);
[whereArgument deleteCharactersInRange:range];
NSString *deleteQuery = [NSString stringWithFormat:#"%# %#", delete, whereArgument];
// sqlite update
sqlite3_stmt *delete_statement;
if (sqlite3_prepare_v2(self->_database, [deleteQuery UTF8String], -1, &delete_statement,
NULL) != SQLITE_OK) {
FIRMessagingRmqLogAndReturn(delete_statement);
}
// bind values
int rmqIndex = 0;
int placeholderIndex = 1; // placeholders in sqlite3 start with 1
for (NSString *rmqId in rmqIds) { // objectAtIndex: is O(n) -- would make it slow
if (rmqIndex < start) {
rmqIndex++;
continue;
} else if (rmqIndex >= end) {
break;
} else {
if (isRmqIDString) {
if (sqlite3_bind_text(delete_statement, placeholderIndex, [rmqId UTF8String],
(int)[rmqId length], SQLITE_STATIC) != SQLITE_OK) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore003,
#"Failed to bind rmqID %#", rmqId);
FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager007,
#"Failed to delete sync message %#", rmqId);
continue;
}
} else {
int64_t rmqIdValue = [rmqId longLongValue];
sqlite3_bind_int64(delete_statement, placeholderIndex, rmqIdValue);
}
placeholderIndex++;
}
rmqIndex++;
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeSyncMessageManager008,
#"Successfully deleted sync message from cache %#", rmqId);
}
if (sqlite3_step(delete_statement) != SQLITE_DONE) {
FIRMessagingRmqLogAndReturn(delete_statement);
}
sqlite3_finalize(delete_statement);
deleteCount += sqlite3_changes(self->_database);
start = end;
}
// if we are here all of our sqlite queries should have succeeded
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRmq2PersistentStore004,
#"Trying to delete %d s2D ID's, successfully deleted %d", toDelete,
deleteCount);
});
}
- (int64_t)nextRmqId {
return ++self.rmqId;
}
- (NSString *)lastErrorMessage {
return [NSString stringWithFormat:#"%s", sqlite3_errmsg(_database)];
}
- (int)lastErrorCode {
return sqlite3_errcode(_database);
}
- (void)logError {
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStore006,
#"Error: code (%d) message: %#", [self lastErrorCode],
[self lastErrorMessage]);
}
- (void)logErrorAndFinalizeStatement:(sqlite3_stmt *)stmt {
[self logError];
sqlite3_finalize(stmt);
}
- (dispatch_queue_t)databaseOperationQueue {
return _databaseOperationQueue;
}
#end
Thanks for your help.

Cannot find error with SQLITE statement call

I am having a problem locating my error. The code gets through the ID(init) okay and I know the database is loading. My issue is with the IF(sqlite3_prepare_v2...) statement. When I run the code this line does not ==SQLITE_OK and it jumps to the end. ANy help is appreciated. Thanks.
#implementation CityState
static CityState *WDdatabase;
+(CityState *)WDdatabase {
if(WDdatabase == nil) {
WDdatabase = [[CityState alloc] init];
}
return WDdatabase;
}
- (id)init {
self = [super init];
if (self) {
NSString *sqliteDB = [[NSBundle mainBundle] pathForResource:#"CityAndState" ofType:#"sqlite"];
if(sqlite3_open([sqliteDB UTF8String], &WDdatebase) != SQLITE_OK){
NSLog(#"Failed to open database");
}
}
return self;
}
-(NSArray *)getAllCities {
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
NSString *query = #"SELECT * FROM Test_Table";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(WDdatebase, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
}
sqlite3_finalize(statement);
}
return returnArray;
}
As far as I know, Objective-C does not do static class variables as you are attempting, and the symbol WDatabase (I'm assuming the typo is just here on SO, not in your code) is actually a class identifier instead of your static variable. To implement a singleton, you will need a file-scope variable (outside of the #implementation block) (and I recommend you name it starting with an underscore to clarify when you are accessing that and when you are accessing the class method. So basically, the call you are failing is likely because you are passing a class object instead of your var. Once you have setup the static var properly.
The proper syntax then for accessing a "class variable" (which end up being just a file-scope/statically-stored variable, by virtue of Objective-C's C soul), is to send a message to the class object:
sqlite3_prepare_v2([CityState wDdatebase], [query UTF8String], ...
Further, and just to be pedantic; if you are not using any of NSString's features and only need UTF8 (or "C-style") strings, you can use them just as you would in C:
-(NSArray *)getAllCities {
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
char query[] = "SELECT * FROM Test_Table";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2([CityState wDdatebase], query, -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
}
sqlite3_finalize(statement);
}
return returnArray;
}

Listing entries in a keychain on Mac OS X

I have been playing around with Cocoa for the last couple of days and I was wondering how I would go about listing all Name/Account pairs of a keychain that I created? the little key chain access app that comes with Mac OS X does that, so it must be possible I presume? Is SecItemCopyMatching what I'm looking for? How do I specify the keychain I want to search, though? And what's a service name in this context?
...am I the only one who thinks the Keychain API in Cocoa is absolutely horrible? I have been reading the documentation up and down for the last couple of hours or so and I'm still getting nowhere :-/
you iterate over the items in your keychain with SecItemCopyMatching and access the password with SecKeychainFindInternetPassword or SecKeychainFindGenericPassword.
Iterate over Keychain:
// iterates over keychain and pass every item found by the query to PrintAccount.
static void IterateOverKeychain() {
// create query
CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll);
CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
// get search results
CFArrayRef result = nil;
OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)&result);
assert(status == 0);
// do something with the result
CFRange range = CFRangeMake(0, CFArrayGetCount(result));
CFArrayApplyFunction(result, range, PrintAccount, nil);
}
// prints the password for a item from the keychain.
static void PrintAccount(const void *value, void *context) {
CFDictionaryRef dict = value;
CFStringRef acct = CFDictionaryGetValue(dict, kSecAttrAccount);
NSLog(#"%#", acct);
}
Print Password:
static void PrintPassword() {
const char *acct = "foo.bar#googlemail.com";
UInt32 acctLen = (UInt32)strlen(acct);
const char *srvr = "calendar.google.com";
UInt32 srvrLen = (UInt32)strlen(srvr);
UInt32 pwLen = 0;
void *pw = 0;
SecKeychainFindInternetPassword(nil, srvrLen, srvr, 0, nil, acctLen, acct, 0, nil, 0, kSecProtocolTypeAny, kSecAuthenticationTypeAny, &pwLen, &pw, nil);
CFStringRef pwString = CFStringCreateWithBytes(kCFAllocatorDefault, pw, pwLen, kCFStringEncodingUTF8, NO);
NSLog(#"%s %#", acct, pwString);
}
Well, I managed to enumerate over the keychain entries, however the password field is empty. I thought if authorization was required, the program would ask for the keychain password automatically like it usually does?
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassInternetPassword, kSecClass,
(id)kCFBooleanTrue, kSecReturnData,
(id)kCFBooleanTrue, kSecReturnAttributes,
kSecMatchLimitAll, kSecMatchLimit,
nil];
NSArray *itemDicts = nil;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&itemDicts);
if (status)
[MessageBox Show:(NSString*)SecCopyErrorMessageString(status, NULL)];
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (NSDictionary *itemDict in itemDicts) {
NSData *data = [itemDict objectForKey:(id)kSecValueData];
NSString *pwd = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSString *acc = [itemDict objectForKey:(id)kSecAttrAccount];
NSString *name = [itemDict objectForKey:(id)kSecAttrLabel];
if(acc != nil) {
NSArray *values = [NSArray arrayWithObjects: (id)name, (id)acc, (id)pwd, nil];
[arr addObject:(id)values];
}
}
[itemDicts release];
NSInteger c = arr.count;
NSString *cnt = [NSString stringWithFormat:#"%d", c];
[MessageBox Show: [arr objectAtIndex:10]];

Assertion failure in sqlite3 using XCode, binding problem?

-(void)updatepw{
databaseName=#"bestfb.sqlite";
NSArray *documnetPath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documnetDir =[documnetPath objectAtIndex:0];
databasePath=[documnetDir stringByAppendingPathComponent:databaseName];
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *update = [[NSString alloc] initWithFormat:#"update staff set pword = %# where staffID=1;", todb];
sqlite3_stmt *selectstmt;
const char *sql= (char *) update;
NSLog(#"new sql :%#", sql);
NSLog(#"values: %#", newpw.text);
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) ==SQLITE_OK){
NSLog(#"prepare failed");
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
else {
sqlite3_bind_text(selectstmt, 1, [todb UTF8String], -1, SQLITE_TRANSIENT);
NSLog(#"binding done");
}
int success1 = sqlite3_step(selectstmt);
if (success1 != SQLITE_DONE) {
NSAssert1(0, #"Error: failed to save priority with message '%s'.", sqlite3_errmsg(database));
}
sqlite3_finalize(selectstmt);
}
sqlite3_close(database);
}
Hi all, I've been working on solving the error for hours.
I could not get the database to update, it would just crash whenever I tries to update.
Anyone who can help is the most welcome!
Please be gentle, as I am only a newbie to XCode.
I think you have missed the single quotes in the below sentence before and after %#
replace with this.
NSString *update = [[NSString alloc] initWithFormat:#"update staff set pword = '%#' where staffID=1;", todb];

help needed with sqlite manager

hi i m using sqlite manager now the manager is showing me tables inside the database but when i m running my code it says that the table is not found. Here is my code. please can someone point out my mistake.
- (IBAction)saveDatabase
{
float x = [_openingBalance.text floatValue];
NSNumber *amount = [NSNumber numberWithFloat:x];
float y = [_monthlyBudget.text floatValue];
NSNumber *budget = [NSNumber numberWithFloat:y];
_uuid = [[UIDevice currentDevice] uniqueIdentifier];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"Accounts.sqlite"];
sqlite3 *database;
if(sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "insert into Account (name, type , currencyCode , parentAccount , currentBalance , monthlyBudget , monthlyBudgetPercentage ) VALUES ( ? , ? , ? , ? , ? , ? , ?)";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_text( compiledStatement, 1, [_accountName.text UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(compiledStatement, 2, 1);
sqlite3_bind_text(compiledStatement, 3, [#"PKR" UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(compiledStatement, 4, 1);
sqlite3_bind_double(compiledStatement, 5, [amount doubleValue]);
sqlite3_bind_double(compiledStatement, 6, [budget doubleValue]);
sqlite3_bind_int(compiledStatement, 7, 0);
}
if(sqlite3_step(compiledStatement) != SQLITE_DONE ) {
NSLog( #"Error: %s", sqlite3_errmsg(database) );
} else {
NSLog( #"Insert into row id = %lld", sqlite3_last_insert_rowid(database));
}
char* errmsg;
sqlite3_exec(database, "COMMIT", NULL, NULL, &errmsg);
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
}
}
The error is Error: no such table: Account
Use this for your file path..
NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Accounts.sqlite"];

Resources