Kohana Query Builder: and or where clause - kohana

->where('orders.date_paid', 'BETWEEN', array($from, $to))
->and_where('orders.status', '=', 'new')
->or_where('orders.status', '=', 'delivered')
I would like to show all rows where date_paid is between $from and $to, where status is either new or delivered.
When i add this or_where(), it ignores the BETWEEN $from and $to date_paid where clause.
How can i do this right?

You need to group your conditions.
->where('orders.date_paid', 'BETWEEN', array($from, $to))
->and_where_open()
->where('orders.status', '=', 'new')
->or_where('orders.status', '=', 'delivered')
->and_where_close();

Related

Insert multiple values into a column of a table in PostgreSQL [duplicate]

A single row can be inserted like this:
client.query("insert into tableName (name, email) values ($1, $2) ", ['john', 'john#gmail.com'], callBack)
This approach automatically comments out any special characters.
How do i insert multiple rows at once?
I need to implement this:
"insert into tableName (name, email) values ('john', 'john#gmail.com'), ('jane', 'jane#gmail.com')"
I can just use js string operators to compile such rows manually, but then i need to add special characters escape somehow.
Use pg-format like below.
var format = require('pg-format');
var values = [
[7, 'john22', 'john22#gmail.com', '9999999922'],
[6, 'testvk', 'testvk#gmail.com', '88888888888']
];
client.query(format('INSERT INTO users (id, name, email, phone) VALUES %L', values),[], (err, result)=>{
console.log(err);
console.log(result);
});
One other way using PostgreSQL json functions:
client.query('INSERT INTO table (columns) ' +
'SELECT m.* FROM json_populate_recordset(null::your_custom_type, $1) AS m',
[JSON.stringify(your_json_object_array)], function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
Following this article: Performance Boost from pg-promise library, and its suggested approach:
// Concatenates an array of objects or arrays of values, according to the template,
// to use with insert queries. Can be used either as a class type or as a function.
//
// template = formatting template string
// data = array of either objects or arrays of values
function Inserts(template, data) {
if (!(this instanceof Inserts)) {
return new Inserts(template, data);
}
this.rawType = true;
this.toPostgres = function () {
return data.map(d=>'(' + pgp.as.format(template, d) + ')').join(',');
};
}
An example of using it, exactly as in your case:
var users = [['John', 23], ['Mike', 30], ['David', 18]];
db.none('INSERT INTO Users(name, age) VALUES $1', Inserts('$1, $2', users))
.then(data=> {
// OK, all records have been inserted
})
.catch(error=> {
// Error, no records inserted
});
And it will work with an array of objects as well:
var users = [{name: 'John', age: 23}, {name: 'Mike', age: 30}, {name: 'David', age: 18}];
db.none('INSERT INTO Users(name, age) VALUES $1', Inserts('${name}, ${age}', users))
.then(data=> {
// OK, all records have been inserted
})
.catch(error=> {
// Error, no records inserted
});
UPDATE-1
For a high-performance approach via a single INSERT query see Multi-row insert with pg-promise.
UPDATE-2
The information here is quite old now, see the latest syntax for Custom Type Formatting. What used to be _rawDBType is now rawType, and formatDBType was renamed into toPostgres.
You are going to have to generate the query dynamically. Although possible, this is risky, and could easily lead to SQL Injection vulnerabilities if you do it wrong. It's also easy to end up with off by one errors between the index of your parameters in the query and the parameters you're passing in.
That being said, here is an example of how you could do write this, assuming you have an array of users that looks like {name: string, email: string}:
client.query(
`INSERT INTO table_name (name, email) VALUES ${users.map(() => `(?, ?)`).join(',')}`,
users.reduce((params, u) => params.concat([u.name, u.email]), []),
callBack,
)
An alternative approach, is to use a library like #databases/pg (which I wrote):
await db.query(sql`
INSERT INTO table_name (name, email)
VALUES ${sql.join(users.map(u => sql`(${u.name}, ${u.email})`), ',')}
`)
#databases requires the query to be tagged with sql and uses that to ensure any user data you pass is always automatically escaped. This also lets you write the parameters inline, which I think makes the code much more readable.
Using npm module postgres (porsager/postgres) which has Tagged Template Strings at the core:
https://github.com/porsager/postgres#multiple-inserts-in-one-query
const users = [{
name: 'Murray',
age: 68,
garbage: 'ignore'
},
{
name: 'Walter',
age: 80,
garbage: 'ignore'
}]
sql`insert into users ${ sql(users, 'name', 'age') }`
// Is translated to:
insert into users ("name", "age") values ($1, $2), ($3, $4)
// Here you can also omit column names which will use all object keys as columns
sql`insert into users ${ sql(users) }`
// Which results in:
insert into users ("name", "age", "garbage") values ($1, $2, $3), ($4, $5, $6)
Just thought I'd post since it's like brand new out of beta and I've found it to be a better philosophy of SQL library. I think would be preferable over the other postgres/node libraries posted in other answers. IMHO
Hi I know I am late to the party, but what worked for me was a simple map.
I hope this will help someone seeking for same
let sampleQuery = array.map(myRow =>
`('${myRow.column_a}','${myRow.column_b}') `
)
let res = await pool.query(`INSERT INTO public.table(column_a, column_b) VALUES ${sampleQuery} `)
client.query("insert into tableName (name, email) values ($1, $2),($3, $4) ", ['john', 'john#gmail.com','john', 'john#gmail.com'], callBack)
doesn't help?
Futher more, you can manually generate a string for query:
insert into tableName (name, email) values (" +var1 + "," + var2 + "),(" +var3 + ", " +var4+ ") "
if you read here, https://github.com/brianc/node-postgres/issues/530 , you can see the same implementation.

Writing a query in knex, where i need to use where with the insert query

This is the raw query, which is working -
Insert into members (activity, emp_id, plan_id) VALUES ('admin', 21937, 2463) on conflict(emp_id, plan_id) where ("responsibility" != 'admin') DO Nothing;
Converted this query into knex query, but it's avoiding the where clause when I printed the query build by knex.
let result = knex('members').withSchema('public').insert(insertParameters);
result = result
.whereNotIn({
'member.responsibility': 'admin',
})
.onConflict(['emp_id', 'plan_id'])
.ignore();
result = await result.returning('id');
return result;
Query prepared by knex -
insert into "public"."member" ("plan_id", "responsibility", "emp_id") values ($1, $2, $3), ($4, $5, $6), ($7, $8, $9) on conflict ("emp_id", "plan_id") do nothing returning "id"
There is an index created for columns -emp_id, plan_id, and responsibility != 'admin', so we need to write the where clause.

How to add 2 conditions in 'new nlobjSearchFilter'?

My code is like that:
var filters = new Array();
filters[0] = new nlobjSearchFilter("isperson", "customer", "is", "F")
filters[1] = new nlobjSearchFilter([["minimumquantity", "equalto", "0"], "OR", ["minimumquantity", "isempty", ""]]);
if (customerId) filters.push(new nlobjSearchFilter("customer", null, "anyof", customerId));
if (currency) filters.push(new nlobjSearchFilter("currency", null, "anyof", currency));
My question is how do I make filters[1] works with the 'OR' operator?
You were on the right track with the 'or' condition.
I can't tell which record you're trying to query, but the easiest way to control multiple and/or conditions when building a search is to use search "filter expressions" rather than manually building with nlobjSearchFilter().
If you want to continue using nlobjSearchFilter(), look up how to use the .setLeftParens()/.setRightParens() and .setOr() functions (example). They're not documented in the NetSuite help).
var filters = [
// this is how joins are referenced in filter expressions
// this is equivalent to nlobjSearchFilter('isperson', 'customer', 'is', 'F')
['customer.isperson', 'is', 'F'],
'and', [
['minimumquantity', 'equalto', 0], 'or', ['minimumquantity', 'isempty', null]
],
];
if (customerId) filters.push('and', ['customer', 'anyof', customerId]);
if (currencyId) filters.push('and', ['currency', 'anyof', currency]);

Adding OR condition with other than entity column in typeorm gives error: could not determine data type of parameter $2

I want to generate postgres query as below:
select * from table1 t1 inner join table2 t2 on t1.id = t2.table1_id
where param.name is null or t1.name ilike param.name
Here param is request parameter
I tried with this:
await this.userRepository.createQueryBuilder("t1")
.innerJoinAndSelect("t1.table2","t2")
.where("t1.name ilike :name or :name is null",{ name:`%${request.body.name}%`)
.getMany()
This returns following error:
QueryFailedError: could not determine data type of parameter $2
I just tried the example and got the same error, from my experience I think this is a bug with typeorm
I suggest you change your aproach to the problem, try this:
await this.userRepository.createQueryBuilder("t1")
.innerJoinAndSelect("t1.table2","t2")
.where("t1.name ilike :name",{ name: req.body.name ? `%${request.body.name}%` : '%%')
.getMany()
this will work the same as the provided query.
I used below query to meet my need:
await this.userRepository.createQueryBuilder("t1")
.andWhere(new Brackets(q => {
q.where("d.name ilike :name", { name:`%${request.body.name}%`})
q.orWhere("cast(:param as character varying) is null", { param: request.body.name || null})
}))

extend wordpress search query

I have a working search query with offset and post_per_page (the user can go through pages)
$args = array(
'post_type' => 'type',
's'=>$the_str,
'posts_per_page' => $the_count,
'offset' => ($the_count*$the_c_page )-$the_count
);
$the_query = new WP_Query( $args );
It works great.
But now I need to add a meta field to the search function. It should get all post where s=>$query OR meta-field=>$query
Something like this:
$args = array(
'post_type' => 'type',
'posts_per_page' => $the_count,
'offset' => ($the_count*$the_c_page )-$the_count,
'meta_query' => array(
'relation' => 'OR',
's'=>$the_str,
array(
'key' => 'key',
'value' => $the_str
)
);
$the_query = new WP_Query( $args );
Unfortunately this will only search after the second condition. Does anybody have an idea?
If you crack open query.php you'll see that it really isn't built with this in mind. It isn't that it isn't a great idea, it's just that each individual query part is concatenated onto the main WHERE using an AND. So "title contains XYZ" AND "whatever the meta query is" AND "whatever the tax query is", etc. Meta and Tax both have sub logic within them that supports AND and OR but there's no way to perform this between these outer parts.
However, you might be able to do what you're looking for by tapping into one of the filters, possibly get_meta_sql. The meta query returns a statement that puts in the AND that you want to be an OR so you can just look for that and replace it:
function change_and_to_or_for_meta( $meta_query, $type, $primary_table, $primary_id_column, $context )
{
if( 0 === strpos( $meta_query['where'], ' AND' ) )
{
$meta_query['where'] = ' OR' . substr( $meta_query['where'], 4 );
}
return $meta_query;
}
//Add our filter to replace the AND at the start with OR
add_filter( 'get_meta_sql', 'change_and_to_or_for_meta', 10, 5 );
$query = new WP_Query( $args );
//Remove our filter so we don't mess other things up
remove_filter( 'get_meta_sql', 'change_and_to_or_for_meta', 10 );

Resources