PostgreSQL,Doctrine SQL语法错误; MySQL工作

时间:2015-08-08 16:35:09

标签: postgresql symfony doctrine-orm

将正在运行的Symfony应用程序从MySQL更改为PostgreSQL会导致

  

SQLSTATE [42601]:语法错误:7错误:语法错误在或附近   “WHERE”第1行:... Id和a4_.functionName ='expiringAlertsAction')   在哪里...

到目前为止,我无法确定发生这种情况的原因。使用MySQL,查询返回预期结果。我的理解是错误发生在WHERE之前的某个地方,但我的试验改变都没有奏效。

存储库源代码:

    public function expiringOppsSent($sent = true)
    {
        $nextMonth = date_add(new \DateTime(), new \DateInterval('P1M'));
        $expiryMonth = date_format($nextMonth, 'm');
        $expiryYear = date_format($nextMonth, 'Y');
        $expireDateCriterion = ($sent) ? "a.date IS NOT NULL" : "a.date IS NULL";
        $sqlString = 
<<<EOT
SELECT op 
FROM TruckeeVolunteerBundle:Opportunity op 
JOIN TruckeeVolunteerBundle:Organization o 
WITH op.organization = o 
JOIN TruckeeVolunteerBundle:Staff s WITH s.organization = o 
LEFT JOIN TruckeeVolunteerBundle:AdminOutbox a 
WITH op.id = a.oppId AND a.functionName = 'expiringAlertsAction'
WHERE SUBSTRING(op.expireDate, 6, 2) = '$expiryMonth' AND 
SUBSTRING(op.expireDate, 1, 4) = '$expiryYear' AND 
(op.expireDate <> a.date OR 
$expireDateCriterion) AND 
op.active = 1 AND o.active = 1 ORDER BY o.orgName
EOT;
        $sent = $this->getEntityManager()
                        ->createQuery($sqlString)->getResult();
        return $sent;
由Doctrine编写的

代码:

SELECT 
  o0_.id AS id_0, 
  o0_.oppName AS oppName_1, 
  o0_.add_date AS add_date_2, 
  o0_.lastUpdate AS lastUpdate_3, 
  o0_.minAge AS minAge_4, 
  o0_.active AS active_5, 
  o0_.group_ok AS group_ok_6, 
  o0_.expireDate AS expireDate_7, 
  o0_.description AS description_8, 
  o0_.orgId AS orgId_9 
FROM 
  opportunity o0_ 
  INNER JOIN organization o1_ ON (o0_.orgId = o1_.id) 
  INNER JOIN staff s2_ 
  INNER JOIN person p3_ ON s2_.id = p3_.id 
  AND (s2_.orgId = o0_.orgId) 
  LEFT JOIN admin_outbox a4_ ON (
    o0_.id = a4_.oppId 
    AND a4_.function = 'expiringAlertsAction'
  ) 
WHERE 
  MONTH(o0_.expireDate) = '09' 
  AND YEAR(o0_.expireDate) = '2015' 
  AND (
    o0_.expireDate <> a4_.date 
    OR a4_.date IS NOT NULL
  ) 
  AND o0_.active = 1 
  AND o1_.active = 1 
ORDER BY 
  o1_.orgName ASC

机会实体

class Opportunity
{
    public function __construct()
    {
        $this->volunteers = new ArrayCollection();
        $this->email = new ArrayCollection();
        $this->searches = new ArrayCollection();
    }

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="oppName", type="string", length=66, nullable=true)
     * @Assert\NotBlank(message = "Opportunity name is required")
     */
    private $oppName;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="add_date", type="date", nullable=true)
     */
    private $addDate;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="lastUpdate", type="datetime", nullable=true)
     */
    private $lastupdate;

    /**
     * @var integer
     *
     * @ORM\Column(name="minAge", type="integer", nullable=true)
     */
    private $minage;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=true)
     */
    private $active;

    /**
     * @var boolean
     *
     * @ORM\Column(name="group_ok", type="boolean", nullable=true)
     */
    private $groupOk;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="expireDate", type="date", nullable=true)
     * @Assert\Date()
     */
    private $expireDate;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text", nullable=true)
     * @Assert\NotBlank(message="Description is required")
     */
    private $description;

    /**
     * @var \Truckee\VolunteerBundle\Entity\Organization
     *
     * @ORM\ManyToOne(targetEntity="Truckee\VolunteerBundle\Entity\Organization", inversedBy="opportunities", cascade={"persist","remove"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="orgId", referencedColumnName="id")
     * })
     */
    private $organization;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity="Truckee\VolunteerBundle\Entity\Search", mappedBy="opportunity", cascade={"persist","remove","merge"})
     */
    protected $searches;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Opportunity
     */
    public function setOppName($name)
    {
        $this->oppName = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getOppName()
    {
        return $this->oppName;
    }

    /**
     * Set addDate
     *
     * @param \DateTime $addDate
     * @return Opportunity
     */
    public function setAddDate($addDate)
    {
        $this->addDate = $addDate;

        return $this;
    }

    /**
     * Get addDate
     *
     * @return \DateTime 
     */
    public function getAddDate()
    {
        return $this->addDate;
    }

    /**
     * Set lastupdate
     *
     * @param \DateTime $lastupdate
     * @return Opportunity
     */
    public function setLastupdate($lastupdate)
    {
        $this->lastupdate = $lastupdate;

        return $this;
    }

    /**
     * Get lastupdate
     *
     * @return \DateTime 
     */
    public function getLastupdate()
    {
        return $this->lastupdate;
    }

    /**
     * Set minage
     *
     * @param integer $minage
     * @return Opportunity
     */
    public function setMinage($minage)
    {
        $this->minage = $minage;

        return $this;
    }

    /**
     * Get minage
     *
     * @return integer 
     */
    public function getMinage()
    {
        return $this->minage;
    }

    /**
     * Set active
     *
     * @param boolean $active
     * @return Opportunity
     */
    public function setActive($active)
    {
        $this->active = $active;

        return $this;
    }

    /**
     * Get active
     *
     * @return boolean 
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * Set group
     *
     * @param boolean $groupOk
     * @return Opportunity
     */
    public function setGroupOk($groupOk)
    {
        $this->groupOk = $groupOk;

        return $this;
    }

    /**
     * Get group
     *
     * @return boolean 
     */
    public function getGroupOk()
    {
        return $this->groupOk;
    }

    /**
     * Set expiredate
     *
     * @param \DateTime $expiredate
     * @return Opportunity
     */
    public function setExpireDate($expiredate)
    {
        $this->expireDate = $expiredate;

        return $this;
    }

    /**
     * Get expiredate
     *
     * @return \DateTime 
     */
    public function getExpireDate()
    {
        return $this->expireDate;
    }

    /**
     * Set description
     *
     * @param string $description
     * @return Opportunity
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set organization
     *
     * @param \Truckee\VolunteerBundle\Entity\Organization $organization
     * @return Opportunity
     */
    public function setOrganization(\Truckee\VolunteerBundle\Entity\Organization $organization = null)
    {
        $this->organization = $organization;

        return $this;
    }

    /**
     * Get organization
     *
     * @return \Truckee\VolunteerBundle\Entity\Organization 
     */
    public function getOrganization()
    {
        return $this->organization;
    }

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Skill", inversedBy="opportunities", cascade={"persist"})
     * @ORM\JoinTable(name="opp_skill",
     *      joinColumns={@ORM\JoinColumn(name="oppId", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="skillId", referencedColumnName="id")}
     *      ))
     * @Assert\NotNull(message="Please select at least one")
     */
    protected $skills;

    /**
     * Add skills
     *
     * @param \Truckee\VolunteerBundle\Entity\Skill $skills
     * @return Opportunity
     */
    public function addSkill(\Truckee\VolunteerBundle\Entity\Skill $skill)
    {
        $this->skills[] = $skill;

        return $this;
    }

    /**
     * Remove skills
     *
     * @param \Truckee\VolunteerBundle\Entity\Skill $skills
     */
    public function removeSkill(\Truckee\VolunteerBundle\Entity\Skill $skill)
    {
        $this->skills->removeElement($skill);
    }

    /**
     * Get skills
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getSkills()
    {
        return $this->skills;

    }

    /**
     * Get search
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getSearches()
    {
        return $this->searches;
    }
}

组织实体

class Organization
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="orgName", type="string", length=65, nullable=true)
     * @Assert\NotBlank(message="Organization name is required")
     */
    protected $orgName;

    /**
     * @var string
     *
     * @ORM\Column(name="address", type="string", length=50, nullable=true)
     */
    protected $address;

    /**
     * @var string
     *
     * @ORM\Column(name="city", type="string", length=50, nullable=true)
     */
    protected $city;

    /**
     * @var string
     *
     * @ORM\Column(name="state", type="string", length=50, nullable=true)
     */
    protected $state;

    /**
     * @var string
     *
     * @ORM\Column(name="zip", type="string", length=10, nullable=true)
     */
    protected $zip;

    /**
     * @var string
     *
     * @ORM\Column(name="phone", type="string", length=50, nullable=true)
     * @V2Assert\PhoneNumber
     */
    protected $phone;

    /**
     * @var string
     *
     * @ORM\Column(name="website", type="string", length=50, nullable=true)
     */
    protected $website;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=true)
     */
    protected $active;

    /**
     * @var boolean
     *
     * @ORM\Column(name="temp", type="boolean", nullable=false)
     */
    protected $temp;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="add_date", type="datetime", nullable=true)
     */
    protected $addDate;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity="Truckee\VolunteerBundle\Entity\Opportunity", mappedBy="organization", cascade={"persist","remove"})
     */
    protected $opportunities;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity="Truckee\VolunteerBundle\Entity\Search", mappedBy="organization", cascade={"persist","remove","merge"})
     */
    protected $searches;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity="Truckee\VolunteerBundle\Entity\Staff", mappedBy="organization", cascade={"persist","remove","merge"})
     */
    protected $staff;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Focus", inversedBy="organizations", cascade={"persist"})
     * @ORM\JoinTable(name="org_focus",
     *      joinColumns={@ORM\JoinColumn(name="orgId", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="focusId", referencedColumnName="id")}
     *      ))
     * @Assert\NotNull(message="Please select at least one")
     */
    protected $focuses;

    /**
     *  @ORM\Column(name="background", type="boolean", nullable=true)
     */
    protected $background;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->opportunities = new ArrayCollection();
        $this->staff = new ArrayCollection();
        $this->searches = new ArrayCollection();
        $this->focuses = new ArrayCollection();
        $this->active = true;
    }


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set organization
     *
     * @param string $organization
     * @return Organization
     */
    public function setOrgName($name)
    {
        $this->orgName = $name;

        return $this;
    }

    /**
     * Get organization
     *
     * @return string 
     */
    public function getOrgName()
    {
        return $this->orgName;
    }

    /**
     * Set address
     *
     * @param string $address
     * @return Organization
     */
    public function setAddress($address)
    {
        $this->address = $address;

        return $this;
    }

    /**
     * Get address
     *
     * @return string 
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * Set city
     *
     * @param string $city
     * @return Organization
     */
    public function setCity($city)
    {
        $this->city = $city;

        return $this;
    }

    /**
     * Get city
     *
     * @return string 
     */
    public function getCity()
    {
        return $this->city;
    }

    /**
     * Set state
     *
     * @param string $state
     * @return Organization
     */
    public function setState($state)
    {
        $this->state = $state;

        return $this;
    }

    /**
     * Get state
     *
     * @return string 
     */
    public function getState()
    {
        return $this->state;
    }

    /**
     * Set zip
     *
     * @param string $zip
     * @return Organization
     */
    public function setZip($zip)
    {
        $this->zip = $zip;

        return $this;
    }

    /**
     * Get zip
     *
     * @return string 
     */
    public function getZip()
    {
        return $this->zip;
    }

    /**
     * Set phone
     *
     * @param string $phone
     * @return Organization
     */
    public function setPhone($phone)
    {
        $this->phone = $phone;

        return $this;
    }

    /**
     * Get phone
     *
     * @return string 
     */
    public function getPhone()
    {
        return $this->phone;
    }

    /**
     * Set website
     *
     * @param string $website
     * @return Organization
     */
    public function setWebsite($website)
    {
        $this->website = $website;

        return $this;
    }

    /**
     * Get website
     *
     * @return string 
     */
    public function getWebsite()
    {
        return $this->website;
    }

    /**
     * Set active
     *
     * @param boolean $active
     * @return Organization
     */
    public function setActive($active)
    {
        $this->active = $active;

        return $this;
    }

    /**
     * Get active
     *
     * @return boolean 
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * Set temp
     *
     * @param boolean $temp
     * @return Organization
     */
    public function setTemp($temp)
    {
        $this->temp = $temp;

    }

    /**
     * Get temp
     *
     * @return boolean 
     */
    public function getTemp()
    {
        return $this->temp;
    }

    /**
     * Set addDate
     *
     * @param \DateTime $addDate
     * @return Organization
     */
    public function setAddDate($addDate)
    {
        $this->addDate = $addDate;

        return $this;
    }

    /**
     * Get addDate
     *
     * @return \DateTime 
     */
    public function getAddDate()
    {
        return $this->addDate;
    }

    /**
     * Add opportunities
     *
     * @param \Truckee\VolunteerBundle\Entity\Opportunity $opportunities
     * @return Organization
     */
    public function addOpportunity(\Truckee\VolunteerBundle\Entity\Opportunity $opportunity)
    {
        $this->opportunities[] = $opportunity;

        return $this;
    }

    /**
     * Remove opportunities
     *
     * @param \Truckee\VolunteerBundle\Entity\Opportunity $opportunities
     */
    public function removeOpportunity(\Truckee\VolunteerBundle\Entity\Opportunity $opportunity)
    {
        $this->opportunities->removeElement($opportunity);
    }

    /**
     * Get opportunities
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getOpportunities()
    {
        return $this->opportunities;
    }

//    /**
//     * Add staff
//     *
//     * @param \Truckee\VolunteerBundle\Entity\Staff $staff
//     * @return Organization
//     */
//    public function addStaff(\Truckee\VolunteerBundle\Entity\Staff $staff)
//    {
//        echo "We found it!";die;
//        $this->staff[] = $staff;
//    
//        return $this;
//    }

//    /**
//     * Remove staff
//     *
//     * @param \Truckee\VolunteerBundle\Entity\Staff $staff
//     */
//    public function removeStaff(\Truckee\VolunteerBundle\Entity\Staff $staff)
//    {
//        $this->staff->removeElement($staff);
//    }

    /**
     * Get staff
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getStaff()
    {
        return $this->staff;
    }

    /**
     * Add search
     *
     * @param \Truckee\VolunteerBundle\Entity\Search $search
     * @return Organization
     */
    public function addSearch(\Truckee\VolunteerBundle\Entity\Search $search)
    {
        $this->searches[] = $search;

        return $this;
    }

    /**
     * Remove search
     *
     * @param \Truckee\VolunteerBundle\Entity\Search $search
     */
    public function removeSearch(\Truckee\VolunteerBundle\Entity\Search $search)
    {
        $this->searches->removeElement($search);
    }

    /**
     * Get search
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getSearch()
    {
        return $this->search;
    }

    /**
     * Add focuses
     *
     * @param \Truckee\VolunteerBundle\Entity\Focus $focuses
     * @return Organization
     */
    public function addFocus(\Truckee\VolunteerBundle\Entity\Focus $focus)
    {
        $this->focuses[] = $focus;

        return $this;
    }

    /**
     * Remove focuses
     *
     * @param \Truckee\VolunteerBundle\Entity\Focus $focuses
     */
    public function removeFocus(\Truckee\VolunteerBundle\Entity\Focus $focus)
    {
        $this->focuses->removeElement($focus);
    }

    /**
     * Get focuses
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getFocuses()
    {
        return $this->focuses;
    }

    /**
     * @var boolean
     *
     * @ORM\Column(name="email", type="string", nullable=true)
     */
    protected $email;

    /**
     * Set email
     *
     * @param boolean $email
     * @return email
     */
    public function setEmail($email) {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return boolean 
     */
    public function getEmail() {
        return $this->email;
    }

    /**
     * @var boolean
     *
     * @ORM\Column(name="areacode", type="integer", nullable=true)
     * @V2Assert\AreaCode
     */
    protected $areacode;

    /**
     * Set areacode
     *
     * @param $areacode
     * @return areacode
     */
    public function setAreacode($areacode) {
        $this->areacode = $areacode;

        return $this;
    }

    /**
     * Get areacode
     *
     * @return boolean 
     */
    public function getAreacode() {
        return $this->areacode;
    }

    /**
     * Set background
     *
     * @param $background
     * @return background
     */
    public function setBackground($background) {
        $this->background = $background;

        return $this;
    }

    /**
     * Get background
     *
     * @return boolean 
     */
    public function getBackground() {
        return $this->background;
    }
}

员工实体

class Staff extends Person
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var \Truckee\VolunteerBundle\Entity\Organization
     *
     * @ORM\ManyToOne(targetEntity="Truckee\VolunteerBundle\Entity\Organization", inversedBy="staff", cascade={"persist","remove"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="orgId", referencedColumnName="id")
     * })
     */
    protected $organization;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set organization
     *
     * @param \Truckee\VolunteerBundle\Entity\Organization $organization
     * @return Staff
     */
    public function setOrganization(\Truckee\VolunteerBundle\Entity\Organization $organization = null)
    {
        $this->organization = $organization;

        return $this;
    }

    /**
     * Get organization
     *
     * @return \Truckee\VolunteerBundle\Entity\Organization 
     */
    public function getOrganization()
    {
        return $this->organization;
    }

}

2 个答案:

答案 0 :(得分:3)

AFAIK错误是因为您的联接缺少标准。这是由Doctrine编写的代码的摘录:

FROM opportunity o0_ 
    INNER JOIN organization o1_ 
        ON (o0_.orgId = o1_.id) 
    INNER JOIN staff s2_ <-- MISSING CRITERIA HERE 
    INNER JOIN person p3_ 
        ON s2_.id = p3_.id AND (s2_.orgId = o1_.id) 
    LEFT JOIN admin_outbox a4_ 
        ON (o0_.id = a4_.oppId AND a4_.functionName = 'expiringAlertsAction') 

您应该仔细检查您的实体定义。

答案 1 :(得分:0)

特别感谢@FrancescoAbeni让我走上正轨。最初的item_vec.last().unwrap().clone() 反映了其他地方被替换的逻辑。我重写了代码来创建以下内容,允许Doctrine保留连接条件。

值得注意的是,对于这个应用程序,我还需要添加orocrm/doctrine-extensions才能拥有MySQL&amp; PostgreSQL expiringOppsSent()month()函数。另外,我必须在pgAdmin查询中year()

CREATE EXTENSION fuzzystrmatch