sqlite3_exec without callback - sqlite

Is there any way by which I can get the sqlite3_exec() result without through callback?
When I do search I want to get the result directly, most like a return of the function or as OUT param?
Thanks.

I have written some code that allows us to read data from open db (db) according to sql query (zSql) without callback.
Please note, that this code works but might still need some work (for example, I'm not sure if we need to free the text data or not...)
int RunSqlNoCallback(sqlite3 * db, const char * zSql)
{
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_prepare_v2(db, zSql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
return rc;
int rowCount = 0;
rc = sqlite3_step(stmt);
while (rc != SQLITE_DONE && rc != SQLITE_OK)
{
rowCount++;
int colCount = sqlite3_column_count(stmt);
for (int colIndex = 0; colIndex < colCount; colIndex++)
{
int type = sqlite3_column_type(stmt, colIndex);
const char * columnName = sqlite3_column_name(stmt, colIndex);
if (type == SQLITE_INTEGER)
{
int valInt = sqlite3_column_int(stmt, colIndex);
printf("columnName = %s, Integer val = %d", columnName, valInt);
}
else if (type == SQLITE_FLOAT)
{
double valDouble = sqlite3_column_double(stmt, colIndex);
printf("columnName = %s,Double val = %f", columnName, valDouble);
}
else if (type == SQLITE_TEXT)
{
const unsigned char * valChar = sqlite3_column_text(stmt, colIndex);
printf("columnName = %s,Text val = %s", columnName, valChar);
free(valChar);
}
else if (type == SQLITE_BLOB)
{
printf("columnName = %s,BLOB", columnName);
}
else if (type == SQLITE_NULL)
{
printf("columnName = %s,NULL", columnName);
}
}
printf("Line %d, rowCount = %d", rowCount, colCount);
rc = sqlite3_step(stmt);
}
rc = sqlite3_finalize(stmt);
return rc;
}

sqlite3_exec is a convenience wrapper.
If you don't need a callback you should use underlying functions: sqlite3_prepare_v2(), sqlite3_step(), and sqlite3_finalize() directly.
Compile sql query with sqlite3_prepare_v2()
Run sqlite3_step() as many times as necessary to execute the query, use
sqlite3_column_bytes() etc to retrieve the data
Destroy prepared query with sqlite3_finalize()
But it requires more coding and careful error handling.

Calling the callback is how sqlite3_exec is designed to work.
If you want a function that allocates all the memory for the result and returns that, you need a different function, like sqlite3_get_table.

The call back is the mechanism that sqlite3_exec () uses to return one or more results. It looks like its primary use is with a select SQL statement. If the select SQL statement returns multiple rows of results then the call back function specified is called by the sqlite functionality for each row.
I am not sure if you are using C or C++ or some other language however I have a possible solution for you using C with SQLite.
The call back function has as its first argument a void pointer and this can point to pretty much anything. For instance it can point to a struct that contains a pointer to a memory area allocated for the result along with parameters indicating the size of the memory area.
I put an answer to this stackoverflow question, use of sql3_exec, with an example of using a call back that populates a C struct with the results of a select SQL statement. In this example I have a call back that takes one or more row results from a select and transform the results into the data values to put into a C struct. When the sqlite3_exec() function returns, I then process the results from the select using the C struct.
This may be what you are looking for in that you can create your select SQL statement, set up the results struct, call sqlite3_exec() specifying the results struct along with the function pointer to the call back to process the results using the results struct, and when sqlite3_exec() return you have the results of your select. The results of the select will be at the point where you called sqlite3_exec().

Related

Passing value by reference to Qore script function from C++ code

I need pass returnValue to a method as argument passed by reference and adjust original var value when function id done. So using ReferenceArgumentHelper class.
What's wrong in code bellow when returnValue is unintentionally deleted (when it is a node, i.e. string) and valgrind detects it. callMethod("onFunctionExit" calls an Qore script method and I can see there correct returnValue value. I suspect it's deleted when exiting onFunctionExit when ReferenceArgumentHelper is destroyed. rah.getArg() references reference variable, so it should not be deleted in callMethod.
DLLLOCAL ThreadDebugEnum callMethod(const char* name, const ThreadDebugEnum defaultResult, QoreProgram *pgm, int paramCount, AbstractQoreNode** params, ExceptionSink* xsink) {
int rv;
QoreListNode* l = new QoreListNode();
qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
if (i == qore_program_to_object_map.end()) {
return defaultResult;
}
i->second->ref();
l->push(i->second);
for (int i=0; i<paramCount; i++) {
if (params[i])
params[i]->ref();
l->push(params[i]);
}
rv = qo->intEvalMethod(name, l, xsink);
l->deref(xsink);
return (ThreadDebugEnum) rv;
}
DLLLOCAL virtual ThreadDebugEnum onFunctionExit(QoreProgram *pgm, const StatementBlock *blockStatement, QoreValue& returnValue, ExceptionSink* xsink) {
AbstractQoreNode* params[2];
params[0] = getLocation(blockStatement);
ReferenceArgumentHelper rah(returnValue.takeNode(), xsink); // grab node from returnValue and pass to helper
params[1] = rah.getArg(); // caller owns ref
ThreadDebugEnum rv = callMethod("onFunctionExit", DBG_SB_RUN, pgm, 2, params, xsink);
AbstractQoreNode* rc = rah.getOutputValue(); // caller owns ref
returnValue.assign(rc); // takes reference
// returnValue.ref();
}
return rv;
}
When looking deeply I did not get why compiler is happy with code in /lib/ReferenceArgumentHelper.cpp:
struct lvih_intern {
LocalVar lv;
ExceptionSink* xsink;
ReferenceNode* ref;
DLLLOCAL lvih_intern(AbstractQoreNode* val, ExceptionSink* xs) : lv("ref_arg_helper", 0), xsink(xs) {
printd(5, "ReferenceArgumentHelper::ReferenceArgumentHelper() instantiating %p (val: %p type: '%s') \n", &lv, val, val ? val->getTypeName() : "n/a");
lv.instantiate(val); <--------------
VarRefNode* vr = new VarRefNode(strdup("ref_arg_helper"), VT_LOCAL);
vr->ref.id = &lv;
ref = new ReferenceNode(vr, 0, vr, 0);
}
class LocalVar {
....
DLLLOCAL void instantiate(QoreValue nval) const {
What is behind conversion AbstractQoreNode* to QoreValue in method call? I did not find an overloaded operator or so. I'm looking what exactly happens with references.
** EDIT **
To make a long story short, ReferenceArgumentHelper was buggy; it hadn't been used in years and was not up to date. The class has been fixed which should fix your issue I hope.
Thank you for pointing this out, and let me know if you have any further problems with this or the fix to the affected code.

Storing arbitrary bytes in RocksDB

RocksDB states that it can store arbitrary data but the API only supports std::string types. I want to store std::vector<T> values and it appears if I want to do this then I must convert it into a std::string.
Is there a less brittle way to storing arbitrary types?
I tend to use the following to pack/unpack structures/classes to std::string using a template to automatically adjust to their size.
template <typename T>
std::string Pack(const T* data)
{
std::string d(sizeof(T), L'\0');
memcpy(&d[0], data, d.size());
return d;
}
template <typename T>
std::unique_ptr<T> Unpack(const std::string& data)
{
if (data.size() != sizeof(T))
return nullptr;
auto d = std::make_unique<T>();
memcpy(d.get(), data.data(), data.size());
return d;
}
So the following client code can pack and unpack a structure into the database:
// Test structure
BOB b = {};
b.a = 12;
b.b = 144;
b.c[0] = 's';
b.c[1] = '\0';
// Write to the db
status = pDb->Put(rocksdb::WriteOptions(), key, Pack(&b));
// Read from db with same key
std::string result;
status = pDb->Get(rocksdb::ReadOptions(), key, &result);
std::unique_ptr<BOB> pBob = Unpack<BOB>(result);
if (b.a == pBob->a && b.b == pBob->b && b.c[0] == pBob->c[0])
{
printf("Structure matches!\n");
}
else
{
printf("Structure doesn't match!\n");
}
As a key-value store, RocksDB can store "arbitrary byte array". For your use case, you would need to have some way to serialize your std::vector<T> to a byte array so that it can be put into a std::string. Note that the input std::string does not need to be zero-terminated.

Xcode - sql Select a single value does not work

In my app, I trying to get the single id from data base using the query:
SELECT _id FROM rules where codigo_rest = 2345
I am passing that query to the following function:
-(NSString *)selectIDrest:(NSString *)query{
NSString * retval;
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
int uniqueId = sqlite3_column_int(statement, 0);
NSLog(#"int %i",uniqueId);
retval = [NSString stringWithFormat:#"%d",uniqueId];
}
sqlite3_finalize(statement);
}
NSLog(#"%#",retval);
return retval;
}
but the retval is alway 0., while table content id is different (1,2,3,4 ...etc).
By NSlogs, I realize that while (sqlite3_step(statement) == SQLITE_ROW) is never executed.
What is my fault?
You are never executing the query, you only prepared it to be executed. You need to call sqllite3_step to read the first row. The you can call sqllit3_column_int.
You can see how to call it in this tutorial: http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app

Accessing an SQLite Database in Swift

I'm looking for a way to access an SQLite database in my app with Swift code.
I know that I can use an SQLite Wrapper in Objective C and use the bridging header, but I'd rather be able to do this project entirely in Swift. Is there a way to do this, if so, can someone point me to a reference that shows how to submit a query, retrieve rows, etc?
While you should probably use one of the many SQLite wrappers, if you wanted to know how to call the SQLite library yourself, you would:
Configure your Swift project to handle SQLite C calls. If using Xcode 9 or later, you can simply do:
import SQLite3
Create/open database.
let fileURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("test.sqlite")
// open database
var db: OpaquePointer?
guard sqlite3_open(fileURL.path, &db) == SQLITE_OK else {
print("error opening database")
sqlite3_close(db)
db = nil
return
}
Note, I know it seems weird to close the database upon failure to open, but the sqlite3_open documentation makes it explicit that we must do so to avoid leaking memory:
Whether or not an error occurs when it is opened, resources associated with the database connection handle should be released by passing it to sqlite3_close() when it is no longer required.
Use sqlite3_exec to perform SQL (e.g. create table).
if sqlite3_exec(db, "create table if not exists test (id integer primary key autoincrement, name text)", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
Use sqlite3_prepare_v2 to prepare SQL with ? placeholder to which we'll bind value.
var statement: OpaquePointer?
if sqlite3_prepare_v2(db, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "foo", -1, SQLITE_TRANSIENT) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding foo: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting foo: \(errmsg)")
}
Note, that uses the SQLITE_TRANSIENT constant which can be implemented as follows:
internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
Reset SQL to insert another value. In this example, I'll insert a NULL value:
if sqlite3_reset(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error resetting prepared statement: \(errmsg)")
}
if sqlite3_bind_null(statement, 1) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding null: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting null: \(errmsg)")
}
Finalize prepared statement to recover memory associated with that prepared statement:
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nil
Prepare new statement for selecting values from table and loop through retrieving the values:
if sqlite3_prepare_v2(db, "select id, name from test", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing select: \(errmsg)")
}
while sqlite3_step(statement) == SQLITE_ROW {
let id = sqlite3_column_int64(statement, 0)
print("id = \(id); ", terminator: "")
if let cString = sqlite3_column_text(statement, 1) {
let name = String(cString: cString)
print("name = \(name)")
} else {
print("name not found")
}
}
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nil
Close database:
if sqlite3_close(db) != SQLITE_OK {
print("error closing database")
}
db = nil
For Swift 2 and older versions of Xcode, see previous revisions of this answer.
The best you can do is import the dynamic library inside a bridging header:
Add libsqlite3.dylib to your "Link Binary With Libraries" build phase
Create a "Bridging-Header.h" and add #import <sqlite3.h> to the top
set "Bridging-Header.h" for the "Objective-C Bridging Header" setting in Build Settings under "Swift Compiler - Code Generation"
You will then be able to access all of the c methods like sqlite3_open from your swift code.
However, you may just want to use FMDB and import that through the bridging header as that is a more object oriented wrapper of sqlite. Dealing with C pointers and structs will be cumbersome in Swift.
I too was looking for some way to interact with SQLite the same way I was used to doing previously in Objective-C. Admittedly, because of C compatibility, I just used the straight C API.
As no wrapper currently exists for SQLite in Swift and the SQLiteDB code mentioned above goes a bit higher level and assumes certain usage, I decided to create a wrapper and get a bit familiar with Swift in the process. You can find it here: https://github.com/chrismsimpson/SwiftSQLite.
var db = SQLiteDatabase();
db.open("/path/to/database.sqlite");
var statement = SQLiteStatement(database: db);
if ( statement.prepare("SELECT * FROM tableName WHERE Id = ?") != .Ok )
{
/* handle error */
}
statement.bindInt(1, value: 123);
if ( statement.step() == .Row )
{
/* do something with statement */
var id:Int = statement.getIntAt(0)
var stringValue:String? = statement.getStringAt(1)
var boolValue:Bool = statement.getBoolAt(2)
var dateValue:NSDate? = statement.getDateAt(3)
}
statement.finalizeStatement(); /* not called finalize() due to destructor/language keyword */
I've created an elegant SQLite library written completely in Swift called SwiftData.
Some of its feature are:
Bind objects conveniently to the string of SQL
Support for transactions and savepoints
Inline error handling
Completely thread safe by default
It provides an easy way to execute 'changes' (e.g. INSERT, UPDATE, DELETE, etc.):
if let err = SD.executeChange("INSERT INTO Cities (Name, Population, IsWarm, FoundedIn) VALUES ('Toronto', 2615060, 0, '1793-08-27')") {
//there was an error during the insert, handle it here
} else {
//no error, the row was inserted successfully
}
and 'queries' (e.g. SELECT):
let (resultSet, err) = SD.executeQuery("SELECT * FROM Cities")
if err != nil {
//there was an error during the query, handle it here
} else {
for row in resultSet {
if let name = row["Name"].asString() {
println("The City name is: \(name)")
}
if let population = row["Population"].asInt() {
println("The population is: \(population)")
}
if let isWarm = row["IsWarm"].asBool() {
if isWarm {
println("The city is warm")
} else {
println("The city is cold")
}
}
if let foundedIn = row["FoundedIn"].asDate() {
println("The city was founded in: \(foundedIn)")
}
}
}
Along with many more features!
You can check it out here
Yet another SQLite wrapper for Swift 2 and Swift 3: http://github.com/groue/GRDB.swift
Features:
An API that will look familiar to users of ccgus/fmdb
A low-level SQLite API that leverages the Swift standard library
A pretty Swift query interface for SQL-allergic developers
Support for the SQLite WAL mode, and concurrent database access for extra performance
A Record class that wraps result sets, eats your custom SQL queries for breakfast, and provides basic CRUD operations
Swift type freedom: pick the right Swift type that fits your data. Use Int64 when needed, or stick with the convenient Int. Store and read NSDate or NSDateComponents. Declare Swift enums for discrete data types. Define your own database-convertible types.
Database Migrations
Speed: https://github.com/groue/GRDB.swift/wiki/Performance
AppDelegate.swift
func createDatabase()
{
var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let directory:String=path[0]
let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")
print(DBpath)
if (FileManager.default.fileExists(atPath: DBpath))
{
print("Successfull database create")
}
else
{
let pathfrom:String=(Bundle.main.resourcePath! as NSString).appendingPathComponent("Food.sqlite")
var success:Bool
do {
try FileManager.default.copyItem(atPath: pathfrom, toPath: DBpath)
success = true
} catch _ {
success = false
}
if !success
{
print("database not create ")
}
else
{
print("Successfull database new create")
}
}
}
Database.swift
import UIKit
class database: NSObject
{
func databasePath() -> NSString
{
var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let directory:String=path[0]
let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")
if (FileManager.default.fileExists(atPath: DBpath))
{
return DBpath as NSString
}
return DBpath as NSString
}
func ExecuteQuery(_ str:String) -> Bool
{
var result:Bool=false
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if (sqlite3_open(DBpath, &db)==SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
if (sqlite3_step(stmt) == SQLITE_DONE)
{
result=true
}
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
return result
}
func SelectQuery(_ str:String) -> Array<Dictionary<String,String>>
{
var result:Array<Dictionary<String,String>>=[]
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
while (sqlite3_step(stmt) == SQLITE_ROW)
{
var i:Int32=0
let icount:Int32=sqlite3_column_count(stmt)
var dict=Dictionary<String, String>()
while i < icount
{
let strF=sqlite3_column_name(stmt, i)
let strV = sqlite3_column_text(stmt, i)
let rFiled:String=String(cString: strF!)
let rValue:String=String(cString: strV!)
//let rValue=String(cString: UnsafePointer<Int8>(strV!))
dict[rFiled] = rValue
i += 1
}
result.insert(dict, at: result.count)
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
}
return result
}
func AllSelectQuery(_ str:String) -> Array<Model>
{
var result:Array<Model>=[]
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
while (sqlite3_step(stmt) == SQLITE_ROW)
{
let mod=Model()
mod.id=String(cString: sqlite3_column_text(stmt, 0))
mod.image=String(cString: sqlite3_column_text(stmt, 1))
mod.name=String(cString: sqlite3_column_text(stmt, 2))
mod.foodtype=String(cString: sqlite3_column_text(stmt, 3))
mod.vegtype=String(cString: sqlite3_column_text(stmt, 4))
mod.details=String(cString: sqlite3_column_text(stmt, 5))
result.insert(mod, at: result.count)
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
}
return result
}
}
Model.swift
import UIKit
class Model: NSObject
{
var uid:Int = 0
var id:String = ""
var image:String = ""
var name:String = ""
var foodtype:String = ""
var vegtype:String = ""
var details:String = ""
var mealtype:String = ""
var date:String = ""
}
Access database :
let DB=database()
var mod=Model()
database Query fire :
var DailyResult:Array<Model> = DB.AllSelectQuery("select * from food where foodtype == 'Sea Food' ORDER BY name ASC")
This is by far the best SQLite library that I've used in Swift: https://github.com/stephencelis/SQLite.swift
Look at the code examples. So much cleaner than the C API:
import SQLite
let db = try Connection("path/to/db.sqlite3")
let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String?>("name")
let email = Expression<String>("email")
try db.run(users.create { t in
t.column(id, primaryKey: true)
t.column(name)
t.column(email, unique: true)
})
// CREATE TABLE "users" (
// "id" INTEGER PRIMARY KEY NOT NULL,
// "name" TEXT,
// "email" TEXT NOT NULL UNIQUE
// )
let insert = users.insert(name <- "Alice", email <- "alice#mac.com")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice#mac.com')
for user in try db.prepare(users) {
print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
// id: 1, name: Optional("Alice"), email: alice#mac.com
}
// SELECT * FROM "users"
let alice = users.filter(id == rowid)
try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
// UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
// WHERE ("id" = 1)
try db.run(alice.delete())
// DELETE FROM "users" WHERE ("id" = 1)
try db.scalar(users.count) // 0
// SELECT count(*) FROM "users"
The documentation also says that "SQLite.swift also works as a lightweight, Swift-friendly wrapper over the C API," and follows with some examples of that.
You can use this library in Swift for SQLite
https://github.com/pmurphyjam/SQLiteDemo
SQLiteDemo
SQLite Demo using Swift with SQLDataAccess class written in Swift
Adding to Your Project
You only need three files to add to your project
* SQLDataAccess.swift
* DataConstants.swift
* Bridging-Header.h
Bridging-Header must be set in your Xcode's project 'Objective-C Bridging Header' under 'Swift Compiler - General'
Examples for Use
Just follow the code in ViewController.swift to see how to write simple SQL with SQLDataAccess.swift
First you need to open the SQLite Database your dealing with
let db = SQLDataAccess.shared
db.setDBName(name:"SQLite.db")
let opened = db.openConnection(copyFile:true)
If openConnection succeeded, now you can do a simple insert into Table AppInfo
//Insert into Table AppInfo
let status = db.executeStatement("insert into AppInfo (name,value,descrip,date) values(?,?,?,?)",
”SQLiteDemo","1.0.2","unencrypted",Date())
if(status)
{
//Read Table AppInfo into an Array of Dictionaries
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
See how simple that was!
The first term in db.executeStatement is your SQL as String, all the terms that follow are a variadic argument list of type Any, and are your parameters in an Array. All these terms are separated by commas in your list of SQL arguments. You can enter Strings, Integers, Date’s, and Blobs right after the sequel statement since all of these terms are considered to be parameters for the sequel. The variadic argument array just makes it convenient to enter all your sequel in just one executeStatement or getRecordsForQuery call. If you don’t have any parameters, don’t enter anything after your SQL.
The results array is an Array of Dictionary’s where the ‘key’ is your tables column name, and the ‘value’ is your data obtained from SQLite. You can easily iterate through this array with a for loop or print it out directly or assign these Dictionary elements to custom data object Classes that you use in your View Controllers for model consumption.
for dic in results as! [[String:AnyObject]] {
print(“result = \(dic)”)
}
SQLDataAccess will store, text, double, float, blob, Date, integer and long long integers.
For Blobs you can store binary, varbinary, blob.
For Text you can store char, character, clob, national varying character, native character, nchar, nvarchar, varchar, variant, varying character, text.
For Dates you can store datetime, time, timestamp, date.
For Integers you can store bigint, bit, bool, boolean, int2, int8, integer, mediumint, smallint, tinyint, int.
For Doubles you can store decimal, double precision, float, numeric, real, double. Double has the most precision.
You can even store Nulls of type Null.
In ViewController.swift a more complex example is done showing how to insert a Dictionary as a 'Blob'. In addition SQLDataAccess
understands native Swift Date() so you can insert these objects with out converting, and it will convert them to text and store them,
and when retrieved convert them back from text to Date.
Of course the real power of SQLite is it's Transaction capability. Here you can literally queue up 400 SQL statements with parameters
and insert them all at once which is really powerful since it's so fast. ViewController.swift also shows you an example of how to do this.
All you're really doing is creating an Array of Dictionaries called 'sqlAndParams', in this Array your storing Dictionaries with two keys
'SQL' for the String sequel statement or query, and 'PARAMS' which is just an Array of native objects SQLite understands for that query.
Each 'sqlParams' which is an individual Dictionary of sequel query plus parameters is then stored in the 'sqlAndParams' Array.
Once you've created this array, you just call.
let status = db.executeTransaction(sqlAndParams)
if(status)
{
//Read Table AppInfo into an Array of Dictionaries for the above Transactions
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
In addition all executeStatement and getRecordsForQuery methods can be done with simple String for SQL query and an Array for the parameters needed by the query.
let sql : String = "insert into AppInfo (name,value,descrip) values(?,?,?)"
let params : Array = ["SQLiteDemo","1.0.0","unencrypted"]
let status = db.executeStatement(sql, withParameters: params)
if(status)
{
//Read Table AppInfo into an Array of Dictionaries for the above Transactions
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
An Objective-C version also exists and is called the same SQLDataAccess, so now you can choose to write your sequel in Objective-C or Swift.
In addition SQLDataAccess will also work with SQLCipher, the present code isn't setup yet to work with it, but it's pretty easy to do, and
an example of how to do this is actually in the Objective-C version of SQLDataAccess.
SQLDataAccess is a very fast and efficient class, and can be used in place of CoreData which really just uses SQLite as it's underlying data
store without all the CoreData core data integrity fault crashes that come with CoreData.
I have written a SQLite3 wrapper library written in Swift.
This is actually a very high level wrapper with very simple API, but anyway, it has low-level C inter-op code, and I post here a (simplified) part of it to shows the C inter-op.
struct C
{
static let NULL = COpaquePointer.null()
}
func open(filename:String, flags:OpenFlag)
{
let name2 = filename.cStringUsingEncoding(NSUTF8StringEncoding)!
let r = sqlite3_open_v2(name2, &_rawptr, flags.value, UnsafePointer<Int8>.null())
checkNoErrorWith(resultCode: r)
}
func close()
{
let r = sqlite3_close(_rawptr)
checkNoErrorWith(resultCode: r)
_rawptr = C.NULL
}
func prepare(SQL:String) -> (statements:[Core.Statement], tail:String)
{
func once(zSql:UnsafePointer<Int8>, len:Int32, inout zTail:UnsafePointer<Int8>) -> Core.Statement?
{
var pStmt = C.NULL
let r = sqlite3_prepare_v2(_rawptr, zSql, len, &pStmt, &zTail)
checkNoErrorWith(resultCode: r)
if pStmt == C.NULL
{
return nil
}
return Core.Statement(database: self, pointerToRawCStatementObject: pStmt)
}
var stmts:[Core.Statement] = []
let sql2 = SQL as NSString
var zSql = UnsafePointer<Int8>(sql2.UTF8String)
var zTail = UnsafePointer<Int8>.null()
var len1 = sql2.lengthOfBytesUsingEncoding(NSUTF8StringEncoding);
var maxlen2 = Int32(len1)+1
while let one = once(zSql, maxlen2, &zTail)
{
stmts.append(one)
zSql = zTail
}
let rest1 = String.fromCString(zTail)
let rest2 = rest1 == nil ? "" : rest1!
return (stmts, rest2)
}
func step() -> Bool
{
let rc1 = sqlite3_step(_rawptr)
switch rc1
{
case SQLITE_ROW:
return true
case SQLITE_DONE:
return false
default:
database.checkNoErrorWith(resultCode: rc1)
}
}
func columnText(at index:Int32) -> String
{
let bc = sqlite3_column_bytes(_rawptr, Int32(index))
let cs = sqlite3_column_text(_rawptr, Int32(index))
let s1 = bc == 0 ? "" : String.fromCString(UnsafePointer<CChar>(cs))!
return s1
}
func finalize()
{
let r = sqlite3_finalize(_rawptr)
database.checkNoErrorWith(resultCode: r)
_rawptr = C.NULL
}
If you want a full source code of this low level wrapper, see these files.
https://github.com/Eonil/SQLite3/blob/master/Swift/Sources/Core.Statement.swift
https://github.com/Eonil/SQLite3/blob/master/Swift/Sources/Core.Database.swift
Configure your Swift project to handle SQLite C calls:
Create bridging header file to the project. See the Importing Objective-C into Swift section of the Using Swift with Cocoa and Objective-C. This bridging header should import sqlite3.h:
Add the libsqlite3.0.dylib to your project. See Apple's documentation regarding adding library/framework to one's project.
and used following code
func executeQuery(query: NSString ) -> Int
{
if sqlite3_open(databasePath! as String, &database) != SQLITE_OK
{
println("Databse is not open")
return 0
}
else
{
query.stringByReplacingOccurrencesOfString("null", withString: "")
var cStatement:COpaquePointer = nil
var executeSql = query as NSString
var lastId : Int?
var sqlStatement = executeSql.cStringUsingEncoding(NSUTF8StringEncoding)
sqlite3_prepare_v2(database, sqlStatement, -1, &cStatement, nil)
var execute = sqlite3_step(cStatement)
println("\(execute)")
if execute == SQLITE_DONE
{
lastId = Int(sqlite3_last_insert_rowid(database))
}
else
{
println("Error in Run Statement :- \(sqlite3_errmsg16(database))")
}
sqlite3_finalize(cStatement)
return lastId!
}
}
func ViewAllData(query: NSString, error: NSError) -> NSArray
{
var cStatement = COpaquePointer()
var result : AnyObject = NSNull()
var thisArray : NSMutableArray = NSMutableArray(capacity: 4)
cStatement = prepare(query)
if cStatement != nil
{
while sqlite3_step(cStatement) == SQLITE_ROW
{
result = NSNull()
var thisDict : NSMutableDictionary = NSMutableDictionary(capacity: 4)
for var i = 0 ; i < Int(sqlite3_column_count(cStatement)) ; i++
{
if sqlite3_column_type(cStatement, Int32(i)) == 0
{
continue
}
if sqlite3_column_decltype(cStatement, Int32(i)) != nil && strcasecmp(sqlite3_column_decltype(cStatement, Int32(i)), "Boolean") == 0
{
var temp = sqlite3_column_int(cStatement, Int32(i))
if temp == 0
{
result = NSNumber(bool : false)
}
else
{
result = NSNumber(bool : true)
}
}
else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_INTEGER
{
var temp = sqlite3_column_int(cStatement,Int32(i))
result = NSNumber(int : temp)
}
else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_FLOAT
{
var temp = sqlite3_column_double(cStatement,Int32(i))
result = NSNumber(double: temp)
}
else
{
if sqlite3_column_text(cStatement, Int32(i)) != nil
{
var temp = sqlite3_column_text(cStatement,Int32(i))
result = String.fromCString(UnsafePointer<CChar>(temp))!
var keyString = sqlite3_column_name(cStatement,Int32(i))
thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
}
result = NSNull()
}
if result as! NSObject != NSNull()
{
var keyString = sqlite3_column_name(cStatement,Int32(i))
thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
}
}
thisArray.addObject(NSMutableDictionary(dictionary: thisDict))
}
sqlite3_finalize(cStatement)
}
return thisArray
}
func prepare(sql : NSString) -> COpaquePointer
{
var cStatement:COpaquePointer = nil
sqlite3_open(databasePath! as String, &database)
var utfSql = sql.UTF8String
if sqlite3_prepare(database, utfSql, -1, &cStatement, nil) == 0
{
sqlite3_close(database)
return cStatement
}
else
{
sqlite3_close(database)
return nil
}
}
}
Sometimes, a Swift version of the "SQLite in 5 minutes or less" approach shown on sqlite.org is sufficient.
The "5 minutes or less" approach uses sqlite3_exec() which is a convenience wrapper for sqlite3_prepare(), sqlite3_step(), sqlite3_column(), and sqlite3_finalize().
Swift 2.2 can directly support the sqlite3_exec() callback function pointer as either a global, non-instance procedure func or a non-capturing literal closure {}.
Readable typealias
typealias sqlite3 = COpaquePointer
typealias CCharHandle = UnsafeMutablePointer<UnsafeMutablePointer<CChar>>
typealias CCharPointer = UnsafeMutablePointer<CChar>
typealias CVoidPointer = UnsafeMutablePointer<Void>
Callback Approach
func callback(
resultVoidPointer: CVoidPointer, // void *NotUsed
columnCount: CInt, // int argc
values: CCharHandle, // char **argv
columns: CCharHandle // char **azColName
) -> CInt {
for i in 0 ..< Int(columnCount) {
guard let value = String.fromCString(values[i])
else { continue }
guard let column = String.fromCString(columns[i])
else { continue }
print("\(column) = \(value)")
}
return 0 // status ok
}
func sqlQueryCallbackBasic(argc: Int, argv: [String]) -> Int {
var db: sqlite3 = nil
var zErrMsg:CCharPointer = nil
var rc: Int32 = 0 // result code
if argc != 3 {
print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
return 1
}
rc = sqlite3_open(argv[1], &db)
if rc != 0 {
print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
sqlite3_close(db)
return 1
}
rc = sqlite3_exec(db, argv[2], callback, nil, &zErrMsg)
if rc != SQLITE_OK {
print("ERROR: sqlite3_exec " + String.fromCString(zErrMsg)! ?? "")
sqlite3_free(zErrMsg)
}
sqlite3_close(db)
return 0
}
Closure Approach
func sqlQueryClosureBasic(argc argc: Int, argv: [String]) -> Int {
var db: sqlite3 = nil
var zErrMsg:CCharPointer = nil
var rc: Int32 = 0
if argc != 3 {
print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
return 1
}
rc = sqlite3_open(argv[1], &db)
if rc != 0 {
print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
sqlite3_close(db)
return 1
}
rc = sqlite3_exec(
db, // database
argv[2], // statement
{ // callback: non-capturing closure
resultVoidPointer, columnCount, values, columns in
for i in 0 ..< Int(columnCount) {
guard let value = String.fromCString(values[i])
else { continue }
guard let column = String.fromCString(columns[i])
else { continue }
print("\(column) = \(value)")
}
return 0
},
nil,
&zErrMsg
)
if rc != SQLITE_OK {
let errorMsg = String.fromCString(zErrMsg)! ?? ""
print("ERROR: sqlite3_exec \(errorMsg)")
sqlite3_free(zErrMsg)
}
sqlite3_close(db)
return 0
}
To prepare an Xcode project to call a C library such as SQLite, one needs to (1) add a Bridging-Header.h file reference C headers like #import "sqlite3.h", (2) add Bridging-Header.h to Objective-C Bridging Header in project settings, and (3) add libsqlite3.tbd to Link Binary With Library target settings.
The sqlite.org's "SQLite in 5 minutes or less" example is implemented in a Swift Xcode7 project here.
You can easlity configure SQLite with swift using single ton class as well.
Refer
https://github.com/hasyapanchasara/SQLite_SingleManagerClass
Method to create database
func methodToCreateDatabase() -> NSURL?{}
Method to insert, update and delete data
func methodToInsertUpdateDeleteData(strQuery : String) -> Bool{}
Method to select data
func methodToSelectData(strQuery : String) -> NSMutableArray{}

Use Collections java object in Processing.js

I'm in need of the Collections object but Processing.js keeps spitting back an error saying Collections is not defined as though it doesn't recognize it as an object. I'm trying to find the minimum value of an ArrayList by using the Collections.min function so this would be really useful.
ArrayList<int> aaa = new ArrayList<int> ();
println(aaa);
Collections<int> fff = new Collections<int> ();
println(fff);
The Collections object is not a Processing API object, but an underlying Java object, and is not available to all interpreters of Processing code (because not all interpreters are based on the JVM).
If you want to find the minimum value, it's three lines of code:
int minval = aaa.get(0);
for(int v: aaa) {
if(v < minval) { minval = v; }
}
Done, we have our minimum value. If we wrap this in a function, we can use it wherever we want:
int getMinValue(ArrayList<Integer> numberlist) {
int minval = numberlist.get(0);
for(int v: numberlist) {
if(v < minval) { minval = v; }
}
return minval;
}

Resources