IFNULL in Symfony2 Doctrine query builder - sql

How is the IFNULL of SQL implemented in Symfony2 Doctrine Query Builder?
Let's say I have this query:
select * from ticket order by IFNULL(modified_date, '2000-01-01') DESC, created_date DESC
I have this DQL:
$this->qb->select("t, c.name")
->from("Ticket", "t");
$this->qb->orderBy("t.modifiedDate", "DESC");
$this->qb->addOrderBy("t.createdDate", "DESC");
Now how to add the IFNULL part?

Ok, done some research and found that there is no such implementation.
Googled a little more, and got that this kind of missing features can be added to Doctrine as own functions.
Found this extension on GitHub I think this will work. But wonder if ther would be any problems or conflicts with Doctrine versions...

This is the valid link with the DQL Extension
Edit with the solution explained:
Create the following directory under your project src path: /src/DoctrineExtensions/Query/Mysql
Put there the DQL Extension file (IfNull.php in this case)
Edit your src/config/packages/doctrine.yaml and insert this new lines:
doctrine:
...
orm:
...
dql:
numeric_functions:
IFNULL: App\DoctrineExtensions\Query\Mysql\IfNull
In your entity repository you can call this function like this:
$qb = $this->createQueryBuilder('tl')
->andWhere('IFNULL(tl.app,0) = 1');

Depending on your usecase you may be able to use the builtin "COALESCE" expression instead of installing the "IFNULL" extension.
The usage then is basically the same as with the IFNULL expression.
Just replace IFNULL with COALESCE in the example in https://stackoverflow.com/a/68827681/1707003.
Note: COALESCE might behave slightly different than IFNULL depending on your database. https://stackoverflow.com/a/18528590/1707003 contains some great explanations.
List of builtin case-expressions: https://www.doctrine-project.org/projects/doctrine-orm/en/2.13/reference/dql-doctrine-query-language.html#case-expressions

Related

Using PosgreSQL array_agg with join alias in JOOQ DSL

I want to convert this SQL query to JOOQ DSL.
select "p".*, array_agg("pmu") as projectmemberusers
from "Projects" as "p"
join "ProjectMemberUsers" as "pmu" on "pmu"."projectId" = "p"."id"
group by "p"."id";
Currently i have tried doing something like this using JOOQ:
val p = PROJECTS.`as`("p")
val pmu = PROJECTMEMBERUSERS.`as`("pmu")
val query = db.select(p.asterisk(), DSL.arrayAgg(pmu))
.from(p.join(pmu).on(p.ID.eq(pmu.PROJECTID)))
.groupBy(p.ID)
This does not work because DSL.arrayAgg expects something of type Field<T> as input.
I am new to JOOQ and not an SQL professional. Detailed explanations and impovement suggestions are highly appreciated.
First of all, the syntax indeed works, checked this in SQL Fiddle: http://sqlfiddle.com/#!17/e45b7/3
But it's not documented in detail: https://www.postgresql.org/docs/9.5/static/functions-aggregate.html
https://www.postgresql.org/docs/current/static/rowtypes.html#ROWTYPES-USAGE
That's probably the reason jOOQ doesn't support this currently: https://github.com/jOOQ/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/DSL.java#L16856
The only syntax that will work currently is with a single field: DSL.arrayAgg(pmu.field(1))
What you're looking for is a way to express PostgreSQL's "anonymous" nested records through the jOOQ API, similar to what is requested in this feature request: https://github.com/jOOQ/jOOQ/issues/2360
This is currently not possible in the jOOQ API as of version 3.11, but it definitely will be in the future.
Workaround 1
You could try using the experimental DSL.rowField() methods on a Row[N]<...> representation of your table type. This may or may not work yet, as the feature is currently not supported.
Workaround 2
A workaround is to create a type:
create type my_type as (...) -- Same row type as your table
And a view:
create view x as
select "p".*, array_agg("pmu"::my_type) as projectmemberusers
from "Projects" as "p"
join "ProjectMemberUsers" as "pmu" on "pmu"."projectId" = "p"."id"
group by "p"."id";
And then use the code generator to pick up the resulting type.

Using built-in SQL functions with SequelizeJS

Can I make Sequelize JS to include combined field to the result set, to get results like for following query?
SELECT id, NOW()-timestamp as recordAge FROM myTable
I wouldn't use raw query for this task, prefer to resolve it with model paradigm.
As there was no answer but someone has starred my question I'm posting the answer I've found myself:
The solution is to use Sequelize.literal() function. As for example in the question, the answer is following:
options = {};
options.attributes = ['id', sequelize.literal('(NOW() - timestamp) as recordAge')];
MyTable.find(options).success(success);

"Searching" a string on a MongoDB DB with MongoMapper

