Overriding ilike method by like in grails createCriteria - mysql

In my application we have collation set for MYSQL in such a way that "like" condition is always case in-sensitive. So, we need conditionally ilike to replaced with like at run time based on config. (Because, in future database might be Oracle or some other DB.Want to handle this at application level.)
Tried one solution which does not works. I want this at application level:
grails.orm.HibernateCriteriaBuilder.metaClass.ilike={String propertyName, Object propertyValue->
println "-------------------${propertyName}, ${propertyValue}"
delegate.like(propertyName, propertyValue)
}
def criteria= MyDomain.createCriteria()
criteria.list(){
ilike('name','%dasda%')
}
So, Any other way would also be appreciated.
Thanks in Advance,
Anuj Aneja

Related

In strapi, that is configured to use MySql, how do I create a new content type record in the code?

y'all,
Within my custom, strapi content type, controller code, what method in the model object do I use to create a new record? My app is configured to use MySql.
The following worked fine when I was using MongoDB, but now with MySql, it doesn't work.
With Mongo, in my code, I was doing this:
let model = strapi.models[modelName];
await model.create({"Name":"<NEW ENTRY>", "Path":ruleData.requestedPath});
, but now, with MySql, I get an error saying that model.create() is not a function. 🤔
Also, when I step into the code, create() is no longer there. I also can't seem to find the equivalent "create" method in the model object, for mysql.
??? Does the strapi ORM, model object change member functions, etc when moving from MongoDB to MySql??? I thought not since that was a big part of the reason for using the ORM.
I suggest you use strapi.query('article') instead of strapi.models.article
So it will be strapi.query('article').create({...})

Multiple, unknown number of fields passed into a query

Is it possible to create a generic query that would work for different types of documents? For example I have "cases" and "factories",
They have different set of fields. e.g:
{
id: 'case_o1',
name: 'Case numero uno',
amount: 40
}
{
id: 'factory_002',
location: 'Venezuela',
workers: 200,
operating: true
}
Is it possible to create a generic query where I would pass the type of an entity (case or factory) and additional parameters and it would filter results based on those?
I could of course use javascript view, but it doesn't allow me to filter by multiple fields. Let's say I want to fetch all factories located in Venezuela, with number of workers between 20 and 55.
I started with this, but then I got stuck:
select * from `mybucket` as entity
where position(meta(entity).id, $entity_type) == 0
How do I pass multiple predicates and have the query to recognize them?
I can of course list fields like this:
where position(meta(entity).id, $entity_type) == 0
and entity.location == 'Venezuela'
and entity.workers > $workers_min
and entity.workers < $workers_max
but then
I'm gonna have to create a separate query for each entity
And even then it won't solve my problem - I have no idea how to ignore predicates, what if next time $workers_min and $workers_max are not passed, does it mean I have to create a query for every single predicate (column)?
For security reasons I cannot generate free-form queries and pass them to Couchbase server, all the queries are already stored in the database, our api just picks them up out of a document and executes them
I think it's possible to create a query that would be "short-circuiting" for args that's undefined (e.g. WHERE $location IS MISSING OR entity.location == $location or something like that)
Is it possible at all to create a query that would be able to effectively filter and order a dataset based on arbitrary parameters? Or there's no way?
#Agzam. Sorry. I were writting my comment when you said it. But anyway. What you are asking for is possible by using coalesces in a not too complex expressions, but it is a REALLY bad idea because this will drastically throw down most of internal database optimizations. Including the use of any existing index. So, except if you are dealing with a relatively small database (and you are sure it will remain being approximately the same size), I suggest you to better try distinct approach… This is, in fact, the reason I implmented sqlapi.
If you need to have all querys previously stored in database, it probably could be much better to sort given arguments by its name and precalculate and store precalculated querys for each possible combination.
You can do it by assigning a default value to the variable when is not used. For instance if $location is not used you can set it to -1 as default value.
Then the where condition would be:
WHERE ($location=-1 OR entity.location = $location)

Find similar names using Couchbase server 3.0 and port 8092

I want to find the similar location names using couchbase server. i created an index as follows
function (doc, meta) {
emit(doc.loc_name, doc);
}
this is how i query data
http://IP Address:8092/dev-locations/_design/dev_test_view/_view/searchByLocationName?full_set=true&inclusive_end=true&stale=false&connection_timeout=60000&key=%22Joh%22
But this will return only if the exact match found. What i am looking for is when i send the key joh, it should return johenaskirchen and johenasberg (same as our LIKE in MySQL)
Any help will be highly appreciated.
Note : I already tried N1QL and i am looking for ways to implement this without N1QL
the key parameter is an exact match. What you want is a combination of startKey and endKey:
?startkey=%22joh%22&endkey=%22joh\uefff%22
The \uefff is a trick, this unicode character can be seen as "the biggest character" so it ensures that a key like johzzzzzz will still be considered under the upper bound of joh\uefff (endkey is inclusive).

Creating an OR statement using existing conditions hash

I am working on a problem where I need to add an OR clause to a set of existing conditions. The current conditions are built in a hash in a method and at the end, they are used in the where clause. Here is a simplified example:
...
conds.merge!({:users => {:archived => false}})
Model.where(conds)
I am trying to add an OR clause to the current set of conditions so it would be something like '(conditions) OR new_condition'. I'd like to add the OR statement without converting each addition to the conds hash into a string. That would be my last option. I was hoping someone has done something like this before (without using Arel). I seem to recall in Rails 2 there was a way to parse a conditions hash using a method from the model (something like Model.some_method(conds) would produce the where clause string. Maybe that would be a good option to just add the OR clause on to that string. Any ideas are appreciated. Thank you for your help!
I found a way to do what I needed. Instead of changing all of the conditions that I am building, I am parsing the conditions to SQL using sanitize_sql_for_conditions. This is a private method in ActiveRecord, so I had to put a method on the model to allow me to access it. Here is my model method:
def self.convert_conditions_hash_to_sql(conditions)
self.sanitize_sql_for_conditions(conditions)
end
So, once I convert my conditions to text, I can add my OR clause (along with the appropriate parentheses) to the end of the original conditions. So, it would go something like this:
Model.where('(?) OR (model.type = ? AND model.id IN(?))', Model.convert_conditions_hash_to_sql(conds), model_type, model_id_array)

Codeigniter order_by with CONVERT

I have to order a selection by CONVERT(`codExtern`, SIGNED) with codeIgniter.
If I use it like this:
$this->db->order_by(" CONVERT(`codExtern`, SIGNED) ");
the codeigniter puts the SIGNED word between `-s, like:
CONVERT(codExtern, `INTEGER` )
How can I make it work?
Unfortunately you can't disable identifier protection with parameters like in the select() method. CI will call CI_DB_driver::_protect_identifiers on the input if it has a , in it.
Currently you can workaround this if you set the supposedly "private" property $_protect_identifiers to false on your $this->db before calling the order_by method so when it runs it will skip this, and then flip it back (it helps with problematic column/table names for example). This is probably not a really good idea, in future CI versions this property might became really private and your code will break.
Unfortunately the database library cannot be extended, but if you are not afraid of modifying the files under system you can create an exception in the order_by() method just like the "order by random()" got one.