Detecting no results in adodb select query - sql

I'm using ADODB connection in C. The code works more or less fine but I'm getting errors when there is no result for my query and I try to read it. Relevant code:
__object *con, *rec;
con = __object_create("ADODB.Connection");
if(con!=NULL) con->Open("odbc name");
if (con == NULL || con->State==0)
{
return 0;
}
rec= __object_create("ADODB.RecordSet");
sprintf(query, "SELECT SUM(column) FROM table WHERE %s", constraint);
rec->CursorLocation=3;
rec->Open(query, con, 1, 3);
float result = rec->Fields(0); // <- Error here
rec->Close();
__object_delete(rec);
__object_delete(con);
I'm getting error code 80020005 (Type mismatch). The DB column is type float. When there are records that meet the constraint and I get a result everything works fine. But when it matches no records the DB server returns null and I get the error. Fortunately result is set to 0 which is reasonable but I would like to detect this better.
The standard ways (BOF/EOF, Fields->Count, == NULL, ...) all fail. Most code samples I can find are for VB and not C so they are not really helpful.

rec->Fields(0).Value returns a variant, before assigning to the float variable check if the variant represents a VT_NULL which indicates that the data returned is NULL.

Related

use associate array total value count Lua

i want to count the data type of each redis key, I write following code, but run error, how to fix it?
local detail = {}
detail.hash = 0
detail.set = 0
detail.string = 0
local match = redis.call('KEYS','*')
for i,v in ipairs(match) do
local val = redis.call('TYPE',v)
detail.val = detail.val + 1
end
return detail
(error) ERR Error running script (call to f_29ae9e57b4b82e2ae1d5020e418f04fcc98ebef4): #user_script:10: user_script:10: attempt to perform arithmetic on field 'val' (a nil value)
The error tells you that detail.val is nil. That means that there is no table value for key "val". Hence you are not allowed to do any arithmetic operations on it.
Problem a)
detail.val is syntactic sugar for detail["val"]. So if you expect val to be a string the correct way to use it as a table key is detail[val].
Possible problem b)
Doing a quick research I found that this redis call might return a table, not a string. So if detail[val] doesn't work check val's type.

How to get floating point results from an SQL query?

I have successfully connected to my database, but when I select 2 cells from my SQL db to set the value for both of my variables it does nothing. I have no problem inserting data into the database. I have tried different approaches to this with no success. Could it be that I am trying to use a string format for doubles??
double userHeight;
double userWeight;
QSqlQuery query;
QString retreiveUserHeight =
QString("SELECT Height, Weight FROM SQL1 WHERE Username='joejoe'");
query.prepare(retreiveUserHeight);
query.bindValue(0,"Height");
query.bindValue(1, "Weight");
query.exec();
userHeight = query.value(0).toInt();
userWeight = query.value(1).toInt();
I'm pretty certain there is a small error in syntax that is causing this mishap but I have been unable to find it. Thanks for your help.
qDebug() << "calculated" << 703*(userWeight/(userHeight*userHeight))
<< userWeight << userHeight ;
Heres the debug output:
calculated nan 0 0
// Obtain username from somewhere
QString username = "joejoe";
// Check whether DB is open
if( db->isOpen( ) )
{
QSqlQuery query;
double userHeight;
double userWeight;
// Prepare select statement
query.prepare ( "SELECT Height , Weight FROM SQL1 WHERE Username = :username" );
query.bindValue ( ":username" , username );
query.exec ( );
// Check if something went wrong when executing your query
if( query.lastError( ).text( ).trimmed( ) == "" )
{
// Loop through all results and handle them accordingly
while( query.next( ) )
{
userHeight = query.value( 0 ).toDouble( );
userWeight = query.value( 1 ).toDouble( );
qDebug( ) << "calculated" << 703 * ( userWeight / ( userHeight * userHeight ) ) << userWeight << userHeight;
qDebug( ) << "---------------------------------";
}
}
else
{
// Display the error that occured
QMessageBox::critical( this , tr( "SQL Error" ) , query.lastError( ).text( ) );
}
}
I assume this is what you wanted it to look like.
I've included some error checking and corrected your query to use .bindValue( ) correctly, since it's not meant for using for return values rather than for input as seen in the WHERE.
Since I don't know anything about your sql table I've included a loop to go through all results of your query. That can obviously be changed.
Apart from that if you're using doubles you should cast the result .toDouble( ) rather than .toInt( )
There are a number of serious problems with this code. Let's start with the concept of prepared SQL queries. Wikipedia lists two reasons for using prepared statements:
The overhead of compiling and optimizing the statement is incurred
only once, although the statement is executed multiple times. [...]
Prepared statements are resilient against SQL injection, because
parameter values, which are transmitted later using a different
protocol, need not be correctly escaped.
Neither of these reasons apply in your code; you're only executing the query once, and you're not splicing any inputs into the string. In fact, the only input in your query at all is the username, which is hard-coded to "joejoe":
"SELECT Height, Weight FROM SQL1 WHERE Username='joejoe'"
Since there are no variable inputs, using a prepared query doesn't make much sense. Neither do the following lines:
query.bindValue(0,"Height");
query.bindValue(1, "Weight");
Height and Weight are outputs from this query, not inputs. See the section in the Qt docs for QSqlQuery titled "Approaches to Binding Values" for an explanation of how this is intended to work. Qt's API for binding prepared SQL queries is fairly typical among database libraries, there's nothing earth shattering here.
Then we get to this:
userHeight = query.value(0).toInt();
userWeight = query.value(1).toInt();
Both the variables you're reading into here were declared as doubles, but you're calling toInt() on the returned QVariant rather than toDouble(). I don't know what (if any!) values are in your database, but it's possible they're getting rounded down to zero during the conversion from double to int if the values are between -1.0 and 1.0.
That said, you aren't doing any error checking whatsoever. The methods prepare() and exec() return bools that indicate whether they succeeded or failed. Likewise, both toInt() and toDouble() tell you whether they've succeeded or failed if you pass in a pointer to a bool. It's worth noting that both methods also return a zero value on failure.

