Doctrine/Symfony "translates" empty string into a NULL - mysql

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.

Related

Trick to use variable in match against mysql

Please first read my question,and then you will find out it is not a duplicate of other question.
I'm using sphinx search for 98% of search,but need to use match against for just one query.
As we know from mysql documentation that AGAINST only takes string.The search string must be a literal string, not a variable or a column name.
But I have found this link http://bugs.mysql.com/bug.php?id=66573 ,which says it is possible.But I'm not sure how to use that in my case.
Here is my code
$sqli="SELECT busi_title,category FROM `user`.`user_det`";
$queryi=mysqli_query($connecti,$sqli);
if(mysqli_num_rows($queryi)>0){
while($rowi=mysqli_fetch_assoc($queryi)){
$busi_title=$rowi['busi_title'];
$category=$rowi['category'];
}
}else{
echo "OH NO";
}
$sqlj="SELECT * FROM `user`.`user_det` WHERE MATCH(student) AGAINST('$busi_title','$category')";
$queryj=mysqli_query($connecti,$sqlj);
if(mysqli_num_rows($queryj)>0){
..............................
..............................
}else{
foreach ( $res["matches"] as $doc => $docinfo ) {
................................
...............................
}
}
MATCH() AGAINST() is giving error,as it supposed to be.How to use that trick of that link in this case.I don't know the use of #word:= of that link.
Thanks in advance.
That link doesn't show a trick to get around a limitation of MySQL. It's a bug report demonstrating an incorrect statement in the MySQL documentation. The statement in the documentation has now been corrected.
The reason you're getting an error is because you're sending two parameters to AGAINST and it only accepts one. You can use a MySQL variable in AGAINST which is what the bug report is about, but this has nothing to do with the PHP variable that you're using.
EDIT
Upon reading your response, I rather suspect that you have your syntax backwards.
SELECT * FROM `user`.`user_dets` WHERE MATCH(busi_title, category) AGAINST('student')
But note this from the documentation:
The MATCH() column list must match exactly the column list in some FULLTEXT index definition for the table, unless this MATCH() is IN BOOLEAN MODE. Boolean-mode searches can be done on nonindexed columns, although they are likely to be slow.
If you don't have a Fulltext index, you'll actually want this:
SELECT * FROM `user`.`user_dets` WHERE `busi_title` LIKE '%student%' OR `category` LIKE '%student%'
When they say "The search string must be a literal string, not a variable or a column name" does not mean you cannot use variable to create your Query String.
So it is OK to make your query very simple.
Your WHERE could be this:
WHERE `student` = $busi_title OR `student` = $category

Same ID which occurs multiple times with SQL-IN Operator at rails

I use the following sql statement:
Keyword.where("id IN (#{params[:keyword_ids]})").order("find_in_set(id, '#{params[:keyword_ids]}')")
The Problem at this statement is that if "keyword id" hold the same id more than ones, the call returns it only ones.
But I need the same number(not fulfilled) as well as the same order(which is fulfilled with this statement) which occurs in the array, independent if the same id occurs more than ones.
How should I change that statement to fix.
Thanks, dot
Well, that's not a bug, it's a feature ;)
My first recommendation would be to sanitize your input. Passing params[:keyword_ids] directly to the database, despite the help that the Rails framework does, is prone to lead to some kind of vulnerability sooner or later.
Secondly, the easiest solution is probably to keep the query as is, convert the results to a map and map the input params to the result.
Sth like
keywords = Keyword.where('id IN (?)', checked_keyword_ids)
keyword_map = Hash[keywords.map { |kw| [kw.id, kw] }]
checked_keyword_ids.map { |id| keyword_map[id] }

DBIx::Class test agains mysql datetime function

I am using DBIx::Class and I would like to select rows based on what day of the year they were inserted on. Below is my query:
$rows = $c->model("DB::Test")->search(
{
"DAYOFYEAR(entry_time)"=>$day_of_year,
});
However this doesn't work because DBIx::Class treats DAYOFYEAR(entry_time) as a column. Is there anyway I could have it use that value litteraly? I know sometimes making it a scalar such as \'DAYOFYEAR(entry_time)' will work for some situations, but I've tried that and it doesn't work. Does anyone know of a way that I could do this? Thanks!
Using \ and 'DAYOFYEAR(entry_time)' is the right approach, and part of the FAQ.
[How do I] .. search with an SQL function on the left hand side?
To use an SQL function on the left hand side of a comparison you currently need to resort to literal SQL:
->search( \[ 'YEAR(date_of_birth) = ?', [ plain_value => 1979 ] ] );
Note: the plain_value string in the [ plain_value => 1979 ] part should be either the same as the name of the column (do this if the type of the return value of the function is the same as the type of the column) or in the case of a function it's currently treated as a dummy string (it is a good idea to use plain_value or something similar to convey intent). The value is currently only significant when handling special column types (BLOBs, arrays, etc.), but this may change in the future.

Is there a way to avoid wasNull() method?

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.

MS Access default value

I have a text column in one of my MS Access tables that is empty be default when a new record is inserted. The problem I have is that I can't seem to check whether this field is empty with EITHER equals Null or equals "" . For example, neither of these "reads" the field as being empty:
If [Field] = "" Or [Field] = Null Then
I've always used Access 2007 to develop this database, and I recently opened it with Access 2003, which is when I think this problem started. Could that be the cause? If so, would simply opening and saving it again with Access 2007 solve it?
When you compare against null, you need to use the IsNull function. With traditional ANSI SQL logic, Null <> Null, so you need a special function to test for null.
If [Field] = "" Or IsNull([Field])
First off, I would suggest that you do one of two things:
set your fields to disallow zero-length strings. That way you'd have to test only Is Null.
if you feel you must allow storage of ZLS, then set the default value to a ZLS. It's still possible for the field to end up Null, though, so this may or may not be helpful.
I don't see storage of ZLS's as having any utility whatsoever. It's almost always a shortcut to accomodate data being appended from sources that return ZLS's instead of Nulls for empty fields.
You should also read up on Nulls. Allen Browne has a number of pages that explain it all quite well:
Nulls: Do I need them?
Common Errors with Null
Aspects of working with Nulls in VBA code:
Nothing? Empty? Missing? Null?
The articles are Access-oriented, but could be valuable to those using any database, particularly relative novices because of the conversational style of the writing.
You should try:
If Nz([Field], "") = "" Then
Because:
If [Field] = ""
in:
If [Field] = "" Or IsNull([Field])
Would still throw a Null Error!