Exemplo n.º 1
0
 /**
  * MySQL specific tests.
  *
  * @return void
  */
 public function testMySQL()
 {
     if ($this->currentlyActiveDriverID !== 'mysql') {
         return;
     }
     testpack('Throw exception in case of issue with assoc constraint');
     $bunny = R::dispense('bunny');
     $carrot = R::dispense('carrot');
     $faultyWriter = new \FaultyWriter(R::getToolBox()->getDatabaseAdapter());
     $faultyOODB = new OODB($faultyWriter);
     $faultyOODB->setBeanHelper(R::getRedBean()->getBeanHelper());
     $faultyToolbox = new ToolBox($faultyOODB, R::getToolBox()->getDatabaseAdapter(), $faultyWriter);
     $faultyAssociationManager = new AssociationManager($faultyToolbox);
     $faultyWriter->setSQLState('23000');
     $faultyAssociationManager->associate($bunny, $carrot);
     pass();
     $faultyWriter->setSQLState('42S22');
     R::nuke();
     try {
         $faultyAssociationManager->associate($bunny, $carrot);
         fail();
     } catch (SQL $exception) {
         pass();
     }
 }
Exemplo n.º 2
0
 /**
  * Loads multiple types of beans with the same ID.
  * This might look like a strange method, however it can be useful
  * for loading a one-to-one relation.
  *
  * @param OODB         $oodb  OODB object
  * @param string|array $types the set of types to load at once
  * @param mixed        $id    the common ID
  *
  * @return OODBBean
  */
 public static function load(OODB $oodb, $types, $id)
 {
     if (is_string($types)) {
         $types = explode(',', $types);
     }
     if (!is_array($types)) {
         return array();
     }
     foreach ($types as $k => $typeItem) {
         $types[$k] = $oodb->load($typeItem, $id);
     }
     return $types;
 }
Exemplo n.º 3
0
 /**
  * @see Finder::find
  *      Convience method. Tries to find beans of a certain type,
  *      if no beans are found, it dispenses a bean of that type.
  *
  * @param  string $type     the type of bean you are looking for
  * @param  string $sql      SQL query to find the desired bean, starting right after WHERE clause
  * @param  array  $bindings values array of values to be bound to parameters in query
  *
  * @return array
  */
 public function findOrDispense($type, $sql = NULL, $bindings = array())
 {
     $foundBeans = $this->find($type, $sql, $bindings);
     if (empty($foundBeans)) {
         return array($this->redbean->dispense($type));
     } else {
         return $foundBeans;
     }
 }
Exemplo n.º 4
0
 /**
  * Returns all the beans associated with $bean.
  * This method will return an array containing all the beans that have
  * been associated once with the associate() function and are still
  * associated with the bean specified. The type parameter indicates the
  * type of beans you are looking for. You can also pass some extra SQL and
  * values for that SQL to filter your results after fetching the
  * related beans.
  *
  * Don't try to make use of subqueries, a subquery using IN() seems to
  * be slower than two queries!
  *
  * Since 3.2, you can now also pass an array of beans instead just one
  * bean as the first parameter.
  *
  * @param OODBBean|array $bean the bean you have
  * @param string         $type      the type of beans you want
  * @param string         $sql       SQL snippet for extra filtering
  * @param array          $bindings  values to be inserted in SQL slots
  *
  * @return array
  */
 public function related($bean, $type, $sql = '', $bindings = array())
 {
     $sql = $this->writer->glueSQLCondition($sql);
     $rows = $this->relatedRows($bean, $type, $sql, $bindings);
     $links = array();
     foreach ($rows as $key => $row) {
         if (!isset($links[$row['id']])) {
             $links[$row['id']] = array();
         }
         $links[$row['id']][] = $row['linked_by'];
         unset($rows[$key]['linked_by']);
     }
     $beans = $this->oodb->convertToBeans($type, $rows);
     foreach ($beans as $bean) {
         $bean->setMeta('sys.belongs-to', $links[$bean->id]);
     }
     return $beans;
 }
Exemplo n.º 5
0
 /**
  * Binds an SQL function to a column.
  * This method can be used to setup a decode/encode scheme or
  * perform UUID insertion. This method is especially useful for handling
  * MySQL spatial columns, because they need to be processed first using
  * the asText/GeomFromText functions.
  *
  * Example:
  *
  * R::bindFunc( 'read', 'location.point', 'asText' );
  * R::bindFunc( 'write', 'location.point', 'GeomFromText' );
  *
  * Passing NULL as the function will reset (clear) the function
  * for this column/mode.
  *
  * @param string $mode     mode for function: i.e. read or write
  * @param string $field    field (table.column) to bind function to
  * @param string $function SQL function to bind to specified column
  *
  * @return void
  */
 public static function bindFunc($mode, $field, $function)
 {
     self::$redbean->bindFunc($mode, $field, $function);
 }
