<?php
namespace RedUNIT\Postgres;
use RedUNIT\Postgres as Postgres;
use RedBeanPHP\Facade as R;
use RedBeanPHP\RedException\SQL as SQLException;
/**
* Partial Beans
*
* This class has been designed to test 'partial bean mode'.
* In 'partial bean mode' only changed properties are being saved,
* not entire beans. This can be useful when you have unsupported
* column types in your table, this is what we test here. In this
* example we have a table that contains a boolean column, this column
* does not accept the value '' as FALSE as shown in the test, it will
* trigger an Invalid Text Representation Exception. Thanks to 'partial beans'
* we can work around this, by selectively updating the non-boolean properties
* of the bean. If we choose to update the boolean property this is no longer
* a problem because we set the value ourselves it will be compatible. However
* automatically loaded and stored properties by RedBeanPHP are subject to
* type inference, and the boolean FALSE value will become '', which is the
* crux of the issue here.
*
* @file RedUNIT/Postgres/Partial.php
* @desc Tests whether 'partial beans' can be used to support non-RB columns
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Partial extends Postgres
{
/**
* Excerpt from issue #547:
* "When I load a bean (via $bean = R::findOne(...);), only change a few
* values and then call R::store($bean);, it can happen that I get an error like:
* Error in SQL query:
* SQLSTATE[22P02]: Invalid text representation:
* 7 ERROR: invalid input syntax for type boolean: ""
* This happens, when there is a boolean field set to FALSE and
* I don't update that field. When R::store() is called,
* the value isn't translated to '0' but instead stays FALSE. PostgreSQL doesn't like this.
* When setting a boolean value, it gets converted correctly,
* but any unchanged values stay of type boolean.
*
* @return void
*/
public function testIssue547BoolCol()
{
R::nuke();
R::usePartialBeans( FALSE );
$bean = R::dispense( 'bean' );
$bean->property1 = 'value1';
$id = R::store( $bean );
R::freeze( TRUE );
R::exec('ALTER TABLE bean ADD COLUMN "property2" BOOLEAN DEFAULT FALSE;');
$bean = R::load( 'bean', $id );
$bean->property1 = 'value1b';
/* we cant save the bean, because there is an unsupported field type in the table */
/* this was the bug... (or missing feature?) */
try {
R::store( $bean );
//No fail? Then this instance of Postgres is more lenient (newer version) - No further testing for now
return;
} catch( SQLException $e ) {
asrt( strpos( $e->getMessage(), 'Invalid text representation' ) > 1, TRUE );
asrt( $e->getSQLState(), '22P02' );
}
/* solved by adding feature partial beans, now only the changed properties get saved */
R::usePartialBeans( TRUE );
$id = R::store( $bean );
/* no exception... */
pass();
/* also test behavior of boolean column in general */
$bean = R::load( 'bean', $id );
asrt( $bean->property1, 'value1b' );
asrt( $bean->property2, FALSE );
$bean->property2 = TRUE;
$id = R::store( $bean );
$bean = R::load( 'bean', $id );
asrt( $bean->property1, 'value1b' );
asrt( $bean->property2, TRUE );
$bean->property2 = FALSE;
$id = R::store( $bean );
$bean = R::load( 'bean', $id );
asrt( $bean->property1, 'value1b' );
asrt( $bean->property2, FALSE );
$bean->property2 = 't';
$id = R::store( $bean );
$bean = R::load( 'bean', $id );
asrt( $bean->property1, 'value1b' );
asrt( $bean->property2, TRUE );
$bean->property2 = 'f';
$id = R::store( $bean );
$bean = R::load( 'bean', $id );
asrt( $bean->property1, 'value1b' );
asrt( $bean->property2, FALSE );
/* but invalid text should not work */
$bean->property2 = 'tx'; //instead of just 't'
try {
$id = R::store( $bean );
fail();
} catch( SQLException $e ) {
asrt( strpos( $e->getMessage(), 'Invalid text representation' ) > 1, TRUE );
asrt( $e->getSQLState(), '22P02' );
}
R::usePartialBeans( FALSE );
}
}
|