/** * Runs static repository restriction query and stores it state into snapshot entity * Doctrine does not supports insert in DQL. To increase the speed of query here uses plain sql query. * * @param Segment $segment * * @throws \LogicException * @throws \Exception */ public function run(Segment $segment) { if ($segment->getType()->getName() !== SegmentType::TYPE_STATIC) { throw new \LogicException('Only static segments could have snapshots.'); } $entityMetadata = $this->em->getClassMetadata($segment->getEntity()); if (count($entityMetadata->getIdentifierFieldNames()) > 1) { throw new \LogicException('Only entities with single identifier supports.'); } $this->em->getRepository('OroSegmentBundle:SegmentSnapshot')->removeBySegment($segment); try { $this->em->beginTransaction(); $date = new \DateTime('now', new \DateTimeZone('UTC')); $dateString = '\'' . $date->format('Y-m-d H:i:s') . '\''; if ($this->em->getConnection()->getDriver()->getName() === DatabaseDriverInterface::DRIVER_POSTGRESQL) { $dateString = sprintf('TIMESTAMP %s', $dateString); } $insertString = sprintf(', %d, %s ', $segment->getId(), $dateString); $qb = $this->dynamicSegmentQB->getQueryBuilder($segment); $this->applyOrganizationLimit($segment, $qb); $query = $qb->getQuery(); $segmentQuery = $query->getSQL(); $segmentQuery = substr_replace($segmentQuery, $insertString, stripos($segmentQuery, 'from'), 0); $fieldToSelect = 'entity_id'; if ($entityMetadata->getTypeOfField($entityMetadata->getSingleIdentifierFieldName()) === 'integer') { $fieldToSelect = 'integer_entity_id'; } $dbQuery = 'INSERT INTO oro_segment_snapshot (' . $fieldToSelect . ', segment_id, createdat) (%s)'; $dbQuery = sprintf($dbQuery, $segmentQuery); $statement = $this->em->getConnection()->prepare($dbQuery); $this->bindParameters($statement, $query->getParameters()); $statement->execute(); $this->em->commit(); } catch (\Exception $exception) { $this->em->rollback(); throw $exception; } $segment = $this->em->merge($segment); $segment->setLastRun(new \DateTime('now', new \DateTimeZone('UTC'))); $this->em->persist($segment); $this->em->flush(); }
/** * Runs static repository restriction query and stores it state into snapshot entity * * @param Segment $segment * * @throws \LogicException * @throws \Exception */ public function run(Segment $segment) { if ($segment->getType()->getName() !== SegmentType::TYPE_STATIC) { throw new \LogicException('Only static segments could have snapshots.'); } $this->em->getRepository('OroSegmentBundle:SegmentSnapshot')->removeBySegment($segment); $qb = $this->dynamicSegmentQB->build($segment); $iterator = new BufferedQueryResultIterator($qb); $writeCount = 0; try { $this->em->beginTransaction(); $this->em->clear(ClassUtils::getClass($segment)); foreach ($iterator as $data) { // only not composite identifiers are supported $id = reset($data); $writeCount++; /** @var Segment $reference */ $reference = $this->em->getReference(ClassUtils::getClass($segment), $segment->getId()); $snapshot = new SegmentSnapshot($reference); $snapshot->setEntityId($id); $this->toWrite[] = $snapshot; if (0 === $writeCount % $this->batchSize) { $this->write($this->toWrite); $this->toWrite = []; } } if (count($this->toWrite) > 0) { $this->write($this->toWrite); } $this->em->commit(); } catch (\Exception $exception) { $this->em->rollback(); throw $exception; } $segment = $this->em->merge($segment); $segment->setLastRun(new \DateTime('now', new \DateTimeZone('UTC'))); $this->em->persist($segment); $this->em->flush(); }
public function testDynamicApply() { $dynamicSegmentStub = new Segment(); $dynamicSegmentStub->setType(new SegmentType(SegmentType::TYPE_DYNAMIC)); $dynamicSegmentStub->setEntity('Oro\\Bundle\\SegmentBundle\\Tests\\Unit\\Stub\\Entity\\CmsUser'); $filterData = ['value' => $dynamicSegmentStub]; $em = $this->getEM(); $qb = $em->createQueryBuilder()->select(['t1.name'])->from('OroSegmentBundle:CmsUser', 't1'); $queryBuilder = new QueryBuilder($em); $queryBuilder->select(['ts1.id'])->from('OroSegmentBundle:CmsUser', 'ts1')->andWhere('ts1.name LIKE :param1')->setParameter('param1', self::TEST_PARAM_VALUE); $ds = new OrmFilterDatasourceAdapter($qb); $this->dynamicSegmentQueryBuilder->expects(static::once())->method('getQueryBuilder')->with($dynamicSegmentStub)->will(static::returnValue($queryBuilder)); $this->filter->init('someName', [FilterUtility::DATA_NAME_KEY => self::TEST_FIELD_NAME]); $this->filter->apply($ds, $filterData); $expectedResult = ['SELECT t1.name FROM OroSegmentBundle:CmsUser t1', 'WHERE EXISTS(SELECT ts1.id FROM OroSegmentBundle:CmsUser ts1' . ' WHERE ts1.name LIKE :param1 AND ts1.id = t1.id)']; $expectedResult = implode(' ', $expectedResult); static::assertEquals($expectedResult, $ds->getQueryBuilder()->getDQL()); $params = $ds->getQueryBuilder()->getParameters(); static::assertCount(1, $params, 'Should pass params to main query builder'); static::assertEquals(self::TEST_PARAM_VALUE, $params[0]->getValue()); }
public function testDynamicApply() { $dynamicSegmentStub = new Segment(); $dynamicSegmentStub->setType(new SegmentType(SegmentType::TYPE_DYNAMIC)); $filterData = ['value' => $dynamicSegmentStub]; $subquery = 'SELECT ts1.id FROM OroSegmentBundle:CmsUser ts1 WHERE ts1.name LIKE :param1'; $em = $this->getTestEntityManager(); $qb = new QueryBuilder($em); $qb->select(['t1.name'])->from('OroSegmentBundle:CmsUser', 't1'); $ds = new OrmFilterDatasourceAdapter($qb); $query = new Query($em); $query->setDQL($subquery); $query->setParameter('param1', self::TEST_PARAM_VALUE); $this->dynamicSegmentQueryBuilder->expects($this->once())->method('build')->with($dynamicSegmentStub)->will($this->returnValue($query)); $this->filter->init('someName', [FilterUtility::DATA_NAME_KEY => self::TEST_FIELD_NAME]); $this->filter->apply($ds, $filterData); $expectedResult = ['SELECT t1.name FROM OroSegmentBundle:CmsUser t1', 'WHERE t1.id IN(SELECT ts1.id FROM OroSegmentBundle:CmsUser ts1 WHERE ts1.name LIKE :param1)']; $expectedResult = implode(' ', $expectedResult); $this->assertEquals($expectedResult, $ds->getQueryBuilder()->getDQL()); $params = $ds->getQueryBuilder()->getParameters(); $this->assertCount(1, $params, 'Should pass params to main query builder'); $this->assertEquals(self::TEST_PARAM_VALUE, $params[0]->getValue()); }