FMDB Swift SQL Get Number of Rows in Table - sqlite

FMDB seems to have lots of functions to deal with columns but none for rows. All I am trying to do is find the number of rows in a table.
func getTableRows() {
sharedInstance.database!.open()
let sqlStatement = "SELECT COUNT(*) FROM NAMESTABLE"
var resultSet: FMResultSet! = sharedInstance.database!.executeQuery(sqlStatement, withArgumentsInArray: nil)
if (resultSet != nil) {
let rowCount = XXXX
NSLog("Table Rows = %i",rowCount)
}
sharedInstance.database!.close()
}
I have tried various approaches with the XXXX but no joy. Am I going about this the wrong way? Many thanks.

try this:
func getTableRows() {
sharedInstance.database!.open()
let sqlStatement = "SELECT COUNT(field) FROM table_name"
var resultSet: FMResultSet! = sharedInstance.database!.executeQuery(sqlStatement, withArgumentsInArray: nil)
if (resultSet != nil) {
let rowCount = XXXX
NSLog("Table Rows = %i",rowCount)
}
sharedInstance.database!.close()
}

Related

Rusqlite query with SUM panics with "InvalidColumnType(0, Null)"

I have this working code:
extern crate rusqlite;
use rusqlite::Connection;
fn main() {
let conn = Connection::open("db.sqlite").unwrap();
conn.execute("CREATE TABLE toto (size INTEGER NOT NULL DEFAULT 0);", &[]).unwrap();
conn.execute("INSERT INTO toto(size) VALUES (42);", &[]).unwrap();
let filter = 0;
let i: i64 = conn.query_row("SELECT SUM(size) FROM toto", &[], |r| r.get(0)).unwrap();
println!("Coucou");
println!("Coucou: {}", i);
}
But if I switch
"SELECT SUM(size) FROM toto", &[]
to
"SELECT SUM(size) FROM toto WHERE size=?1", &[&filter]
and re-run, it panics:
rm db.sqlite
RUST_BACKTRACE=1 cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/testsqlite`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidColumnType(0, Null)', /checkout/src/libcore/result.rs:860
If I execute this query in sqliteman, it works, so why does rusqlite panic?
If I run your query directly in the sqlite command line utility, there is no value, the result is NULL:
sqlite> SELECT SUM(size) FROM toto WHERE size=42;
sqlite> SELECT coalesce(SUM(size), 'NULL!') FROM toto WHERE size=42;
NULL!
sqlite>
Since there are no rows matching the where clause, the sum is NULL:
If there are no non-NULL input rows then sum() returns NULL but total() returns 0.0
Your NULL result cannot be converted to an i64, so you get an error:
InvalidColumnType(0, Null)
If you print that error out, it says the same thing:
let i: i64 = conn.query_row("SELECT SUM(size) FROM toto WHERE size = ?1", &[&filter], |r| {
match r.get_checked(0) {
Ok(v) => v,
Err(e) => panic!("query_row error: {}", e),
}
}).expect("select failed");
query_row error: Invalid column type Null at index: 0
Fixing it Rust-side
If you update your code to account for a NULL by using an Option, it will correctly execute:
let i: Option<i64> = conn.query_row(
"SELECT SUM(size) FROM toto WHERE size = ?1",
&[&filter],
|r| r.get(0)
).expect("select failed");
You can then use i.unwrap_or(0).
Fixing it SQL-side with TOTAL
let i: f64 = conn.query_row(
"SELECT TOTAL(size) FROM toto WHERE size = ?1",
&[&filter],
|r| r.get(0)
).expect("select failed");
Note that we switched to a f64.
Fixing it SQL-side with COALESCE
let i: i64 = conn.query_row(
"SELECT COALESCE(SUM(size), 0) FROM toto WHERE size = ?1",
&[&filter],
|r| r.get(0)
).expect("select failed");

F# Async - An item with the same key has already been added

I am trying some async ops in f# but w/o much luck. I am trying to grab records from the db and perform operations on each record in Parallel.
let IsA1 companyId =
query { for comp in db.Company do
join cc in db.CC on (comp.CompanyId = int(cc.CompanyId))
join pp in db.PP on (cc.PartId = pp.PartId)
join tl in db.TL on (pp.CompanyId = tl.CompanyId)
where (comp.CompanyId = companyId)
select (comp.CompanyId > 0)
}
|> Seq.length |> fun len -> len > 0
let IsA2 companyId =
query { for t in db.Title do
join pp in db.PP on (t.Tid = pp.Tid)
join comp in db.Company on (pp.CompanyId = comp.CompanyId)
where (comp.CompanyId = companyId)
select (comp.CompanyId > 0)
}
|> Seq.length |> fun len -> len > 0
let GetAffiliations id =
async {
if (IsA1 id) then return "AffilBBB"
elif (IsA2 id) then return "AffilCCD"
else return Unknown
}
let ProcessCompany (company:dbSchema.ServiceTypes.Company) =
async {
let grp = GetAffiliations company.CompanyId
let result = { Id=company.CompanyId; Name=company.Name; Affiliations=grp; ContactType="ok"; }
return result
}
let GetCompanyNames =
let companies = db.Company |> Seq.distinctBy(fun d -> d.CompanyId)
companies
|> Seq.map(fun co -> ProcessCompany co)
|> Async.Parallel
|> Async.RunSynchronously
When I run the above code, I get error:
System.ArgumentException: An item with the same key has already been added.
The error is occurring as a result of another function call inside async { }:
let grp = GetAffiliations company.CompanyId
I am sure its a newbie issue, but I am not sure what the issue is. I even tried making the call inside of the async{ } another async call and used let! grp = (GetAffiliations company.CompanyId) but that does not resolve.
Because the two concurrent queries are sharing the same context, when the second result is added to the same context, you get an error saying that the context already has an item with the same key.
Using distinct instances of the 'db' context for each of the queries, should solve your issue.

Why doesn't SQLite JOIN work?

I've a problem with the following function. Its just the join I think. By using sql statement "SELECT * FROM pkw", I got the results. Both tables are filled with data.
Do you see the mistake?
function gotoauftrag(id) {
db = window.sqlitePlugin.openDatabase(shortName, version, displayName,maxSize);
var list = '';
var sql = "SELECT DISTINCT p.name FROM pkw p INNER JOIN ta_pkw tp ON tp.pkw_id = p.pkw_id AND tp.ta_id = ?";
db.transaction(function (tx) {
tx.executeSql(sql, [id], function (tx, results) {
if (results.rows.length > 0) {
document.getElementById('auftrag_pkw').innerHTML = '';
for (i = 0; i < results.rows.length; i++) {
r = results.rows.item(i);
list = '<li>'+r['name']+'<span class="ui-li-count">1</span></li>';
document.getElementById('auftrag_pkw').innerHTML += list;
$('#auftrag_pkw').listview('refresh');
}
}
});
});
$('#auftrag_pkw').listview('refresh');
}
I don't believe you are able to bind to the JOIN predicate. Try using the WHERE clause instead.
SELECT DISTINCT
p.name
FROM pkw p
INNER JOIN ta_pkw tp
ON tp.pkw_id = p.pkw_id
WHERE
tp.ta_id = ?
Also, you probably should be doing the ta_id selection before your join. The above will do a natural join on pkw_id, THEN it will filter the results based on ta_id.

how to fetch two same fields data from db [HTML5]?

this.db.transaction(function (tx)
{
tx.executeSql('SELECT tsk.*, cont.firstName, cont.lastName ,cont1.firstName, cont1.lastName, list.listId FROM tbl_tasks tsk, tbl_contacts cont,tbl_contactequests cont1, tbl_lists list WHERE (tsk.assignedId=0 or tsk.assignedId=cont.contactId or tsk.assignedId=cont1.contactRequestId) and tsk.taskCategoryType != "INBOX_NOT_ACCEPTED" and list.listId=tsk.listId and list.listId='+window.defaultlistid+' group by tsk.taskId', [], enyo.bind(this,this.queryResponse), enyo.bind(this,this.errorHandler));//call queryResponse
}.bind(this));
Now as you can see cont.firstName (Table tbl_contacts) & cont1.firstName has (Table tbl_contactequests) has same fields first name
for (var i = 0; i < len; i++)
{
list[i] = results.rows.item(i);
fname = list[i].firstName;
lname = list[i].lastName;
fullname = fname+' '+lname;
//alert(fullname);
if(list[i].assignedId==0)
{list[i].name = '';}
else
{list[i].name=fullname;}
}
with this loop i can able to featch first value of tbl_contacts field firstname.Now suppose if i can't to access tbl_contactequests table firstname.
Use AS keyword for SQL query:
'SELECT tsk.*,
cont.firstName AS cFirstName,
cont.lastName ,
cont1.firstName AS c1FirstName,
cont1.lastName, list.listId
FROM tbl_tasks tsk, tbl_contacts cont,
tbl_contactequests cont1, tbl_lists list
WHERE (tsk.assignedId=0 OR tsk.assignedId=cont.contactId OR
tsk.assignedId=cont1.contactRequestId) AND
tsk.taskCategoryType != "INBOX_NOT_ACCEPTED" AND
list.listId=tsk.listId AND list.listId='+window.defaultlistid+'
GROUP BY tsk.taskId'

Correct way to access Multi-Dimensional Array with string indexes in Lua?

I'm trying to have a good access to multi-dimensional arrays with string indexes in Lua, here's basically what I'm trying to do:
rules =
{
{"S_RIGHT", "A_STOP", "S_RESULT"},
}
matrix = {}
for _,v in pairs(rules) do
if( matrix[ v[1] ] == nil ) then
matrix[ v[1] ] = {}
end
matrix[ v[1] ][ v[2] ] = v[3]
end
-- results in error ( attempt to index field 'S_NO' a nil value)
var = matrix["S_NO"]["S_RESULT"]
assert(var == nil, "Var should be nil")
A way to do it but quite verbose is:
var = matrix["S_NO"]
if var ~= nil then
var = var["S_RESULT"]
end
assert(var == nil, "Var should be nil")
Is there a way to make the first case to work ? ( less verbose )
Ok,
Found the answer.
If matrix is going to be read-only a correct approach would be:
local empty = {}
setmetatable(matrix, {__index=function() return empty end})
If I would like to allow writes and it's specifically two levels of tables, I could do:
setmetatable(matrix, {__index=function(t,k) local new={} rawset(t,k,new) return new end}
Hope this helps!

Resources