/**
  * 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());
 }