2016-02-25 278 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大小。

我建議挖掘一些像'如何使用教條執行存儲函數調用'。