ZF2 - How to correctly concatenate a select statement containing a CONCAT function - postgresql

I'm new to Zend and to Postgres. My Users table contains a FirstName column and a LastName column.
I want to query the table using a single 'full name' string; e.g. $search = 'John Sm'.
I'm trying to use the CONCAT_WS function to concatenate the two names from the table, and then compare this with the search string.
My statement
$select->where(array('CONCAT_WS(" ", "u"."FirstName", "u"."LastName") LIKE ?' => array("%$search%")));
I've tried different combinations but can't seem to get the concatenation right.
An example of the statement I want is SELECT * FROM Users WHERE 'firstname lastname' LIKE '%john s%'

This doesn't answer your question, but have you considered making a view for this?

Did you check the latest version of the documentation?
https://framework.zend.com/manual/1.12/en/zend.db.statement.html

If you use array as parameter in your $select->where() it is interpreted as pairs ['column1' => 'value', 'column2' => 'value']. In this solution you can't use functions and combined parts of query.
You can use Zend\Db\Sql\Predicate\Literal(), eg.:
$select->where
->literal('CONCAT_WS(" ", "u"."FirstName", "u"."LastName") LIKE \'%word%\'')
or use Zend\Db\Sql\Predicate\Expression(), eg.:
$select->where
->expression('CONCAT_WS(" ", "u"."FirstName", "u"."LastName") LIKE \'%?%\'', $word)
(second parameter can bee array if variables is more)
In this solution you can build sql WHERE using the same method
$select->where
->equalsTo()
->or
->greatherThan()
->and
->like()
->nest()
->lessThan()
->or
->literal()
->unnest()
...
https://framework.zend.com/manual/2.2/en/modules/zend.db.sql.html#id7
Also you can build as Zend\Db\Sql\Where / Zend\Db\Sql\Predicate as eg.:
$where = new Where();
$where->equalsTo();// and more, more, more, with sub-where inclusive
$select->where->predicate($where);

Related

how to use IN-function within Zend_Select

I different string values komma separated out of a form.
In the code I cast them and then it looks like this:
$kritkeyword ='test, abc, xyz';
Now I want to use the variable within an IN-function. In original sql ist would be:
where keyword IN ('test', 'abc', 'xyz')
In my code I tried to do the following:
$select->where('keyword IN (?)', $kritkeyword);
I also tried:
$select->where(['keyword IN ?' =>$kritkeyword]);
Until now I had different ideas how to write it, but I always get a sql error. So how to do this correct?
You must use Zend\Db\Sql\Where. If $kitkeyword is array :
$condition = new Zend\Db\Sql\Where();
$condition->in('keyword', $kritkeyword);
$select->where($condition);

How use '?' in #Query? How use Jsonb of postgres in spring-boot at all?

How to use ?| operator in postgres query in spring repository? I need to use where in my query for text type column which content json.
#Query(value =
"SELECT * \n" +
"FROM tbl t \n" +
"WHERE t.some_ids::::jsonb ?| array['152960','188775']", nativeQuery = true
)
List<Model> getModelsByIds();
But that don't work and I catch the next exeception:
org.springframework.dao.InvalidDataAccessApiUsageException: At least 1 parameter(s) provided but only 0 parameter(s) present in query.
You can use the associated function of that operator instead. Most of the time the obfuscation layers also choke on the :: cast operator, so you might want to use cast() instead:
WHERE pg_catalog.jsonb_exists_any(cast(t.some_ids as jsonb), array['152960','188775'])
However I think this wouldn't be able to make use of an index defined on some_ids::jsonb
You didn't mention how exactly the content of some_ids looks like.
If that is a JSON array (e.g. '["123", "456"]'::jsonb) then you can also use the contains operator #>:
WHERE cast(t.some_ids as jsonb) #> '["152960","188775"]'
If your JSON array contains numbers rather than strings ('[123,456]') you need to pass numbers in the argument as well:
WHERE cast(t.some_ids as jsonb) #> '[152960,188775]'

MongoDB - Contains (LIKE) query on concatenated field

I am new in MongoDB.
I am programming an application with spring data and mongodb and I have one class with two fields: firstname and lastname.
I need one query for documents that contain one string in the full name (firstname + lastname).
For example: firstname = "Hansen David", lastname = "Gonzalez Sastoque" and I have a query to find David Gonzalez. In this example I expect there to be a match.
Concatenate two strings solves it but I don't know how to perform this.
Create a new array field (call it names) in the document and in that array put each name split by space. In your example the array would have the following contents:
hansen
david
gonzalez
sastoque
(make them all lower case to prevent case insensitivity issues)
Before you do your query, convert your input to lower case and split it by spaces as well.
Now, you can use the $all operator to achieve your objective:
db.persons.find( { names: { $all: [ "david", "gonzalez" ] } } );
You can use $where modifier in your queries:
db.users.findOne({$where: %JavaScript to match the document%})
In your case it may look like this:
db.users.findOne({$where: "this.firstname + ' ' + this.lastname == 'Gonzalez Sastoque'"})
or this:
db.users.findOne({$where: "this.firstname.match(/Gonzalez/) && this.lastname.match(/Sastoque/)"})
My last example does exactly what you want.
Update: Try following code:
db.users.findOne({$where: "(this.firstname + ' ' + this.lastname).match('David Gonzalez'.replace(' ', '( .*)? '))"})
You should split your full name into a first name and a last name, then do your query on both fields, using the appropriate MongoDB query selectors.

search by date on DBIx::Class

I have a table in a SQLite database where a column stores file mtimes in epoch seconds.
I would now like to search in that table files that were modified in a certain month?
In raw SQL I would do:
select * from my_table where strftime('%Y-%m', mtime, "unixepoch") = "2009-08"
Is there a way to do this efficiently via DBIx::Class? Is it possible to do
$m->search({ \'strftime('%Y-%m', mtime, "unixepoch")' => "2009-08" })
I tried understanding if there's a way with DBIx::Class::InflateColumn::DateTime but I didn't find it.
Thanks
Simone
The syntax you're looking for is:
$m->search(
\[ q{strftime('%Y-%m', mtime, "unixepoch") = ?}, "2009-08" ]
);
Yes, that's an array-ref-ref. The first element is literal SQL which is permitted to use ? placeholders, and the remaining elements are values to bind to those placeholders, and DBIC will make sure to reorder everything internally so that those values get put into the right place in the bind list when the query runs.
If you need to combine one of these with other criteria, since an arrayrefref isn't a valid hash key, you need to use the -and syntax:
$m->search({
-and => [
foo => 'bar',
\[ q{ SQL }, $bind ],
],
});
Here is the section of the SQL::Abstract docs for this construct.
I would suggest you using search_literal instead:
# assuming $m isa DBIx::Class::ResultSet
$m->search_literal('strftime("%Y%m", mtime, "unixepoch") = ?', '200908');
EDIT: I stand corrected. Please refer to #hobbs' comment and answer.

Zend Framework: Re-use WHERE clause returned from Zend_Db_Select::getPart()

I have a SELECT object which contains a WHERE.
I can return the WHERE using getPart(Zend_Db_Select::WHERE), this returns something like this:
array
0 => string "(clienttype = 'agent')"
1 => string "AND (nextpayment < (NOW() - INTERVAL 1 DAY))"
This array seems pretty useless as I cannot do this with it
$client->update(array("paymentstatus" => "lapsed"), $where);
Or even put it into another SELECT object. Is there a way of getting a more useful representation of the WHERE statement from the SELECT object?
Thanks
EDIT
The best I have come up with so far is
$where = new Zend_Db_Expr(implode(" ", $select->getPart(Zend_Db_Select::WHERE)));
Your first choice, $client->update(...) would work, if getParts omitted the 'AND' from the second part of the where clause.
I'm pretty sure your only choice is to:
use your second option (probably safest depending on how complex the where clauses are) -or-
iterate through the $where returned and remove the leading 'AND', 'OR' that may exist.