I'm making a webapp where I'm using MongoMapper and Sinatra. I wonder how could I implement a search feature against a DB's collection. I though something like SQL's:
SELECT * FROM posts WHERE match(title) against ("String to search");
How could I achieve this with MongoMapper? Thanks!
ok this is from my project and does work:
Post.where(:title => Regexp.new(/^string/i)) # Limit output with: .limit(10)
Maybe it's the Regexp?
You query for documents that match a case sensitive rooted regular expression:
Post.where(:title => /^stringtosearch/).first
MongoDB does not support full text search so this is the best you can do at the moment.

How to turn on REGEXP in SQLite3 and Rails 3.1?

I have the following statement in Rails 3 using an SQLite3 database:
word = 'Hello'
word_entry = Word.where("name REGEXP :word", {:word => "[[:<:]]#{word}[[:>:]]"})
However, when running this under SQLite3, I keep getting:
SQLite3::SQLException: no such function: REGEXP
I read in the SQLite3 documentation that it does indeed support the REGEXP function.
In my gemfile, I have the line
gem 'sqlite3'
And my database config file looks like this:
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
Any ideas what's going on?
RESOLUTION:
I ended up finding this solution. Unfortunately, it doesn't work for Rails 3.
So to use regular expressions I ended up switching to MYSQL instead of SQLite3.
I ran into the same issue. I took the code used in the resolution, ported it to work with Rails 3+ and made a gem for easier use. I hope this helps.
https://github.com/sei-mi/sqlite3_ar_regexp
From the fine manual:
The REGEXP operator is a special syntax for the regexp() user function. No regexp() user function is defined by default and so use of the REGEXP operator will normally result in an error message. If a application-defined SQL function named "regexp" is added at run-time, that function will be called in order to implement the REGEXP operator.
So the grammar supports REGEXP but the default SQLite library does not provide an implementation for it. You'll have to hook up your own implementation through some C wrangling if you want or need such a thing.
Presumably the rationale is that the SQLite people want to keep SQLite as small and tight as possible but including a whole regular expression library would add weight that most people don't want. Also, they would have to choose a regular expression library and include it with the SQLite source or they'd have to put up with the vagaries of everyone's regular expression support in libc. I'm not one of the SQLite developers so this is pure speculation.
I'm guessing that you'll probably have to make do with LIKE and GLOB. Using LIKE will provide a more portable solution.
You may be intested in the sqlite3-pcre package, which implements REGEXP for SQLite.
See this comment on a similar issue.
I had a similar question, and found a Gem named wherex that is well documented and worked out of the box.
Your expression from above
Word.where("name REGEXP :word", {:word => "[[:<:]]#{word}[[:>:]]"})
would there be
Word.where(:name => Regexp.new("[[:<:]]#{word}[[:>:]]"))
Works like a charm for me :-)
From source of sqlite3_ar_regexp project, I extract this:
db = SQLite3::Database.open( database_name )
db.create_function('regexp', 2) do |func, pattern, expression|
func.result = expression.to_s.match(
Regexp.new(pattern.to_s, Regexp::IGNORECASE)) ? 1 : 0
end
From source of sqlite3_ar_regexp project, I extract this:
db = ActiveRecord::Base.connection.raw_connection
db.create_function('regexp', 2) do |func, pattern, expression|
func.result = expression.to_s.match(
Regexp.new(pattern.to_s, Regexp::IGNORECASE)) ? 1 : 0
end
Improved upon a previous answer with ActiveRecord::Base.connection.raw_connection so that db name isn't needed

nHibernate 3.0 queries

Working through the summer of nHibernate tutorials have gotten to the section on queries. Seems there have been changes since that series was made. So I went to the online docs for nHB 3.0 but code such as:
IList cats = session.CreateCriteria(typeof(Cat))
.Add(Expression.Like("Name", "Fritz%"))
.Add(Expression.Between("Weight", minWeight, maxWeight))
.List();
Generates the error "The name 'Expression' does not exist in the current context"
Code like:
return session.CreateCriteria(typeof(DataTransfer.Customer))
.Add(new NHibernate.Criterion.LikeExpression("Firstname", firstname))
.Add(new NHibernate.Criterion.LikeExpression("Lastname", lastname))
.List<Customer>();
Works but it seems that it is missing a number of query methods like GtExpression.
Are the online docs up to date, and if so, why can't I use Expression...
If the online docs aren't up to date then where do I get a description of the Criterion interface?
Thanks
You forgot to add using NHibernate.Criterion;.
Anyway, the Expression class is deprecated. Use Restrictions instead.
Weird thing. I still use Expression.* static methods and these are still work. Are you sure you use the latest version of NH3.0? I use Alpha 2 version.
If you need to make it work urgently, let's try the QueryOver<> feature:
return session.QueryOver<DataTransfer.Customer>()
.WhereRestrictionOn(u => u.Name).IsLike("Fritz%")
.AndRestrictionOn(u => u.Weight).IsBetween(minWeight).And(maxWeight)
.List();
It works well for simple queries