Is there a way to avoid wasNull() method? - mysql

I have a big ResultSet (getting from a JDBC query) of few thousand rows. Using each of these rows, I have to instantiate an Object, setting fields of it according to the fields of this result set. Now, as we all know, the getXXX() methods of this JDBC API return 0 if that particular column was null. So for each field of each row, I have to do a wasNull() before setting the value in my object, which looks pretty ugly and may be is not efficient as well. So, is there any other way by which I can avoid it?
Apart from JDBC, if there is some entirely different, standard, commonly used way, I am open to know about that as well.
Thanks!
EDIT 1
patientInput.setRaceCodeId(patients.getShort("race_code_id"));
if(patients.wasNull())
patientInput.setRaceCodeId(null);
patients is a ResultSet. patientInput is an object. This is the code which I am trying to avoid. I mean, everytime I do a getXXX(), and do a setXXX(), I have to check again that what I got from ResultSet was not null. If it was, then set that object field as null, as getXXX() returns 0 in that case.

Ok. I believe there are two possible approaches to 'tidying' up your code. However, this could come down to a difference of opinion as to what is tidy!
Solution 1 - replace getXXX() with getObject() which returns null e.g.
Short s = (Short)patients.getObject("race_code_id");
patientInput.setRaceCodeId(s);
Solution 2 - write a generic wrapper method that retrieves nullable values
protected final <T> T getNullableValue(T returnType, String colName, ResultSet rs) throws SQLException {
Object colValue = rs.getObject(colName);
return (T) colValue;
}
final static Integer INT = 0;
final static Short SHORT = 0;
.
.
.
patientInput.setRaceCodeId(getNullableValue(SHORT,"race_code_id",patients));

You don't have to do it to each field, only to fields that are numeric and, possibly, boolean, and are declared as nullable in your database. It happens not as frequently as you fear.
If you absolutely hate writing such code, you can try switching to an ORM library, for example, Hibernate.

Related

Doctrine/Symfony "translates" empty string into a NULL

So there is a form, and non-required fields, like say "first_name". When I leave this field empty, I got an error that "Column 'first_name' cannot be null", because indeed it can't. But why does Doctrine converts empty string to NULL?
But I have to questions regarding this:
Is this possible to disable it?
What's your opinion about it? Until now I was used to the fact that when a form field was empty, I simply inserted an empty string. Not NULL o_O But... somebody told me this is a principle we should follow. For me however, NULL means "there is no value", and '' (empty string) means something different - "there IS a value, but it's empty". What do you think?
p.s. I use MySql if it matters.
edit:
there is a similar question:
Symfony2 forms interpret blank strings as nulls but maybe there is a new solution as of 2016?
The only solution which work is the one from the accepted answer:
Or otherway when you have the function setRecap you can check if empty
or not set and set the value you expect.
public function setRecap($recap) {
if(!isset($recap)) {
$this->recap = ''
} else {
$this->recap = $recap;
}
}
But I have a lot of such fields, and this seems overkill to me, there must a simpler solution.
p.s. I did not try Thomas Decaux' answer below the accepted answer, because it seems hacky to me.
Well, as somebody suggested me, it's as simple as:
public function setUserName($userName) {
$this->userName = (string)$userName;
return $this;
}
In an entity.
Edit: plus, we need to give a default value for the variable, like:
$userName = '';
Frankly it would be best to allow NULL values for your first names in your DB. Doing what you did just make things more complicated.
Symfony is developped by professionals and to me that conversion seems reasonable, because an empty string isn't more interesting than NULL.
What you said above, that NULL and an empty strings are two different things, is true in a sense, but what does that mean to have an empty name (i.e. empty string)? Isn't it better to say that this guy has no known first name (i.e. NULL)?
EDIT:
In response to your first comment:
Well in that case, typecasting to string is the right approach.

Why does MySQL permit non-exact matches in SELECT queries?

