How to mix raw SQL and non-raw with Laravel's fluent query builder - fluent

I'm sure it's very simple but I couldn't find any examples.
I am using fluent in my Laravel application to log my users' logins and so I have created my own auth driver, however I am having a problem with a fluent query that mixes raw data and none raw, look at the following:
DB::table('logins')->insert(array(
'login_email' => $arguments['email'],
'login_date' => DB::raw('UNIX_TIMESTAMP(NOW())'),
'login_ip'=> DB::raw('INET_ATON('.$_SERVER['REMOTE_ADDR'].')'),
'login_result' => (bool)$success
));
which causes:
SQLSTATE[42000]: Syntax error or access violation: 1064 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 '#gmail.com, UNIX_TIMESTAMP(NOW()), INET_ATON(127.0.0.1), ?)' at line 1
SQL: INSERT INTO `cs_logins` (`login_email`, `login_date`, `login_ip`, `login_result`) VALUES (?, UNIX_TIMESTAMP(NOW()), INET_ATON(127.0.0.1), ?)
Bindings: array (
0 => false,
)
so I did the following:
DB::table('logins')->insert(array(
'login_email' => DB::raw("'".$arguments['email']."'"),
'login_date' => DB::raw('UNIX_TIMESTAMP(NOW())'),
'login_ip'=> DB::raw('INET_ATON('.$_SERVER['REMOTE_ADDR'].')'),
'login_result' => DB::raw((bool)$success)
));
But as Dayle Rees says, if it looks ugly it's not in the framework... so I want to know what I am missing here.

Use eloquent
First of all, if not already done, create a model for Login, so you can use laravel's own ORM eloquent. Eloquent allows you to write simple and yet powerful queries in a very expressive way.
Now you can do one of these two options:
$logins = Login::create(array('email' => 'example#gmail.com'));
or, maybe more elegant in your case:
$login = new Login;
$login->email = 'example#gmail.com';
$login->login_date = DB::raw('UNIX_TIMESTAMP(NOW())');
$login->save();
See the eloquent docs for more information.

OK, never mind it seems like the "?" question mark just meant that fluent had not got to that part of creating the prepared statement. I am new to Laravel and Fluent and I thought the question mark meant the error was in that part of the query.

Related

How to query array column from mysql in Rails 5.2?