Linq Query in VB

Good Day,
I am querying my database using Linq and I have run into a problem, the query searched a column for a search phrase and based on if the column has the phrase, it then returns the results, The query is below,
Dim pdb = New ProductDataContext()
Dim query =
From a In pdb.tblUSSeries
Join b In pdb.tblSizes_ On a.Series Equals b.Series
Where
a.Series.ToString().Equals(searchString) Or
b.Description.Contains(searchString) Or Not b.Description.Contains(Nothing)
Order By b.Series, b.OrderCode Ascending
Select New CustomSearch With
{
.Series = a.Series,
.SeriesDescription= a.Description,
.Coolant = a.Coolant,
.Material = a.Material,
.Standard = a.Standard,
.Surface = a.Surface,
.Type = a.Type,
.PointAngle = a.PointAngle,
.DiaRange = a.DiaRange,
.Shank = b.Shank,
.Flutes = b.Flutes,
.EDPNum = b.EDPNum,
.SizesDescription = b.Description,
.OrderCode = b.OrderCode
}
Return query
I think the problem is that, in the table certain rows are NULL, so when it is checking the column for the phrase and it encounters a row that is null it, breaks and returns this error,
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
I have ran this query against another column that has all the rows populated with data and it returns the results ok.
So my question is how can I write it in VB to query the db with the supplied searchstring and return the results, when some of the rows in the columns have null values.
Any help would be great.
The exception occurs when you make the projection (i.e. select new CustomSearch)
And yes your trying to assign Null to some int property
(Not sure which one of your properties that is)
one of 2 choices :
1) Use nullalbe types for your properties (or just that one property).
2) project with an inline If ( ?? in C#) , I don't know VB so don't catch me on the syntax.
Taking Series just as an example i don't know if it's an int or if that's the problematic property
Select New CustomSearch With
{
.Series = If(a.Series Is Nothing,0, CInt(a.Series))
}
In C#
Select new CustomSearch
{
Series = a.Series ?? 0;
}

Multiple parameter values

I have a problem with BIRT when I try to pass multiple values from report parameter.
I'm using BIRT 2.6.2 and eclipse.
I'm trying to put multiple values from cascading parameter group last parameter "JDSuser". The parameter is allowed to have multiple values and I'm using list box.
In order to be able to do that I'm writing my sql query with where-in statement where I replace text with javascript. Otherwise BIRT sql can't get multiple values from report parameter.
My sql query is
select jamacomment.createdDate, jamacomment.scopeId,
jamacomment.commentText, jamacomment.documentId,
jamacomment.highlightQuote, jamacomment.organizationId,
jamacomment.userId,
organization.id, organization.name,
userbase.id, userbase.firstName, userbase.lastName,
userbase.organization, userbase.userName,
document.id, document.name, document.description,
user_role.userId, user_role.roleId,
role.id, role.name
from jamacomment jamacomment left join
userbase on userbase.id=jamacomment.userId
left join organization on
organization.id=jamacomment.organizationId
left join document on
document.id=jamacomment.documentId
left join user_role on
user_role.userId=userbase.id
right join role on
role.id=user_role.roleId
where jamacomment.scopeId=11
and role.name in ( 'sample grupa' )
and userbase.userName in ( 'sample' )
and my javascript code for that dataset on beforeOpen state is:
if( params["JDSuser"].value[0] != "(All Users)" ){
this.queryText=this.queryText.replaceAll('sample grupa', params["JDSgroup"]);
var users = params["JDSuser"];
//var userquery = "'";
var userquery = userquery + users.join("', '");
//userquery = userquery + "'";
this.queryText=this.queryText.replaceAll('sample', userquery);
}
I tryed many different quote variations, with this one I get no error messages, but if I choose 1 value, I get no data from database, but if I choose at least 2 values, I get the last chosen value data.
If I uncomment one of those additional quote script lines, then I get syntax error like this:
The following items have errors:
Table (id = 597):
+ An exception occurred during processing. Please see the following message for details: Failed to prepare the query execution for the
data set: Organization Cannot get the result set metadata.
org.eclipse.birt.report.data.oda.jdbc.JDBCException: SQL statement does not return a ResultSet object. SQL error #1:You have an error in
your SQL syntax; check the manual that corresponds to your MySQL
server version for the right syntax to use near 'rudolfs.sviklis',
'sample' )' at line 25 ;
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near
'rudolfs.sviklis', 'sample' )' at line 25
Also, I should tell you that i'm doing this by looking from working example. Everything is the same, the previous code resulted to the same syntax error, I changed it to this script which does the same.
The example is available here:
http://developer.actuate.com/community/forum/index.php?/files/file/593-default-value-all-with-multi-select-parsmeter/
If someone could give me at least a clue to what I should do that would be great.
You should always use the value property of a parameter, i.e.:
var users = params["JDSuser"].value;
It is not necessary to surround "userquery" with quotes because these quotes are already put in the SQL query arround 'sample'. Furthermore there is a mistake because userquery is not yet defined at line:
var userquery = userquery + users.join("', '");
This might introduce a string such "null" in your query. Therefore remove all references to userquery variable, just use this expression at the end:
this.queryText=this.queryText.replaceAll('sample', users.join("','"));
Notice i removed the blank space in the join expression. Finally once it works finely, you probably need to make your report input more robust by testing if the value is null:
if( params["JDSuser"].value!=null && params["JDSuser"].value[0] != "(All Users)" ){
//Do stuff...
}

