How to execute a MySQL function in a Knex query? - mysql

I have a BINARY field in my table which I usually grab like this:
SELECT HEX(users.id) AS id FROM users WHERE username = ?
I recently started using Knex because I need to be able to dynamically generate WHERE clauses from objects. Here's what I tried:
knex('users').select('HEX(users.id) AS id)').where(filter);
Here's the query it generates:
select `HEX(users`.`id)` as `id` ....
And then I tried this:
knex('users').select('HEX(`users`.`id`) AS id').where(filter);
And it comes up with this:
select `HEX(``users```.```id``)` as `id` ....
How do I execute HEX() without it being mistaken for a column name?

With knex letting to do quoting of identifiers it would look like this:
knex('users').select(knex.raw('HEX(??) AS id', ['users.id'])).where(filter);

I've found a solution. I have to use raw() function. So my query builder will look like this:
knex('users').select(knex.raw('HEX(`users`.`id`) AS id')).where(filter);

Related

SQL get value from key in dictionary

I have a column in my database which is called user_log. It basically logs everything a user does on the page. I use MySQL.
It looks like that:
user_id
user_log
1028
{ "last_login":"2022-04-08 12:03:05", "blog_entry_at":"2022-04-08 12:43:12" }
Now, I want to extract all "last_login" and get the value of it.
It is a text field, but not a dict or something else
You can use json_extract in MySQL.
SELECT user_id, json_extract(user_log, '$.last_login') as last_login FROM users;
Sample query: https://onecompiler.com/mysql/3y8a3brhr
More on json_extract here in the mariadb docs: https://mariadb.com/kb/en/json_extract/
You can simply use JSON_VALUE() function provided that the DB is of version 8.0.21+ such as
SELECT JSON_VALUE(user_log, '$.last_login') AS extracted_value
FROM t

Select NULL as column using JOOQ

I'm trying to select NULL as a column in my query using JOOQ, so basically something like this:
SELECT name, NULL as 'someColumn' FROM someTable;
I need to do this, because the result needs to include someColumn (as part of a data standard), but we do not have this information in our database. This works fine in plain SQL, but I'm struggling to reproduce this using JOOQ.
Does anyone know how to do this in a query of this form?
context.select(
SOMETABLE.NAME,
... // Other columns here
DSL.NULL.as("someColumn") // <-- This doesn't exist
)
You can use an inline value
DSL.inline(null)
Depending on your database dialect or query usage, you may need to add a data type to that value, e.g.
DSL.inline(null, SQLDataType.VARCHAR)

MySql explode/in_array functionalilty

In my table I have a field with data such as 1,61,34, and I need to see if a variable is in that.
So far I have this
SELECT id, name FROM siv_forms WHERE LOCATE(TheVariable, siteIds) > 0
Which works, with the exception that if the siteIds were 2,61,53, and TheVariable was 1, it would return the row as there is a 1 in 61. Is there anyway around this using native MySql, or would I need to just loop the results in PHP and filter the siteIds that way?
I've looked through the list of string functions in MySql and can't see anything that would do what I'm after.
Try with find_in_set function.
SELECT id, name FROM siv_forms WHERE find_in_set(TheVariable, siteIds);
Check Manual for find_in_set function.

Rails 3 connection.execute IN statement parameters array syntax

I have a syntax question regarding the Rails 3 ActiveRecord::Base.connection.execute method and parameter that i want to use with it. I have been fighting with this for some hours now and just do not seem to find any answers to this specific question on the internet.
The database is MySQL.
I need to create a temporary table through SELECT with IN condition statement, where the list of values against which IN should check, is a parameter - rails Array. The code looks like so:
arr = [1,2,3]
ActiveRecord::Base.connection.execute("CREATE TEMPORARY TABLE things SELECT * FROM objects WHERE objects.id IN #{arr}")
I get a MySQL syntax error!
ActiveRecord::Base.connection.execute("CREATE TEMPORARY TABLE things SELECT * FROM objects WHERE objects.id IN #{(arr)}")
Again MySQL syntax error!
ActiveRecord::Base.connection.execute("CREATE TEMPORARY TABLE things SELECT * FROM objects WHERE objects.id IN (#{arr})")
MySQL syntax error
The above attempts correspond to this question-answer:
How to execute arbitrary parameterized SQL in rails
I even tried to use in the manner like with find_by_sql, but still get an error:
ActiveRecord::Base.connection.execute(["CREATE TEMPORARY TABLE things SELECT * FROM objects WHERE objects.id IN (:ids)",{:ids => arr }]) - obviously, I get an MySQL error.
Am I missing something obvious? Please help! I need this exactly in this way (e.g. create temporary table with exactly such conditions), otherwise a more complicated query based on this one will not work. Thanks!
Here's another option that uses Rails' query sanitization
arr = [1,2,3]
query = "SELECT * FROM objects where id IN (?)"
query = ActiveRecord::Base.send :sanitize_sql_array, [query, arr]
ActiveRecord::Base.connection.execute(query)
If you convert arr.to_s you get "[1, 2, 3]".
I think arr.join(', ') should work.
ActiveRecord::Base.connection.execute("CREATE TEMPORARY TABLE things SELECT * FROM objects WHERE objects.id IN (#{arr.join(', ')})")

What is the "Rails Way" of doing a query with an OR clause using ActiveRecord?

I'm using Rails 3 with a MySQL database, and I need to programmatically create a query like this:
select * from table where category_name like '%category_name_1%'
OR category_name like '%category_name_2%'
(...snip...)
OR category_name like '%category_name_n%'
Given the table size and the project scope (500 rows at most, I think), I feel that using something like thinking sphinx would be overkill.
I know I could simply do this by writing the query string directly, but wanted to know if there's an ActiveRecord way to do this. There's no mention of this on the official guide, and I've been googling for a long while now, just to end empty-handed :(
Also, is there a reason (maybe a Rails reason?) to not to include the OR clause?
Thanks!
Assuming you have an array names with category names:
Model.where( names.map{"category_name LIKE ?"}.join(" OR "),
*names.map{|n| "%#{n}%" } )
you should google first, there is already an answer.
Look here and then here
and you'll get something like this:
accounts = Account.arel_table
Account.where(accounts[:name].matches("%#{user_name}%").or(accounts[:name].matches("%#{user_name2}%")))
If you look at the guide, they have examples that can easily be modified to this:
Client.where("orders_count = ? OR locked = ?", params[:orders], false)
Mysql has a regexp function now that can clean things up a bit, assuming there's no regex metachars in your category names:
Table.where "category_name regexp '#{names.join('|')}'"