Exemplo n.º 6
0
 /**
  * Test trashAll().
  */
 public function testMultiDeleteUpdate()
 {
     testpack('test multi delete and multi update');
     $beans = R::dispenseLabels('bean', array('a', 'b'));
     $ids = R::storeAll($beans);
     asrt((int) R::count('bean'), 2);
     R::trashAll(R::batch('bean', $ids));
     asrt((int) R::count('bean'), 0);
     testpack('test assocManager check');
     $rb = new OODB(R::getWriter());
     try {
         $rb->getAssociationManager();
         fail();
     } catch (RedException $e) {
         pass();
     }
 }
Exemplo n.º 7
0
 /**
  * Test the database driver and low level functions.
  * 
  * @return void
  */
 public function testDriver()
 {
     $currentDriver = $this->currentlyActiveDriverID;
     R::store(R::dispense('justabean'));
     $adapter = new TroubleDapter(R::getToolBox()->getDatabaseAdapter()->getDatabase());
     $adapter->setSQLState('HY000');
     $writer = new SQLiteT($adapter);
     $redbean = new OODB($writer);
     $toolbox = new ToolBox($redbean, $adapter, $writer);
     // We can only test this for a known driver...
     if ($currentDriver === 'sqlite') {
         try {
             $redbean->find('bean');
             pass();
         } catch (\Exception $e) {
             var_dump($e->getSQLState());
             fail();
         }
     }
     $adapter->setSQLState(-999);
     try {
         $redbean->find('bean');
         fail();
     } catch (\Exception $e) {
         pass();
     }
     try {
         $redbean->wipe('justabean');
         fail();
     } catch (\Exception $e) {
         pass();
     }
     $toolbox = R::getToolBox();
     $adapter = $toolbox->getDatabaseAdapter();
     $writer = $toolbox->getWriter();
     $redbean = $toolbox->getRedBean();
     $pdo = $adapter->getDatabase();
     $page = $redbean->dispense("page");
     try {
         $adapter->exec("an invalid query");
         fail();
     } catch (SQL $e) {
         pass();
     }
     // Special data type description should result in magic number 99 (specified)
     if ($currentDriver == 'mysql') {
         asrt($writer->code(MySQL::C_DATATYPE_SPECIAL_DATE), 99);
     }
     if ($currentDriver == 'pgsql') {
         asrt($writer->code(PostgreSQL::C_DATATYPE_SPECIAL_DATE), 99);
     }
     if ($currentDriver == 'CUBRID') {
         asrt($writer->code(CUBRID::C_DATATYPE_SPECIAL_DATE), 99);
     }
     asrt((int) $adapter->getCell("SELECT 123"), 123);
     $page->aname = "my page";
     $id = (int) $redbean->store($page);
     asrt((int) $page->id, 1);
     asrt((int) $pdo->GetCell("SELECT count(*) FROM page"), 1);
     asrt($pdo->GetCell("SELECT aname FROM page LIMIT 1"), "my page");
     asrt((int) $id, 1);
     $page = $redbean->load("page", 1);
     asrt($page->aname, "my page");
     asrt((bool) $page->getMeta("type"), TRUE);
     asrt(isset($page->id), TRUE);
     asrt($page->getMeta("type"), "page");
     asrt((int) $page->id, $id);
 }
Exemplo n.º 8
0
 /**
  * Constructor,
  * creates a new instance of DupManager.
  *
  * @param ToolBox $toolbox
  */
 public function __construct(ToolBox $toolbox)
 {
     $this->toolbox = $toolbox;
     $this->redbean = $toolbox->getRedBean();
     $this->associationManager = $this->redbean->getAssociationManager();
 }