Here's the story. I'm testing doing some security testing (using zaproxy) of a Laravel (PHP framework) application running with a MySQL database as the primary store for data.
Zaproxy is reporting a possible SQL injection for a POST request URL with the following payload:
id[]=3-2&enabled[]=on
Basically, it's an AJAX request to turn on/turn off a particular feature in a list. Zaproxy is fuzzing the request: where the id value is 3-2, there should be an integer - the id of the item to update.
The problem is that this request is working. It should fail, but the code is actually updating the item where id = 3.
I'm doing things the way I'm supposed to: the model is retrieved using Eloquent's Model::find($id) method, passing in the id value from the request (which, after a bit of investigation, was determined to be the string "3-2"). AFAIK, the Eloquent library should be executing the query by binding the ID value to a parameter.
I tried executing the query using Laravel's DB class with the following code:
$result = DB::select("SELECT * FROM table WHERE id=?;", array("3-2"));
and got the row for id = 3.
Then I tried executing the following query against my MySQL database:
SELECT * FROM table WHERE id='3-2';
and it did retrieve the row where id = 3. I also tried it with another value: "3abc". It looks like any value prefixed with a number will retrieve a row.
So ultimately, this appears to be a problem with MySQL. As far as I'm concerned, if I ask for a row where id = '3-2' and there is no row with that exact ID value, then I want it to return an empty set of results.
I have two questions:
Is there a way to change this behaviour? It appears to be at the level of the database server, so is there anything in the database server configuration to prevent this kind of thing?
This looks like a serious security issue to me. Zaproxy is able to inject some arbitrary value and make changes to my database. Admittedly, this is a fairly minor issue for my application, and the (probably) only values that would work will be values prefixed with a number, but still...
SELECT * FROM table WHERE id= ? AND ? REGEXP "^[0-9]$";
This will be faster than what I suggested in the comments above.
Edit: Ah, I see you can't change the query. Then it is confirmed, you must sanitize the inputs in code. Another very poor and dirty option, if you are in an odd situation where you can't change query but can change database, is to change the id field to [VAR]CHAR.
I believe this is due to MySQL automatically converting your strings into numbers when comparing against a numeric data type.
https://dev.mysql.com/doc/refman/5.1/en/type-conversion.html
mysql> SELECT 1 > '6x';
-> 0
mysql> SELECT 7 > '6x';
-> 1
mysql> SELECT 0 > 'x6';
-> 0
mysql> SELECT 0 = 'x6';
-> 1
You want to really just put armor around MySQL to prevent such a string from being compared. Maybe switch to a different SQL server.
Without re-writing a bunch of code then in all honesty the correct answer is
This is a non-issue
Zaproxy even states that it's possibly a SQL injection attack, meaning that it does not know! It never said "umm yeah we deleted tables by passing x-y-and-z to your query"
// if this is legal and returns results
$result = DB::select("SELECT * FROM table WHERE id=?;", array("3"));
// then why is it an issue for this
$result = DB::select("SELECT * FROM table WHERE id=?;", array("3-2"));
// to be interpreted as
$result = DB::select("SELECT * FROM table WHERE id=?;", array("3"));
You are parameterizing your queries so Zaproxy is off it's rocker.
Here's what I wound up doing:
First, I suspect that my expectations were a little unreasonable. I was expecting that if I used parameterized queries, I wouldn't need to sanitize my inputs. This is clearly not the case. While parameterized queries eliminate some of the most pernicious SQL injection attacks, this example shows that there is still a need to examine your inputs and make sure you're getting the right stuff from the user.
So, with that said... I decided to write some code to make checking ID values easier. I added the following trait to my application:
trait IDValidationTrait
{
/**
* Check the ID value to see if it's valid
*
* This is an abstract function because it will be defined differently
* for different models. Some models have IDs which are strings,
* others have integer IDs
*/
abstract public static function isValidID($id);
/**
* Check the ID value & fail (throw an exception) if it is not valid
*/
public static function validIDOrFail($id)
{
...
}
/**
* Find a model only if the ID matches EXACTLY
*/
public static function findExactID($id)
{
...
}
/**
* Find a model only if the ID matches EXACTLY or throw an exception
*/
public static function findExactIDOrFail($id)
{
...
}
}
Thus, whenever I would normally use the find() method on my model class to retrieve a model, instead I use either findExactID() or findExactIDOrFail(), depending on how I want to handle the error.
Thank you to everyone who commented - you helped me to focus my thinking and to understand better what was going on.

Dynamic Linq failing when using Contains against Int Field

I'm using Entity Frameworks 4.1.0.0 and MySQL.Data.Entity 6.5.4.0 and when I try and generate a dynamic query for a range of integers, I get an error of:
No applicable method 'Contains' exists in type 'Int32'
This seems to work fine when using a similar structure to check against Strings..but I want to expand this to support the other db fields I have in my data.
Code Example:
int[] ids = new int[] { 1, 3, 4 };
IQueryable<entityname> list = db.tablename.Where("Id.Contains(#0)", ids);
I have added in the Dynamic.cs to my project and followed along with
http://blog.walteralmeida.com/2010/05/advanced-linq-dynamic-linq-library-add-support-for-contains-extension-.html
but there has been no difference then using the Dynamic I loaded via Nuget.
Thank you in advance.
The syntax is slightly different:
IQueryable<entityname> list = db.tablename.Where("#0.Contains(outerIt.Id)", ids);
following the link you refer to.
If you need to check if a given (variable) int value is contained within a entity column, you can do the following using Dynamic Linq:
return query.Where(String.Format("{0}.ToString().Contains(#0)", field), value);
Check out this answer for an extension method that can perform such task with strings, integers and booleans column types in a rather seamless way.

Can LINQToSQL be used with sproc that uses sp_executeSQL? If not, how do you handle?

