2016-02-25 266 views
2

我试图用自定义映射类型实现PostGis中的栅格功能。将光栅添加到数据库,Doctrine自定义映射类型带来数据库错误

我正在创建一个类型为栅格的列表。 要插入光栅数据,我要用st_makeemptyraster插入一个新的空Raster,用st_addband添加一个新的波段,并用st_setvalues设置值。

所以,这可能在普通的SQL做那样:

CREATE TABLE IF NOT EXISTS rasters (id serial, rast raster); 
INSERT INTO rasters(id,rast) 
VALUES(
    3, 
    st_setvalues(
     st_addband(  
      ST_MakeEmptyRaster(2, 2, 0.0005, 0.0005, 1, 1, 0, 0, 4326), 
      1, 
      '32BF', 
      1, 
      0 
     ), 
     1, 
     1, 
     1, 
     ARRAY[[9, 9], [9, 9]]::double precision[][] 
    ) 
); 

现在我试图在学说添加自定义映射类型的光栅。

我增加了一个实体光栅:

<?php 
/** 
* More Documentation here: 
* 
* http://postgis.net/docs/manual-dev/RT_ST_MakeEmptyRaster.html 
* 
* raster ST_MakeEmptyRaster(raster rast); 
* raster ST_MakeEmptyRaster(integer width, integer height, float8 upperleftx, float8 upperlefty, float8 scalex, float8 scaley, float8 skewx, float8 skewy, integer srid=unknown); 
* raster ST_MakeEmptyRaster(integer width, integer height, float8 upperleftx, float8 upperlefty, float8 pixelsize); 
* 
* 
* http://postgis.net/docs/manual-2.2/RT_ST_AddBand.html 
* 
* 
*/ 
namespace AppBundle\Entity; 
use Doctrine\ORM\Mapping as ORM; 
use JMS\Serializer\Annotation as JMS; 
use AppBundle\Model\Raster as RasterModel; 
/** 
* Raster 
* 
* @ORM\Entity(repositoryClass="AppBundle\Entity\RasterRepository") 
* @ORM\Table(name="rasters") 
*/ 
class Raster 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 
    /** 
    * @var RasterModel $raster 
    * 
    * @ORM\Column(name="rast", type="raster", nullable=true) 
    */ 
    private $raster; 
    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 
    /** 
    * Set raster 
    * 
    * @param RasterModel $raster 
    * 
    * @return Raster 
    */ 
    public function setRaster(RasterModel $raster) 
    { 
     $this->raster = $raster; 
     return $this; 
    } 
    /** 
    * Get raster 
    * 
    * @return Raster 
    */ 
    public function getRaster() 
    { 
     return $this->raster; 
    } 
} 

模型的PHP的对象:

<?php 
namespace AppBundle\Model; 
use Doctrine\Common\Collections\ArrayCollection; 
/** 
* Raster 
*/ 
class Raster 
{ 
    /** 
    * @var Raster $raster 
    */ 
    private $raster; 
    /** 
    * @var integer 
    */ 
    private $width; 
    /** 
    * @var integer 
    */ 
    private $height; 
    /** 
    * @var float 
    */ 
    private $upperLeftX; 
    /** 
    * @var float 
    */ 
    private $upperLeftY; 
    /** 
    * @var float 
    */ 
    private $scaleX; 
    /** 
    * @var float 
    */ 
    private $scaleY; 
    /** 
    * @var float 
    */ 
    private $skewX; 
    /** 
    * @var float 
    */ 
    private $skewY; 
    /** 
    * @var float 
    */ 
    private $pixelSize; 
    /** 
    * @var integer 
    */ 
    private $srid; 
    /** 
    * @var ArrayCollection RasterBand 
    */ 
    private $bands; 
    /** 
    * Raster constructor. 
    */ 
    public function __construct() 
    { 
     $this->bands = new ArrayCollection(); 
    } 
    /** 
    * @return Raster 
    */ 
    public function getRaster() 
    { 
     return $this->raster; 
    } 
    /** 
    * @param Raster $raster 
    * @return Raster 
    */ 
    public function setRaster($raster) 
    { 
     $this->raster = $raster; 
     return $this; 
    } 
    /** 
    * @return int 
    */ 
    public function getWidth() 
    { 
     return $this->width; 
    } 
    /** 
    * @param int $width 
    * @return Raster 
    */ 
    public function setWidth($width) 
    { 
     $this->width = $width; 
     return $this; 
    } 
    /** 
    * @return int 
    */ 
    public function getHeight() 
    { 
     return $this->height; 
    } 
    /** 
    * @param int $height 
    * @return Raster 
    */ 
    public function setHeight($height) 
    { 
     $this->height = $height; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getUpperLeftX() 
    { 
     return $this->upperLeftX; 
    } 
    /** 
    * @param float $upperLeftX 
    * @return Raster 
    */ 
    public function setUpperLeftX($upperLeftX) 
    { 
     $this->upperLeftX = $upperLeftX; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getUpperLeftY() 
    { 
     return $this->upperLeftY; 
    } 
    /** 
    * @param float $upperLeftY 
    * @return Raster 
    */ 
    public function setUpperLeftY($upperLeftY) 
    { 
     $this->upperLeftY = $upperLeftY; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getScaleX() 
    { 
     return $this->scaleX; 
    } 
    /** 
    * @param float $scaleX 
    * @return Raster 
    */ 
    public function setScaleX($scaleX) 
    { 
     $this->scaleX = $scaleX; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getScaleY() 
    { 
     return $this->scaleY; 
    } 
    /** 
    * @param float $scaleY 
    * @return Raster 
    */ 
    public function setScaleY($scaleY) 
    { 
     $this->scaleY = $scaleY; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getSkewX() 
    { 
     return $this->skewX; 
    } 
    /** 
    * @param float $skewX 
    * @return Raster 
    */ 
    public function setSkewX($skewX) 
    { 
     $this->skewX = $skewX; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getSkewY() 
    { 
     return $this->skewY; 
    } 
    /** 
    * @param float $skewY 
    * @return Raster 
    */ 
    public function setSkewY($skewY) 
    { 
     $this->skewY = $skewY; 
     return $this; 
    } 
    /** 
    * @return float 
    */ 
    public function getPixelSize() 
    { 
     return $this->pixelSize; 
    } 
    /** 
    * @param float $pixelSize 
    * @return Raster 
    */ 
    public function setPixelSize($pixelSize) 
    { 
     $this->pixelSize = $pixelSize; 
     return $this; 
    } 
    /** 
    * @return int 
    */ 
    public function getSrid() 
    { 
     return $this->srid; 
    } 
    /** 
    * @param int $srid 
    * @return Raster 
    */ 
    public function setSrid($srid) 
    { 
     $this->srid = $srid; 
     return $this; 
    } 
    /** 
    * @return ArrayCollection 
    */ 
    public function getBands() 
    { 
     return $this->bands; 
    } 
    /** 
    * @param ArrayCollection $bands 
    * @return Raster 
    */ 
    public function setBands($bands) 
    { 
     $this->bands = $bands; 
     return $this; 
    } 
    /** 
    * @param RasterBand $band 
    * @return array|ArrayCollection 
    */ 
    public function addBand(RasterBand $band) 
    { 
     $this->bands[] = $band; 
     return $this->bands; 
    } 
    /** 
    * @param RasterBand $band 
    * @return $this 
    */ 
    public function removeBand(RasterBand $band) 
    { 
     $this->bands->removeElement($band); 
     return $this; 
    } 
} 

而且自定义映射类型:

<?php 
namespace AppBundle\Type; 
use Doctrine\DBAL\Platforms\AbstractPlatform; 
use Doctrine\DBAL\Types\Type; 
class RasterType extends Type 
{ 
    const RASTER = 'raster'; 
    public function getName() 
    { 
     return self::RASTER; 
    } 
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) 
    { 
     return 'raster'; 
    } 
    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     /** 
     * ToDo: Finish implementing it 
     */ 
     return new \AppBundle\Model\Raster(); 
    } 
    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
     return sprintf('%d, %d, %f, %f, %f, %f, %f, %f, %d', 10, 10, 0.1, 0.1, 0.1, 0.1, 0, 0, 4269); 
    } 
    public function canRequireSQLConversion() 
    { 
     return true; 
    } 
    public function convertToPHPValueSQL($sqlExpr, $platform) 
    { 
     /** 
     * ToDo: Finish implementing it 
     */ 
     return sprintf('AsText(%s)', $sqlExpr); 
    } 
    public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) 
    { 
     return sprintf('st_makeemptyraster(%s)', $sqlExpr); 
    } 
} 

在我的第一个意向我试图向数据库添加一个空的光栅。 除了插入或更新光栅,出现以下错误:

2) AppBundle\Tests\Entity\RasterTest::testCreateEmptyRasterAndAddBand 
Doctrine\DBAL\Exception\DriverException: An exception occurred while executing 'INSERT INTO rasters (id, rast) VALUES (?, ?)' with params [2, "st_makeemptyraster(10, 10, 0.100000, 0.100000, 0.100000, 0.100000, 0.000000, 0.000000, 4269)"]: 

SQLSTATE[XX000]: Internal error: 7 ERROR: rt_raster_from_wkb: wkb size (46) < min size (61) 

相同的数据作为一个普通的SQL查询工作正常:

INSERT INTO rasters (id, rast) VALUES (14, st_makeemptyraster(10, 10, 0.100000, 0.100000, 0.100000, 0.100000, 0.000000, 0.000000, 4269)); 
INSERT 0 1 

有谁有一个想法如何得到这个固定? 谢谢

回答

1

(我不能小于50。于是我就可以写一个用的answere我的名声发表评论。一些MOD可能会改变它的评论呢?)

我不familar与教义,但首先我有一个常见问题的假设。

您能否确保在构建查询之前将值传递给任何查询不受字符串转换的影响?使用参数执行查询可能会将它们转换为带有转义字符的字符串值,以避免安全问题。

一个例子:

$yourDoctrineAdapter->executeInsert(42, "storedProcedureCall('foo')");

可能导致类似

INSERT INTO foo (bar, baz) VALUES ('42', 'storedProcedureCall(\'foo\')');

我的第二个假设是关于内部错误消息,而不是关于错误的类型。

rt_raster_from_wkb: wkb size (46) < min size (61)

我不知道st_makeemptyraster()的返回值是什么,但您从Doctrine的调用仍然可能会导致字符串参数而不是存储的函数调用。在列rast中插入的值是装箱类型,然后字符串“调用”的WKB大小小于存储函数返回值st_makeemptyraster()的WKB大小。

我建议挖掘一些像'如何使用教条执行存储函数调用'。