Exemplo n.º 9
0
 /**
  * Returns a hashmap with bean arrays keyed by type using an SQL
  * query as its resource. Given an SQL query like 'SELECT movie.*, review.* FROM movie... JOIN review'
  * this method will return movie and review beans.
  *
  * Example:
  *
  * $stuff = $finder->findMulti('movie,review', '
  *          SELECT movie.*, review.* FROM movie
  *          LEFT JOIN review ON review.movie_id = movie.id');
  *
  * After this operation, $stuff will contain an entry 'movie' containing all
  * movies and an entry named 'review' containing all reviews (all beans).
  * You can also pass bindings.
  *
  * If you want to re-map your beans, so you can use $movie->ownReviewList without
  * having RedBeanPHP executing an SQL query you can use the fourth parameter to
  * define a selection of remapping closures.
  *
  * The remapping argument (optional) should contain an array of arrays.
  * Each array in the remapping array should contain the following entries:
  *
  * array(
  * 	'a'       => TYPE A
  *    'b'       => TYPE B
  *    'matcher' => MATCHING FUNCTION ACCEPTING A, B and ALL BEANS
  *    'do'      => OPERATION FUNCTION ACCEPTING A, B, ALL BEANS, ALL REMAPPINGS
  * )
  *
  * Using this mechanism you can build your own 'preloader' with tiny function
  * snippets (and those can be re-used and shared online of course).
  *
  * Example:
  *
  * array(
  * 	'a'       => 'movie'     //define A as movie
  *    'b'       => 'review'    //define B as review
  *    'matcher' => function( $a, $b ) {
  *       return ( $b->movie_id == $a->id );  //Perform action if review.movie_id equals movie.id
  *    }
  *    'do'      => function( $a, $b ) {
  *       $a->noLoad()->ownReviewList[] = $b; //Add the review to the movie
  *       $a->clearHistory();                 //optional, act 'as if these beans have been loaded through ownReviewList'.
  *    }
  * )
  *
  * The Query Template parameter is optional as well but can be used to
  * set a different SQL template (sprintf-style) for processing the original query.
  *
  * @note the SQL query provided IS NOT THE ONE used internally by this function,
  * this function will pre-process the query to get all the data required to find the beans.
  *
  * @note if you use the 'book.*' notation make SURE you're
  * selector starts with a SPACE. ' book.*' NOT ',book.*'. This is because
  * it's actually an SQL-like template SLOT, not real SQL.
  *
  * @note instead of an SQL query you can pass a result array as well.
  *
  * @param string|array $types         a list of types (either array or comma separated string)
  * @param string|array $sqlOrArr      an SQL query or an array of prefetched records
  * @param array        $bindings      optional, bindings for SQL query
  * @param array        $remappings    optional, an array of remapping arrays
  * @param string       $queryTemplate optional, query template
  *
  * @return array
  */
 public function findMulti($types, $sql, $bindings = array(), $remappings = array(), $queryTemplate = ' %s.%s AS %s__%s')
 {
     if (!is_array($types)) {
         $types = explode(',', $types);
     }
     if (!is_array($sql)) {
         $writer = $this->toolbox->getWriter();
         $adapter = $this->toolbox->getDatabaseAdapter();
         //Repair the query, replace book.* with book.id AS book_id etc..
         foreach ($types as $type) {
             $pattern = " {$type}.*";
             if (strpos($sql, $pattern) !== FALSE) {
                 $newSelectorArray = array();
                 $columns = $writer->getColumns($type);
                 foreach ($columns as $column => $definition) {
                     $newSelectorArray[] = sprintf($queryTemplate, $type, $column, $type, $column);
                 }
                 $newSelector = implode(',', $newSelectorArray);
                 $sql = str_replace($pattern, $newSelector, $sql);
             }
         }
         $rows = $adapter->get($sql, $bindings);
     } else {
         $rows = $sql;
     }
     //Gather the bean data from the query results using the prefix
     $wannaBeans = array();
     foreach ($types as $type) {
         $wannaBeans[$type] = array();
         $prefix = "{$type}__";
         foreach ($rows as $rowkey => $row) {
             $wannaBean = array();
             foreach ($row as $cell => $value) {
                 if (strpos($cell, $prefix) === 0) {
                     $property = substr($cell, strlen($prefix));
                     unset($rows[$rowkey][$cell]);
                     $wannaBean[$property] = $value;
                 }
             }
             if (!isset($wannaBean['id'])) {
                 continue;
             }
             if (is_null($wannaBean['id'])) {
                 continue;
             }
             $wannaBeans[$type][$wannaBean['id']] = $wannaBean;
         }
     }
     //Turn the rows into beans
     $beans = array();
     foreach ($wannaBeans as $type => $wannabees) {
         $beans[$type] = $this->redbean->convertToBeans($type, $wannabees);
     }
     //Apply additional re-mappings
     foreach ($remappings as $remapping) {
         $a = $remapping['a'];
         $b = $remapping['b'];
         $matcher = $remapping['matcher'];
         $do = $remapping['do'];
         foreach ($beans[$a] as $bean) {
             foreach ($beans[$b] as $putBean) {
                 if ($matcher($bean, $putBean, $beans)) {
                     $do($bean, $putBean, $beans, $remapping);
                 }
             }
         }
     }
     return $beans;
 }
Exemplo n.º 10
0
 /**
  * Nukes the entire database.
  * This will remove all schema structures from the database.
  * Only works in fluid mode. Be careful with this method.
  * 
  * @warning dangerous method, will remove all tables, columns etc.
  *
  * @return void
  */
 public static function nuke()
 {
     if (!self::$redbean->isFrozen()) {
         self::$writer->wipeAll();
     }
 }