LINQToSQL doesn't like my sproc. It says that the sproc has return type "none", which is probably, because I am using an sp_ExecuteSQL statement to produce the results.
The SQL Server Sproc Code
I have a stored procedure similar to the following
CREATE PROCEDURE Foo
#BarName varchar(50)
AS
BEGIN
DECLARE #SQL NVARCHAR(1024)
SET #SQL = 'SELECT tbFoo.FooID, tbFoo.Name FROM tbFOO ';
IF #BarName IS NOT NULL
BEGIN;
SET #SQL = #SQL
+ ' JOIN tbBar '
+ ' ON tbFoo.FooID = tbBar.FooID '
+ ' AND tbBar.BarName = ''' + #BarName + ''''
END;
EXEC sp_executeSQL #SQL
END
Returns
This sproc returns a set of FooID | FooName tuples.
12345 | Tango
98765 | Cash
Goal
This stored procedure is going to be used to return search results on a search page. This is a fairly common search pattern. I want to find Foos that meet a condition, however the condition is being applied to a separate table. I could have chosen to write this query directly without using sp_executeSQL, however what this approach does is to create SQL that will only include the tables actually being queried. In a real world scenario, I could have 12 joins, instead of 1 and this methodology allows me to only string together joins that will actually be used as criteria.
The problem
LINQ to SQL doesn't like it. It says that this query returns type "none" and doesn't allow me to specify a return type. I'm not sure if other ORMs, such as NHibernate, Entity Framework or LLBLGen would be able to handle this or not. LINQToSQL has worked fine thus far on the project and I'm 95% finished with the project and don't want to use a different ORM for a single method. It might be something to refactor if I make further changes, but for now, I'm not ready to do a switch to a different ORM just for this.
I really want to find a way to make this work in LinqToSql! I'm not sure if it can or not. I haven't found any official documentation on this apparent limitation.
Alternatives that I'm considering so far
I've come up with a few alternatives so far. I don't like any of them so I really hope that someone has a good "hack" to solve this problem. These are what I've got thus far:
Re-write the sproc. Get rid of sp_executeSQL. Do LEFT JOINs on all the tables.
Use ADO.Net and hand roll the method.
Don't use a sproc, but instead try to do all the filtering in LINQ.
You can use Linq2SQL to call your sproc, but the Entity modeler probably can't generate the call wrapper for you because it can't figure out what the sproc is returning, so you'll have to create the call wrapper yourself.
To do this create an Entity Model "non-designer" module with a partial class definition matching your Entity Model data Context (and Entities if necessary) and define the call wrapper like this.
namespace bar.Context
{
public partial class EntityModelDataContext
{
/// <summary>
/// LINQ to SQL class mapper for Foo StoredProcedure
/// </summary>
/// <remarks>
/// This one is too tough for the LINQ to SQL modeler tool to auto-generate
/// </remarks>
/// <returns></returns>
[Function(Name = "dbo.Foo")]
[ResultType(typeof(bar.Entity.tbFoo))]
public ISingleresult<bar.Entity.tbFoo> Foo([Parameter(Name = "BarName", DbType = "varchar")] string barname)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), barname);
return ((ISingleResult<bar.Entity.tbFoo>)(result.ReturnValue));
}
}
}
namespace bar.Entity
{
/// <summary>
/// Data Modeler couldn't figure out how to generate this from the sproc
/// hopefully your entity model generated this and you don't need to replicate it
/// </summary>
[Table(Name = "dbo.tbFoo")]
public partial class tbFoo {
....
}
}
Is there some reason you can't handle the query using the object properties in Linq?
I'd need to see the table schema, including the foreign key linkage, in order to give a good example, but it'd be something like:
dbContextObject.Foos.Where(foo=> foo.Bars.Where(bar=> bar.BarName == searchString))
You'd then have an IEnumerable of Foos matching the condition and you could do whatever you wanted with.
If searchString is null, then you'd just use dbContextObject.Foos.All()

LINQ to SQL, how to write a method which checks if a row exists when we have multiple tables

I'm trying to write a method in C# which can take as parameter a tabletype, column and a columnvalue and check if the got a row with a with value
the method looks like:
public object GetRecordFromDatabase(Type tabletype, string columnname, string columnvalue)
I'm using LINQ to SQL and need to to this in a generic way so I don't need to write each table I got in the DB.
I have been doing this so far for each table, but with more than 70 of these it becomes cumbersome and boring to do.
Is there a way to generate the following code dynamically, And swap out the hardcoded tablenames with the values from the parameterlist? In this example I have a table in the DB named tbl_nation, which the DataContext pluralizes to tbl_nations, and I'm checking the column for the value
if (DB.tbl_nations.Count(c => c.code.Equals(columnvalue)) == 1)
{
return DB.tbl_nations.Single(c => c.code.Equals(columnvalue));
}
Take a look at System.Linq.Dynamic:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx