Dynamyc queries in knex - mysql

I am trying to implement unions that can dynamically take query strings or builder as parameters. See the code below:
function dynamicUnion(queryString||builder){
baseQuery.union(function () {
//I want to use query string or querybuilder here instead.
this.select('*').from('users').whereNull('first_name');
})
}
In the place of the line: this.select('*').from('users').whereNull('first_name'), I would like to implement something like: this.raw(queryString||builder) or any working alternative though I've not come across .raw() method when working with this keyword in that block.
I am implementing it this way since the select queries that are to be used in the union will will vary and it's efficient if passed dynamically.

Sounds like a bug in knex that this.raw is not working in this case. Here is one way to pass raw query to union:
const Knex = require('knex');
const knex = Knex({
client: 'mysql',
});
knex('foo').union(knex.raw('foo bar')).toSQL();
// outputs "select * from `foo` union foo bar"
https://runkit.com/embed/10boda0lt1it

Related

How to use MySQL's LIKE in Prisma ORM on non string fields?

Having some experience in writing raw SQL queries for some time, I want to use Prisma in Node.js to ask MySQL for something like that:
SELECT ..... WHERE dateField LIKE '2020-05%'
or
SELECT ..... WHERE numberField LIKE '%99'
I know, that the database will return what I want.
I just can't make Prisma to do that. Is it possible?
For string/varchar fields i use contains keyword in where object and it works fine.
const orders = await prisma.order.findMany({
where: {
textField: {
contains: 'test'
}
}
});
Is there any workaround to get such functionality for date/number type fields?
I managed to run raw SQL in Prisma as a workaround:
const orders = await prisma.$queryRaw`SELECT * FROM Order WHERE dataField LIKE '%-05-%'`;
It can even be type casted:
import { Order } from '#prisma/client'
const orders = await prisma.$queryRaw<Order[]>`SELECT * FROM Order WHERE dataField LIKE '%-05-%'`;
Not pretty, but works as intended.

How to work with data returned by mysql select query in nodejs

I am working on a discord bot written in nodejs, the bot utilises a mysql database server to store information. The problem I have run into is that I cannot seem to retrieve the data from the database in a neat way, every single thing I try seems to run into some issue or another.
The select query returns an object called RowDataPacket. When googling every single result will reference this solution: Object.values(JSON.parse(JSON.stringify(rows)))
It postulates that I should get the values back, but I dont I get an array back that is as hard to work with as the rowdatapacket object.
This is a snippet of my code:
const kenneledMemberRolesTableName = 'kenneled_member_roles'
const kenneledMemberKey = 'kenneled_member'
const kenneledMemberRoleKey = 'kenneled_member_role_id'
const kenneledStaffMemberKey = 'kenneled_staff_member'
const kenneledDateKey = 'kenneled_date'
const kenneledReturnableRoleKey = 'kenneled_role_can_be_returned'
async function findKenneledMemberRoles(kenneledMemberId) {
let sql = `SELECT CAST(${kenneledMemberRoleKey} AS Char) FROM ${kenneledMemberRolesTableName} WHERE ${kenneledMemberKey} = ${kenneledMemberId}`
let rows = await databaseAccessor.runQuery(sql)
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row.kenneled_member_role_id
})
return result
}
This seemed to work, until I had to do a type conversion on the value, now the dot notations requires me to reference row.CAST(kenneled_member_role_id AS Char), this cannot work, and I have found no other way to retrieve the data than through dot notation. I swear there must be a better way to work with mysql rowdatapackets but the solution eludes me
I figured out something that works, however I still feel like this is an inelegant solution, I would love to hear from others if I am misunderstanding how to work with mysql code in nodejs, or if this is just a consequence of the library:
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row[`CAST(${kenneledMemberRoleKey} AS CHAR)`];
})
So what I did is I access the value through brackets instead of dot notation, this seems to work, and at least makes me able to store part of or the whole expression in a constant variable, hiding the ugliness.

Escaping knex mysql query statements

