Doctrine DQL throws fatal error on query builder - doctrine-orm

I follow pagination example from Doctrine but get fatal error:
PHP Fatal error: Uncaught Doctrine\ORM\Query\QueryException: SELECT * FROM Model\Report r in /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:43
Stack trace:
#0 /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(456): Doctrine\ORM\Query\QueryException::dqlError('SELECT * FROM M...')
#1 /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(2253): Doctrine\ORM\Query\Parser->syntaxError('IdentificationV...', Array)
#2 /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(1182): Doctrine\ORM\Query\Parser->SelectExpression()
#3 /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(878): Doctrine\ORM\Query\Parser->SelectClause()
#4 /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(847): Doctrine\ORM\Query\Parser->SelectStatement()
#5 /usr/share/nginx/html/td/ven in /usr/share/nginx/html/td/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php on line 54
Here is the default example from Doctrine
https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/pagination.html
and here is my code:
<?php
use Doctrine\ORM\Tools\Pagination\Paginator;
require "bootstrap.php";
$dql = 'SELECT * FROM reports';
$max = isset($args[1])?$args[1]:5;
$query = $entityManager->createQuery($dql)->setFirstResult(0)->setMaxResults($max);
$paginator = new Paginator($query, $fetchJoinCollection = false);
$c = count($paginator);
foreach($paginator as $report){
echo $report->getName() . "\n";
}

There is no wildcard * in dql select.
Change
$dql = 'SELECT * FROM reports';
to
$dql = 'SELECT r FROM Model\Report r';
References
Wildcard in doctrine dql error
Doctrine select queries

Related

Doctrine2 DQL Syntax error when ordering by count

This is Doctrine Repository function
public function mostReadArticleByUser($userId){
$total = $this->createQueryBuilder('ar')
->select('ar.articleId', 'COUNT(ar)')
->where('ar.authorId = :userId')
->groupBy('ar.articleId')
->orderBy('COUNT(ar)', 'DESC')
->setMaxResults(1)
->setParameter('userId', $userId)
->getQuery()
->getResult();
return $total;
}
which should be equivalent to this query
SELECT article_id, count(id)
FROM profile_article_reads
WHERE author_id = 2
GROUP BY article_id
Order by count(id) DESC
LIMIT 1;
When I execute this code I get error
Error: Expected end of string, got '('
QueryException: SELECT ar.articleId, COUNT(ar) FROM
SciProfileBundle\Entity\ProfileArticleReads ar WHERE ar.authorId =
:userId GROUP BY ar.articleId ORDER BY COUNT(ar) DESC
THe count funtion accept a field, so try with
COUNT(ar.id)
instead of:
COUNT(ar)
Probably for sorting is better using an alias, as example:
public function mostReadArticleByUser($userId){
$total = $this->createQueryBuilder('ar')
->select('ar.articleId', 'COUNT(ar.id) as total')
->where('ar.authorId = :userId')
->groupBy('ar.articleId')
->orderBy('total', 'DESC')
->setMaxResults(1)
->setParameter('userId', $userId)
->getQuery()
->getResult();
return $total;
}
Hope this help

Doctrine use count() in NativeQuery with ResultSetMapping

i try to use NativeQuery of Doctrine. If i use my SQL ind Phpmyadmin i have the good result. If i use this, my var_dump return an empty array. I don't understand why.
$sql = 'SELECT COUNT(id) as nb FROM app_facture f WHERE SUBSTR(f.datecreate_facture, 1, 4) = 2014 AND SUBSTR(f.numero_facture,1,1) != "E"';
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Acme\MyBundle\Entity\Facture', 'f');
$rsm->addFieldResult('f', 'COUNT(id)', 'nb');
$query = $this->getEntityManager()->createNativeQuery($sql,$rsm);
$results = $query->getResult();
var_dump($results);//return empty array
Thanks
Try
$rsm->addFieldResult('f', 'nb', 'id');
this worked for me.

Exception in getting list from CriteriaQuery

for some reason i can't tell, there is exception when i try to get a list from CriteriaQuery using subquery. some one please help!!!
here is the code:
public String[] getProductsDistinctBySubQueriesName(String category) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
//subquery
Subquery<Integer> subqueries = criteria.subquery(Integer.class);
Root<Productscategory> productCategory = subqueries.from(Productscategory.class);
subqueries.select(productCategory.<Integer>get("productscategoryid"))
.where(builder.equal((productCategory.<String>get("productcatgoryname")), category));
//outerquery
Root<Products> root = criteria.from(Products.class);
criteria.multiselect(root.get(Products_.productname)).distinct(true)
.where(builder.in(root.get("productscategoryid")).value(subqueries));
List<Tuple> tupleResult = em.createQuery(criteria).getResultList(); // the exception is thrown here
String[] arrayProducts = new String[tupleResult.size()];
for (int i = 0; i < tupleResult.size(); i++) {
arrayProducts[i] = (String) tupleResult.get(i).get(0);
}
return arrayProducts;
}
here is the exception
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
Error Code: 1064
Error Code: 1064
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:469)
at com.inventory.service.ProductsServices.getProductsDistinctBySubQueriesName(ProductsServices.java:112)
at com.inventory.service.ProductsServices.getAllByName(ProductsServices.java:211)
at com.inventory.server.InventorySocketRequest.getServiceClass(InventorySocketRequest.java:77)
at com.inventory.server.InventorySocketRequest.run(InventorySocketRequest.java:44)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
Error Code: 1064
Call: SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))
bind => [1 parameter bound]
Query: TupleQuery(referenceClass=Products sql="SELECT DISTINCT t0.productname FROM products t0 WHERE t0.productscategoryid IN (SELECT t1.productscategoryid.t1.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = ?))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675)
at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
... 5 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.productscategoryid FROM productscategory t1 WHERE (t1.productcatgoryname = 'Pri' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
... 24 more
Try to use this query instead of yours, this works perfectly with EclipseLink provider, not sure what your query is not working in eclipselink but works in hibernate, I tested the query below and you will be able to select Products based on a ProductCategoryName.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaQuery");
EntityManager em = emf.createEntityManager();
String category = "cat2";
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Products> query = builder.createQuery(Products.class);
Root<Products> products = query.from(Products.class);
Subquery<Productscategory> squery = query.subquery(Productscategory.class);
Root<Productscategory> productCategoryRoot = squery.from(Productscategory.class);
Join<Productscategory, Products> join = productCategoryRoot.join("productsCollection");
squery.select(productCategoryRoot)
.where(builder.equal(join, products), builder.equal(productCategoryRoot.get("productcatgoryname"), category));
query.where( builder.exists(squery));
List<Products> productList = em.createQuery(query).getResultList();
for (Products product : productList) {
System.out.println(product);
}
In which category is the name of the category you are trying to search..
This solved the problem =).. If this works, don't forget to accept the answer XD.

How to paginate a native query in Doctrine 2 with zend framwork 2

Here is what I tried:
$entityManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$rsm->addEntityResult('SchoolAdmin\Entity\Maptechclass', 'Mt');
$rsm->addFieldResult('Mt', 'map_tech_class_id', 'mapTechClassID');
$rsm->addFieldResult('Mt', 'map_tech_id', 'mapTechID');
$rsm->addEntityResult('SchoolAdmin\Entity\Teacher', 'Th');
$rsm->addFieldResult('Th', 'th_id', 'th_id');
$rsm->addFieldResult('Th', 'th_first_name', 'th_first_name');
$rsm->addFieldResult('Th', 'th_last_name', 'th_last_name');
$rsm->addEntityResult('SchoolAdmin\Entity\Classes', 'Cs');
$Q = "SELECT Mt.map_tech_class_id , Mt.map_tech_id ,
Th.th_id,
Th.th_first_name,
Th.th_last_name,
Cs.class_name
FROM maptechclass Mt
LEFT JOIN teacher Th
ON Mt.map_tech_id=Th.th_teacher_id
LEFT JOIN classes Cs
ON Mt.map_class_id=Cs.class_id
WHERE Mt.map_sch_id=49";
$query = $entityManager->createNativeQuery($Q, $rsm);
$auctions = $query->getResult();
return new ViewModel(array('paginator' => $auctions));
But I get the following error:
Catchable fatal error: Argument 1 passed to Doctrine\ORM\Tools\Pagination\Paginator::cloneQuery() must be an instance of Doctrine\ORM\Query, array given, called in D:\xampp\htdocs\deltaspiral\vendor\doctrine\orm\lib\Doctrine\ORM\Tools\Pagination\Paginator.php on line 122 and defined in D:\xampp\htdocs\deltaspiral\vendor\doctrine\orm\lib\Doctrine\ORM\Tools\Pagination\Paginator.php on line 205
Return $query instead of returning $qb->result(). $query is an instance of Doctrine\ORM\Query, whereas $qb-result() returns an array of results.
The paginator needs the query, not the result!

Doctrine 2: how do you use a subquery column (in the SELECT clause)

I'm trying to do a simple select query with a subquery in the SELECT clause and have simply not found a way to do it. I've tried with both DQL and with the QueryBuilder, neither work. The code follows, please don't say I could just use a join, this is a simplified example just to illustrate the problem, I have legitimate use cases for subqueries.
// With QueryBuilder
$query = $qb->select(array('a',
'(SELECT at.addresstypeName
FROM e:Addresstype at
WHERE at.addresstypeId = a.addresstypeId
) AS addresstypeName'))
->from('e:Address', 'a')
->where('a.addressId = :addressId')
->setParameter('addressId', 1);
// With DQL
$dql = "SELECT a,
(SELECT at.addresstypeName
FROM e:Addresstype at
WHERE at.addresstypeId = a.addresstypeId
) AS addresstypeName
FROM e:Address a
WHERE a.addressId = :addressId";
$query = $em->createQuery($dql)->setParameter(':addressId', 1);
The following relationship is defined on the Address table:
/**
* #ORM\ManyToOne(targetEntity="Addresstype")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="addresstype_id", referencedColumnName="addresstype_id")
* })
*/
protected $addresstype;
In native SQL, the query would look like this:
SELECT
a.*,
(
SELECT at.addresstype_name
FROM addresstype at
WHERE at.addresstype_id = a.addresstype_id
) AS addresstype_name
FROM address a
WHERE a.address_id = 1
Any ideas?
$query = $qb->select('a')
->addSelect('(SELECT at.addresstypeName
FROM e:Addresstype at
WHERE at.addresstypeId = a.addresstypeId) AS addresstypeName'
)
->from('e:Address', 'a')
->where('a.addressId = :addressId')
->setParameter('addressId', 1);
For me subquery with doctrine works with this query :
$qb->select('e.field')
->addSelect('(SELECT count(mv.nm)
FROM Clt\Bundle\MyBundle\Entity\MV mv
LEFT JOIN Clt\Bundle\MyBundle\Entity\M ma WITH mv.nm=ma.nm
WHERE mv.ne=e.ne and ma.nm is null
) AS nm'
)
->from($this->_entityName, 'e')
->leftJoin('e.m', 'm')
->where($qb->expr()->eq('t.id'.$typeModule, $idElementModule));
Note that in the left join you must use WITH instead of ON...
I know this is an old question, but if you want, you could have used another query builder as your subquery:
$qb->select("a")
->addSelect("(" . $qb2->select("at.addresstypeName")
->from("e:Addresstype", "at")
->where("at.addresstypeId = a.addresstypeId")
->getDQL() . ") AS addresstypeName"
)
->from('e:Address', 'a')
->where('a.addressId = :addressId')
->setParameter('addressId', 1);
In my scenario what I needed was to look into a join and find an Id and use it as boolean, found 1 otherwise 0, then applying this to orderBy. DQL expressions worked only when combined with Where clause, which wasn't my case. So, a DQL subselect saved me.
Adapted more or less to your scenario, it would look like this:
// With QueryBuilder
// In AddressRepository
// Where one address may belong to several addressTypes
public function getWithType($addressType){
$qb = $this->createQueryBuilder('a1');
$qb->addSelect('a1.someField', 'a1.otherField')
$qb->addSelect(
'(SELECT at.addressTypeName
FROM App\Entity\Address a2
JOIN a2.addressType at
WHERE at.id = '.$addressType.' AND a2.id = a1.id
) AS addressTypeName')
//The rest part of the query
}