I am using gem rails~> 5.2 and gem mysql2 >= 0.3.13, < 0.5.
I have a model Lawer, which has an array column lawer_filed [sic].
# Model lawer.rb
serialize :lawer_field, Array
Then I created a Lawer, and I can get the lawer_field value as follows:
=> Lawer.first.lawer_field
=> ["2", "3", "5"]
Now, I want to find one Lawer with a query using lawer_field. I tried:
#lawer = Lawer.where("lawer_field && ARRAY[?]", "2")
which raised an error like this:
ActiveRecord::StatementInvalid (Mysql2::Error: 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 '['2']) LIMIT 11' at line 1: SELECT `lawers`.* FROM `lawers` WHERE (lawer_field && ARRAY['2']) LIMIT 11)
There is a mistake in my SQL syntax, but I don't how to fix it. Can anyone help?
MySQL, unlike PostgreSQL, does not support arrays in database. Therefore you needed to add this line:
serialize :lawer_field, Array
This means that you have a string field in your database, but whenever ActiveRecord is unpacking results returned by the database, it maps them directly to an instance of Ruby Array. What this means is that your only option to filter the results in the database is with any MySQL string comparison functions, LIKE, etc.
Your options are to either use LIKE or perform some other String functions (which will not perform well as you will be unable to use indices) or build another table, add a has_many association to it and use MySQL the way it was supposed to be used. You could also, of course, migrate to PostgreSQL, but that seems to be the most extreme option.
EDIT: you could also consider using MySQL`s JSON, which has been added recently. That depends on your version of MySQL though.
I didn't try this answer because I don't have any Rails project ready for testing, but I think the problem is in the syntax.
I think it should be something like this:
Lawer.where("lawer_field IN (?)", "2")

CakePHP 3.0: Mysql Syntax Error caused by a class named Group

I just created a table called group and generated the skeleton files referenced to this table.
I realized that this name enter in conflict with MySQL Reserved Words, because cakephp3.0 generates queries like that:
SELECT
Group.group_id AS `Group__group_id`,
Group.name AS `Group__name`,
Group.created_at AS `Group__created_at`
FROM
group Group
LIMIT
20 OFFSET 0
That throws this error:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'group Group
LIMIT 20 OFFSET 0' at line 1
Is there a way to avoid this kind of error?
Indeed you can enable the quoteItendifiers but that comes with a performance hit as it says in the comment above it.
I use a different solution to this issue, by customizing the Table class for the problematic db_table like so:
Note the table alias being renamed and also the table name I have escaped manually
class GroupTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config); // TODO: Change the autogenerated stub
$this->setAlias('MyGroup');
$this->setTable("`group`");
}
}
This will generate a query looking like this:
SELECT
MyGroup.id AS `MyGroup__id`,
MyGroup.filed1 AS `MyGroup__filed1`
FROM
`group` MyGroup
With CakePHP 3.6 $Group->find()->all() runs successfully.
I'm using CakePHP 4, and to solve this problem, I just added quoteIdentifiers => true, inside config -> app_local -> datasources
Datasources' => [
'default' => [
'quoteIdentifiers' => true,
'host' => '127.0.0.1',
quoteIdentifiers
Set to true if you are using reserved words or special characters in your table or column names. Enabling this setting will result in queries built using the Query Builder having identifiers quoted when creating SQL. It should be noted that this decreases performance because each query needs to be traversed and manipulated before being executed.
See more in: https://book.cakephp.org/4/en/orm/database-basics.html
I just found the solution. The solution is to change the value of 'quoteIdentifiers' to true in your Datasource configuration. May you need to clear the cache.
Source: https://book.cakephp.org/3.0/en/orm/database-basics.html#configuration

Rails: MySQL2 Error when hitting the finder of a model

with Rails I hit this:
User.find(:all, :conditions => ["character = ?", character])
character is a Fixnum, as you can see by the way it is translated for the sql. A Fixnum is expected.
Then I get this error:
Mysql2::Error: 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 '= 5)'
at line 1: SELECT `users`.* FROM `users` WHERE (character = 5)
I'm somewhat confused and absolutely do not get what might be wrong with this line of sql.
Please help.
Yours
Joern
The problem is that character is a keyword in mysql. If you escape it in backticks it should work, eg
User.find(:all, :conditions => ["`character` = ?", character])
When you do a rails find like
User.where(:character => character)
as Rich Peck suggests, then rails automatically escapes the names of all fields to prevent this problem: you can see it do this in your log.
EDIT: you might find it less hassle in the long run to change the name of your column.
ActiveRecord
If using Rails 4, you should use this to look up multiple records:
User.where character: character
If you want to load a specific record, you can just use .find like this:
User.find_by character: character
--
Specific
I think your error is more an ActiveRecord issue than a Fixnum one - the fact you're using that data to look up the records shouldn't have any bearing.
I could be wrong, but I think the bottom line is your use of the ActiveRecord methods you've defined.

CakePHP 1.3 - Using RLIKE in model query

I have the following conditions for a model that finds a list of subjects:
$subjects = $this->PtlSubject->find('all', array(
'conditions' => array('PtlSubject.title RLIKE' => '[[:<:]]'.$value),
'limit' => 6
));
When running the query I get a mysql error:
1064: 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 '= '[[:<:]]mat' LIMIT 6' at line 1
Is there another way you can use REGEX word boundaries for mysql queries in CakePHP?
Thanks in advance for any help, much appreciated :)
I'm not sure if Cake knows how to deal with RLIKE. You can always pass the whole condition directly, like this:
'conditions' => "PtlSubject.title RLIKE '[[:<:]]$value'"
Just make sure $value is properly escaped, to avoid injection.

Linq to SQL and SQL Server Compact Error: "There was an error parsing the query."

I created a SQL server compact database (MyDatabase.sdf), and populated it with some data. I then ran SQLMetal.exe and generated a linq to sql class (MyDatabase.mdf)
Now I'm trying to select all records from a table with a relatively straightforward select, and I get the error:
"There was an error parsing the query. [ Token line number = 3,Token line offset = 67,Token in error = MAX]"
Here is my select code:
public IEnumerable<Item> ListItems()
{
MyDatabase db_m = new MyDatabase("c:\mydatabase.sdf");
return this.db_m.TestTable.Select(test => new Item()
{
ID = test.ID,
Name = test.Name,
RequestData = test.RequestData != null ? test.RequestData.ToString() : null,
Url = new System.Uri(test.Uri)
}.AsEnumerable();
}
I've read that Linq to SQL works with Sql Compact, is there some other configuration I need to do?
Could it be an errant NVARCHAR(MAX)? I think I've seen an error like this before with sql compact edition, and as I recall it had to do with the fact that sql compact edition doesn't support the NVARCHAR(MAX) datatype. This is also maybe why you see the "token in error = MAX" message in the exception?
Why do you need to do the conversion on RequestData? What does your class look like? Can you just set it like this?
RequestData = test.RequestData
I also tried the approach of using a SQLMetal for a SQL Server compact edition in a Winforms app for Linq-to-sql
.
After some problems i skipped the Linq-to-SQL Approach and went for the Linq-To-Entities approach. The syntax is like 99% the same for the query's i'm doing so ;-)
Also, when using the edmx designer, it's possible to easy update , delete and add tables.(with drag drop or Right-Click equivalent in the designer.)