Using linQ to perform a simple select where

I am using VS2013 with SQL server 2012, VB.net. I am developing a web application.
Let me say before I ask the question that this will probably be extremely simple for this board but I have not been able to find this through googling.
I have an SQL table that holds some data, two columns (settingName (nvarchar) and settingValue (float)). I want to do the following but using LinQ.
SELECT Settingvalue
FROM Settings
WHERE settingName = 'Name1'
I have the following so far in VB.
Dim db As New GMConnectionDataContext
Dim result = From a In db.Settings
Where a.SettingName = "Name1"
Select a.SettingValue
txtEgdon.Text = result
This doesn't work as result is a double but if I add .tostring to result then the output in the text box is the full linq query not the result I am looing for.
I just need to understand this simple query so I can build on it but I just cant get it and any help offered would be great.
This is because your result is an IQueryable and not a single value(even if you expect it to be). This is also why ToString will get you the SQL that will be run against your DB.
You need to get either the First or if you are really sure this would be a single value get Single. The OrDefaults are used in the case that no value is returned so the result will be null.
A Few options:
// You expect 1 to many results and get the first
txtEgdon.Text = result.First().ToString()
// You expect 0 to many results and get the first or null in case of zero results
txtEgdon.Text = result.FirstOrDefault().ToString()
// You expect exactly 1 result and get it (you will get an exception if no results are returned)
txtEgdon.Text = result.Single().ToString()
// You expect exactly 0 or 1 results and get null or the result
txtEgdon.Text = result.SingleOrDefault().ToString()
I would prefer the FirstOrDefault()