I'm fairly new to knex and databases in general, so this is a beginner question.
I found no clear mention in the knex docs about this.
Are non-raw knex queries automatically "safe"?
Secondly, for raw queries, I have several raw statements similar to this:
var condition = _.map(ids, function(id) {
return '`id`=' + id;
}).join(' OR ');
knex('categories')
.whereRaw(condition)
.select('*')
.catch(_error.bind(null, cb))
.then(function(res) { ... });
Would escaping the id in the condition with a function described here be sufficient to escape that query?
What else to look out fo in such a scenario?
All knex queries are safe, also the knex.raw() queries if you use parameter binding syntax where ? are replaced with escaped values (http://knexjs.org/#Raw).
Query that you are doing would be better be done without raw as follows
knex('categories').whereIn('id', ids).catch(...).then(...);
If you want to use automatic escaping of column reference a.k.a identifier you may use whereRaw('?? = ?', ['id', value]) which escapes first part as identifier and second part as value.
So with parameter escaping your example would be something like this:
var condition = _.map(ids, function() {
return '?? = ?';
}).join(' OR ');
var conditionParameters = _.flatten(_.map(ids, function(id) {
return ['id', id];
}));
knex('categories')
.whereRaw(condition, conditionParameters)
.select('*')
.catch(_error.bind(null, cb))
.then(function(res) { ... });
However I have to say that there is pretty much always better ways to do the queries in knex than using raw conditions made this way.

zend framework automatically alter queries

My database (mysql) tables use TIMESTAMP columns, and whenever I want them returned in a query, I want them to be queried as "UNIX_TIMESTAMP(columnname)".
How do you easily modify queries in zend framework to achieve this?
For example, the current code is:
select = $this->select();
$select->where('user_id = ?',$user_id);
return $this->fetchAll($select);
This eventually becomes:
select * from tablename where user_id = 42;
I want something that automatically finds the TIMESTAMP column and changes the resulting query to:
select user_id,name,unix_timestamp(created) where user_id = 42;
I know I can use a MySQL view to achieve this, but I'd rather avoid that.
Thanks.
RR
You should be able to specify the fields you want in the select using the $select->from() object.
Zend_Db_Select
You should end up with something like this.
$select = $this->select();
$select->from(
array('t' => 'tablename'),
array('user_id', 'name', 'UNIX_TIMESTAMP(created)')
);
$select->where('user_id = ?',$user_id);
return $this->fetchAll($select);
If you wanted to run an expression that doesn't have parenthese in the function, Use the Zend_Db_Expr() method to escape the query properly.

Populate JOIN into a list in one database query

I am trying to get the records from the 'many' table of a one-to-many relationship and add them as a list to the relevant record from the 'one' table.
I am also trying to do this in a single database request.
Code derived from Linq to Sql - Populate JOIN result into a List almost achieves the intended result, but makes one database request per entry in the 'one' table which is unacceptable. That failing code is here:
var res = from variable in _dc.GetTable<VARIABLE>()
select new { x = variable, y = variable.VARIABLE_VALUEs };
However if I do a similar query but loop through all the results, then only a single database request is made. This code achieves all goals:
var res = from variable in _dc.GetTable<VARIABLE>()
select variable;
List<GDO.Variable> output = new List<GDO.Variable>();
foreach (var v2 in res)
{
List<GDO.VariableValue> values = new List<GDO.VariableValue>();
foreach (var vv in v2.VARIABLE_VALUEs)
{
values.Add(VariableValue.EntityToGDO(vv));
}
output.Add(EntityToGDO(v2));
output[output.Count - 1].VariableValues = values;
}
However the latter code is ugly as hell, and it really feels like something that should be do-able in a single linq query.
So, how can this be done in a single linq query that makes only a single database query?
In both cases the table is set to preload using the following code:
_dc = _db.CreateLinqDataContext();
var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<VARIABLE>(v => v.VARIABLE_VALUEs);
_dc.LoadOptions = loadOptions;
I am using .NET 3.5, and the database back-end was generated using SqlMetal.
This link may help
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
Look under join operators. You'll probably have to change from using extension syntax other syntax too. Like this,
var = from obj in dc.Table
from obj2 in dc.Table2
where condition
select