I'm trying to get the row count of a QSqlQuery, the database driver is qsqlite
bool Database::runSQL(QSqlQueryModel *model, const QString & q)
{
Q_ASSERT (model);
model->setQuery(QSqlQuery(q, my_db));
rowCount = model->query().size();
return my_db.lastError().isValid();
}
The query here is a select query, but I still get -1;
If I use model->rowCount() I get only ones that got displayed, e.g 256, but select count(*) returns 120k results.
What's wrong about it?
This row count code extract works for SQLite3 based tables as well as handles the "fetchMore" issue associated with certain SQLite versions.
QSqlQuery query( m_database );
query.prepare( QString( "SELECT * FROM MyDatabaseTable WHERE SampleNumber = ?;"));
query.addBindValue( _sample_number );
bool table_ok = query.exec();
if ( !table_ok )
{
DATABASETHREAD_REPORT_ERROR( "Error from MyDataBaseTable", query.lastError() );
}
else
{
// only way to get a row count, size function does not work for SQLite3
query.last();
int row_count = query.at() + 1;
qDebug() << "getNoteCounts = " << row_count;
}
The documentation says:
Returns ... -1 if the size cannot be determined or if the database does not support reporting information about query sizes.
SQLite indeed does not support this.
Please note that caching 120k records is not very efficient (nobody will look at all those); you should somehow filter them to get the result down to a manageable size.
Related
I have spent ages searching for an answer to this, but i can't quite get my head around it.
Basically.I have a sqlite db on a sd card connected to a esp32. SQLite works perfectly and will return when using the standard sample code. For example:
rc = db_exec(db2, "Select * from domain_rank where domain between 'google.com' and 'google.com.z'");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}`
this looks at a "db_exec" function in the sketch then passes it to a "callback" function. Is there a way to do without this? All I want to do is count the number of records in a select statement.
Thanks
Andrew
Ok I think I may have found a solution
Putting it here just in case anyone else is interested.
String sql = "Select count(*) from surnames where name = 'MICHELLE'";
rc = sqlite3_prepare_v2(db1, sql.c_str(), 1000, &res, &tail);
if (rc != SQLITE_OK) {
String resp = "Failed to fetch data: ";
Serial.println(resp.c_str());
return;
}
while (sqlite3_step(res) == SQLITE_ROW) {
rec_count = sqlite3_column_int(res, 0);
}
Serial.println(rec_count);
can't quite get my head around what the while loop is doing counting the cells, i thought the sql count* query would just return an int value I could use directly. So I'm still a little confused.
Comments would be welcomed! If anyone has any better ideas?
Thanks
Andrew
I am new to go and trying to retrieve data from a sqlite database.
Im using github.com/mattn/go-sqlite3 as sqlite driver.
The query I m sending does not return any results even though it should. I tried the query my programme is generating manually and it returns data as it should when I use the query manually as well as when I send it via my programme.
Here is my code:
for index := range Array {
id, _ := strconv.Atoi(Array[index])
rand.Seed(time.Now().UnixNano())
RandomNr := rand.Intn(100)
fmt.Printf("index: %d - randomnr: %d \n", id, RandomNr)
rows, errROW := db.Query("SELECT user.id,user.name,stage.link,player.url,player.characterchance,player.chance FROM user,stage,player WHERE user.id = '%d' AND '%d' <= user.chance AND stage.user = user.id AND stage.domain = player.id AND player.chance > 0 ORDER BY player.id ASC \n",id, RandomNr)//.Scan(&idr, &name, &link, &url, &characterchance, &chance)
//this is what the finished query looks like and it returns the rows as its supposed to
//rows, errROW := db.Query("SELECT user.id,user.name,stage.link,player.url,player.characterchance,player.chance FROM user,stage,player WHERE user.id = '203' AND '33' <= user.chance AND stage.user = user.id AND stage.domain = player.id AND player.chance > 0 ORDER BY player.id ASC")
if errROW != nil {
fmt.Println("errROW")
log.Println(errROW)
}
defer rows.Close()
if rows.Next() == false {
fmt.Println("no rows ")
}
for rows.Next() {
fmt.Println("where are the rows")
var id int
var name string
var link string
var url string
var characterchance int
var chance int
rows.Scan(&id, &name, &link, &url, &characterchance, &chance)
fmt.Println(id,name,link,url,characterchance,chance)
}
rows.Close()
}
}
This query can return multiple and single rows. I also tried retrieving the data via QueryRow as a single row which also did not return any result.
Any help would be much appreciated.
UPDATE:
I added
if rows.Next() == false
as an attempt to find the problem. Removing it yields the same result. Furthermore I do not get an error message from scan. The for rows.next() loop does not even get executed.
when you do:
if rows.Next() == false
you are scrolling to the first row
and
for rows.Next()
moves to the next row
basically, you are skipping the first row in your result set in the example code you provided.
also, you are ignoring the error in Scan.
This looks like it would print something if the query returns at least 2 rows (since first row is being skipped)
Ok I figured out what the problem was:
In my query I used: %d as a placeholder for my variable when I should have used $1,$2 etc. Using this the query returns results as expected.
It seems strange to me that this behaviour is allowed returns no error from go or sqlite and even works when you just printout the query and use it with sqlite3 manually. Coming from C and just starting out with go this can obviously be the cause for some headaches.
My question is similar to this one: link except that I don't want to serialize the QList. I want to store a QList as a double precision array in the DB table.
I am trying the following bindValue command for the variable val:
query.bindValue( QStrFromSrcEnc( id ), QVariant::fromValue( val ) );
where val is QList and id is ":value"
I am executing the following postgres query:
"INSERT INTO valtable( type_id, asset_id, value, tag )\n"
"VALUES ( :typeId, :assetId, :value, :tag )\n"
The value column of the table is of the type double precision[].
I get the following error, as you can see the 3rd field for value is blank which means val wasn't bound correctly.
ERROR: syntax error at or near ","
LINE 1: EXECUTE qpsqlpstmt_13e (60, 63, , '')
^
however, if val is simply a QVariant, then it works fine.
Ok, I did a workaround.
I convert the QList List to a QString in a postgres array format (e.g.'{1.32,4.43}').
QString valueStr = QStrFromSrcEnc("{");
for(int i=0; i<List.size(); ++i)
{
valueStr += QString::number( List[i] );
valueStr += QStrFromSrcEnc(",");
}
valueStr.chop(1);
valueStr += QStrFromSrcEnc("}");
then I bind the string value to the :val placeholder
Im writing SSAS MDX queries involving more than 2 axis' to retrieve a value. Using ADOMD.NET, I can get the returned cellset and determine the value by using
lblTotalGrossSales.Text = CellSet.Cells(0).Value
Is there a way I can get the CellSet's Cell(0) Value in my MDX query, instead of relying on the data returning to ADOMD.NET?
thanks!
Edit 1: - Based on Daryl's comment, here's some elaboration on what Im doing. My current query is using several axis', which is:
SELECT {[Term Date].[Date Calcs].[MTD]} ON 0,
{[Sale Date].[YQMD].[DAY].&[20121115]} ON 1,
{[Customer].[ID].[All].[A612Q4-35]} ON 2,
{[Measures].[Loss]} ON 3
FROM OUR_CUBE
If I run that query in Management Studio, I am told Results cannot be displayed for cellsets with more than two axes - which makes sense since.. you know.. there's more than 2 axes. However, if I use ADOMD.NET to run this query in-line, and read the returning value into an ADOMD.NET cellset, I can check the value at cell "0", giving me my value... which as I understand it (im a total noob at cubes) is the value sitting where all these values intersect.
So to answer your question Daryl, what I'd love to have is the ability to have the value here returned to me, not have to read in a cell set into the calling application. Why you may ask? Well.. ultimately I'd love to have one query that performs several multi-axis queries to return the values. Again.. Im VERY new to cubes and MDX, so it's possible Im going at this all wrong (Im a .NET developer by trade).
Simplify your query to return two axis;
SELECT {[Measures].[Loss]} ON 0, {[Term Date].[Date Calcs].[MTD] * [Sale Date].[YQMD].[DAY].&[20121115] * [Customer].[ID].[All].[A612Q4-35]} ON 1 FROM OUR_CUBE
and then try the following to access the cellset;
string connectionString = "Data Source=localhost;Catalog=AdventureWorksDW2012";
//Create a new string builder to store the results
System.Text.StringBuilder result = new System.Text.StringBuilder();
AdomdConnection conn = new AdomdConnection(connectionString);
//Connect to the local serverusing (AdomdConnection conn = new AdomdConnection("Data Source=localhost;"))
{
conn.Open();
//Create a command, using this connection
AdomdCommand cmd = conn.CreateCommand();
cmd.CommandText = #"SELECT { [Measures].[Unit Price] } ON COLUMNS , {[Product].[Color].[Color].MEMBERS-[Product].[Color].[]} * [Product].[Model Name].[Model Name]ON ROWS FROM [Adventure Works] ;";
//Execute the query, returning a cellset
CellSet cs = cmd.ExecuteCellSet();
//Output the column captions from the first axis//Note that this procedure assumes a single member exists per column.
result.Append("\t\t\t");
TupleCollection tuplesOnColumns = cs.Axes[0].Set.Tuples;
foreach (Microsoft.AnalysisServices.AdomdClient.Tuple column in tuplesOnColumns)
{
result.Append(column.Members[0].Caption + "\t");
}
result.AppendLine();
//Output the row captions from the second axis and cell data//Note that this procedure assumes a two-dimensional cellset
TupleCollection tuplesOnRows = cs.Axes[1].Set.Tuples;
for (int row = 0; row < tuplesOnRows.Count; row++)
{
for (int members = 0; members < tuplesOnRows[row].Members.Count; members++ )
{
result.Append(tuplesOnRows[row].Members[members].Caption + "\t");
}
for (int col = 0; col < tuplesOnColumns.Count; col++)
{
result.Append(cs.Cells[col, row].FormattedValue + "\t");
}
result.AppendLine();
}
conn.Close();
TextBox1.Text = result.ToString();
} // using connection
Source : Retrieving Data Using the CellSet
This is fine upto select on columns and on Rows. It will be helpful analyze how to traverse sub select queries from main query.
I decided to test sqlite db for my Qt application.
I have created the sqlite db file with the proper statements (create table etc. and Inserted some rows of data).
My problem is that when I execute a select statement I don't get any records.
This is the code I use:
qq.sprintf("SELECT * from descriptors WHERE descriptors.id=%d ",idx);
query.exec(qq);
if( query.isSelect() ){
while (query.next()){
int fff = query.value(0).toInt();
}}
The problem is that I never get inside the while loop. query.next() doesn't seem to work.
any hints?
thanks in advance,
Thodoris
p.s. I forgot to write my configuration so: Qt 4.7.3, windows 7, visual studio 2008
Other than the mistake hexa posted, query.isSelect() will always return true even if the query failed. You need to check the result of exec():
QSqlQuery query;
query.prepare( "SELECT * FROM descriptors WHERE id = ?" );
query.bindValue( 0, idx ); // assuming idx is an integer/long/QVariant value
if( !query.exec() )
{
// Error Handling, check query.lastError(), probably return
}
// Note: if you don't return in case of an error, put this into the else{} part
while( query.next() )
{
int fff = query.value( 0 ).toInt();
}
In my case, backward iteration over QSqlQueries worked. I think this could be a bug somewhere in the QSQLite Driver implementation.
QSqlQuery q = db.exec("SELECT * FROM Table");
if (q.last()) {
do {
// Do something with row...
} while (q.previous());
}