From 40839add4346ca155a5b5f9f0d5f03ce990b07bd Mon Sep 17 00:00:00 2001 From: sparkyx Date: Mon, 8 Sep 2025 17:19:09 +0200 Subject: [PATCH] DatabaseCore : add the function lo_write , lo_replace and lo_read to create large objects from string --- include/lib/database_core.class.php | 76 +++++++++++++++++- unit-test/include/lib/databaseCoreTest.php | 90 +++++++++++++++++++++- 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/include/lib/database_core.class.php b/include/lib/database_core.class.php index bea8cf4eb..901f3b644 100644 --- a/include/lib/database_core.class.php +++ b/include/lib/database_core.class.php @@ -759,6 +759,80 @@ class DatabaseCore } return false; } + /** + * @brief large_object writee: create a Large object if oid is not given + * with data content in a binaray + * @param $binary_data (raw data) binary + * @returns $oid of the LO, false if it fails + */ + function lo_write($binary_data) + { + //var $a : 0 where in a transaction, 1 we are not in a transaction + $a=0; + if ( $this->status() !== PGSQL_TRANSACTION_INTRANS ) { + $a=1; + $this->start(); + } + + $oid= pg_lo_create($this->db); + + if ( ($handle=pg_lo_open($this->db,$oid,"w")) == false ) { return false ;} + pg_lo_write($handle, $binary_data); + pg_lo_close($handle); + if ( $a==1) { $this->commit(); } + return $oid; + + } + /** + * @brief read a Large object with data content in a binary + * @param $oid (int8) oid of the large object + * @returns $binary_data (raw data) binary + */ + function lo_read($oid) + { + //var $a : 0 where in a transaction, 1 we are not in a transaction + $a=0; + if ( $this->status() !== PGSQL_TRANSACTION_INTRANS ) { + $a=1; + $this->start(); + } + + $handle=pg_lo_open($this->db,$oid,"r"); + if ( $handle == false ) { return false ;} + // set position end of the LO + pg_lo_seek($handle, 0, PGSQL_SEEK_END); + // get the size + $size= pg_lo_tell($handle); + // set position to start + pg_lo_seek($handle, 0, PGSQL_SEEK_SET); + // read the comùplete LOB + $binary_data = pg_lo_read($handle,$size ); + pg_lo_close($handle); + if ( $a==1) { $this->commit(); } + return $binary_data; + } + /** + * @brief replace a Large object with data content in a binary + * @param $oid (int8) oid of the large object + * @param $binary_data (raw data) binary + * @returns $oid of the LO, false if it fails + */ + function lo_replace($binary_data, $oid) { + $a = 0; + if ($this->status() !== PGSQL_TRANSACTION_INTRANS) { + $a = 1; + $this->start(); + } + $handle = pg_lo_open($this->db, $oid, "w"); + if ( $handle == false ) { return false ;} + pg_lo_truncate($handle, 0); + pg_lo_write($handle, $binary_data); + pg_lo_close($handle); + if ($a == 1) { + $this->commit(); + } + return $oid; + } /** * \brief wrapper for the function pg_num_rows @@ -823,7 +897,7 @@ class DatabaseCore /** * \brief wrapper for the function pg_lo_unlink * \param $p_oid is the of oid - * \return return the result of the operation + * \return return the result of the operation : false == fails */ function lo_unlink($p_oid) diff --git a/unit-test/include/lib/databaseCoreTest.php b/unit-test/include/lib/databaseCoreTest.php index 5280d19f9..3268a691c 100644 --- a/unit-test/include/lib/databaseCoreTest.php +++ b/unit-test/include/lib/databaseCoreTest.php @@ -123,6 +123,94 @@ class DatabaseCoreTest extends TestCase $this->assertStringContainsString("Documentation", $p_content,"$filename invalid content"); } - + /** + * @brief read / write large object + * @testDox read and write - unlink large object + * + */ + public function testWrite_Read_large_object() + { + $md5="965765540c1531370e5856ff81696107"; + $file=__DIR__."/file/developpement-widget.pdf"; + // step 1 : we create the large object + $binary_data= file_get_contents($file); + $this->assertEquals($md5,md5($binary_data)," error when reading $file "); + $oid = $this->object->lo_write($binary_data); + $this->assertTrue ($oid != false , "writing in DB fails"); + // step 2 = read object + $retrieve = $this->object->lo_read($oid); + $this->assertEquals($md5,md5($retrieve)," error when retrieving file from db"); + + $target=$file."retrieve.pdf"; + if ( file_exists($target) ) { unlink($target);} + + file_put_contents($target, $retrieve); + $this->assertTrue(file_exists($target)); + + if ( file_exists($target) ) { unlink($target);} + $this->assertTrue( $this->object->lo_unlink($oid)," cannot unlink it"); + + + } + /** + * @brief import export large objects + * @testDox import and export large object + * + */ + public function testImport_export_large_object() + { + $md5="965765540c1531370e5856ff81696107"; + $file=__DIR__."/file/developpement-widget.pdf"; + $this->object->start(); + $oid = $this->object->lo_import($file); + $this->object->commit(); + $this->assertTrue( $oid != false , "import of the file fails"); + $target=$file."-tmp"; + if ( file_exists($target) ) { unlink($target);} + $this->object->start(); + $this->object->lo_export($oid , $file."-tmp"); + $this->object->commit(); + $this->assertTrue(file_exists($file."-tmp")," file not exported"); + if ( file_exists($target) ) { unlink($target);} + $this->assertTrue( $this->object->lo_unlink($oid)," cannot unlink it"); + } + + public function testReplace() { + $string=<<object->start(); + $oid=$this->object->lo_write($string); + $this->object->commit(); + + $this->object->start(); + $stringDB = $this->object->lo_read($oid); + $this->object->commit(); + + $this->assertEquals(md5($string),md5($stringDB)," error string from DB corrupted"); + + $string = "second"; + $this->object->start(); + $this->object->lo_replace($string,$oid); + $this->object->commit(); + + $this->object->start(); + $stringDB = $this->object->lo_read($oid); + var_dump($stringDB); + $this->object->commit(); + + $this->assertEquals(md5($string),md5($stringDB)," after lo_replace(), string from DB corrupted"); + } + } \ No newline at end of file