/** * Constructor, requires a writer * @param RedBean_QueryWriter $writer */ public function __construct(RedBean_ToolBox $toolbox) { $this->writer = $toolbox->getWriter(); $this->adapter = $toolbox->getDatabaseAdapter(); $this->redbean = $toolbox->getRedBean(); if ($this->redbean->isFrozen()) { $this->adapter->exec("\n\t\t\t\t\t\tCREATE TABLE IF NOT EXISTS `__log` (\n\t\t\t\t\t\t`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,\n\t\t\t\t\t\t`tbl` VARCHAR( 255 ) NOT NULL ,\n\t\t\t\t\t\t`action` TINYINT( 2 ) NOT NULL ,\n\t\t\t\t\t\t`itemid` INT( 11 ) NOT NULL\n\t\t\t\t\t\t) ENGINE = MYISAM ;\n\t\t\t\t"); //Must be MyISAM! else you run in trouble if you use transactions! } $maxid = $this->adapter->getCell("SELECT MAX(id) FROM __log"); $this->adapter->exec("DELETE FROM __log WHERE id < {$maxid} - 200 "); }
/** * Creates a view with name $viewID based on $refType bean type * and then left-joining the specified types in $types in the given * order. * * @param string $viewID desired name of the view * @param string $refType first bean type to be used as base * @param array $types array with types to be left-joined in view * * @return boolean $success whether we created a new view (false if already exists) */ public function createView($viewID, $refType, $types) { if ($this->oodb->isFrozen()) { return false; } $history = array(); $tables = array_flip($this->writer->getTables()); $refTable = $refType; //$this->writer->safeTable($refType, true); $currentTable = $refTable; $history[$refType] = $refType; foreach ($types as $t) { if (!isset($history[$t])) { $history[$t] = $t; $connection = array($t, $currentTable); sort($connection); $connection = implode("_", $connection); $connectionTable = $this->writer->safeTable($connection, true); if (isset($tables[$connectionTable])) { //this connection exists $srcPoint = $this->writer->safeTable($connection) . "." . $this->writer->safeColumn($currentTable . "_id"); //i.e. partic_project.project_id $dstPoint = $this->writer->safeTable($currentTable) . "." . $this->writer->safeColumn($this->writer->getIDField($currentTable)); //i.e. project.id $joins[$connection] = array($srcPoint, $dstPoint); //now join the type $srcPoint = $this->writer->safeTable($connection) . "." . $this->writer->safeColumn($t . "_id"); $dstPoint = $this->writer->safeTable($t) . "." . $this->writer->safeColumn($this->writer->getIDField($t)); $joins[$t] = array($srcPoint, $dstPoint); } else { //this connection does not exist $srcPoint = $this->writer->safeTable($t) . "." . $this->writer->safeColumn($currentTable . "_id"); $dstPoint = $this->writer->safeTable($currentTable) . "." . $this->writer->safeColumn($this->writer->getIDField($currentTable)); $joins[$t] = array($srcPoint, $dstPoint); } } //now set the new refTable $currentTable = $t; } try { $rs = (bool) $this->writer->createView($refType, $joins, $viewID); } catch (Exception $e) { throw new RedBean_Exception_SQL('Could not create view, types does not seem related (yet)..'); } return $rs; }
/** * Associates a pair of beans. This method associates two beans, no matter * what types. * * @param RedBean_OODBBean $bean1 first bean * @param RedBean_OODBBean $bean2 second bean * @param RedBean_OODBBean $bean base bean * * @return mixed $id either the link ID or null */ protected function associateBeans(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, RedBean_OODBBean $bean) { $idfield1 = $this->writer->getIDField($bean1->getMeta("type")); $idfield2 = $this->writer->getIDField($bean2->getMeta("type")); $property1 = $bean1->getMeta("type") . "_id"; $property2 = $bean2->getMeta("type") . "_id"; if ($property1 == $property2) { $property2 = $bean2->getMeta("type") . "2_id"; } //add a build command for Unique Indexes $bean->setMeta("buildcommand.unique", array(array($property1, $property2))); //add a build command for Single Column Index (to improve performance in case unqiue cant be used) $indexName1 = "index_for_" . $bean->getMeta("type") . "_" . $property1; $indexName2 = "index_for_" . $bean->getMeta("type") . "_" . $property2; $bean->setMeta("buildcommand.indexes", array($property1 => $indexName1, $property2 => $indexName2)); $this->oodb->store($bean1); $this->oodb->store($bean2); $bean->setMeta("assoc." . $bean1->getMeta("type"), $bean1); $bean->setMeta("assoc." . $bean2->getMeta("type"), $bean2); $bean->setMeta("cast.{$property1}", "id"); $bean->setMeta("cast.{$property2}", "id"); $bean->{$property1} = $bean1->{$idfield1}; $bean->{$property2} = $bean2->{$idfield2}; try { $id = $this->oodb->store($bean); //On creation, add constraints.... if ($this->flagUseConstraints && !$this->oodb->isFrozen() && $bean->getMeta("buildreport.flags.created")) { $bean->setMeta("buildreport.flags.created", 0); if (!$this->oodb->isFrozen()) { $this->writer->addConstraint($bean1, $bean2); } } return $id; } catch (RedBean_Exception_SQL $e) { if (!$this->writer->sqlStateIn($e->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) { throw $e; } } }
/** * Associates a pair of beans. This method associates two beans, no matter * what types. Accepts a base bean that contains data for the linking record. * This method is used by associate. This method also accepts a base bean to be used * as the template for the link record in the database. * * @param RedBean_OODBBean $bean1 first bean * @param RedBean_OODBBean $bean2 second bean * @param RedBean_OODBBean $bean base bean (association record) * * @throws Exception|RedBean_Exception_SQL * * @return mixed */ protected function associateBeans(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, RedBean_OODBBean $bean) { $property1 = $bean1->getMeta('type') . '_id'; $property2 = $bean2->getMeta('type') . '_id'; if ($property1 == $property2) { $property2 = $bean2->getMeta('type') . '2_id'; } //add a build command for Unique Indexes $bean->setMeta('buildcommand.unique', array(array($property1, $property2))); //add a build command for Single Column Index (to improve performance in case unqiue cant be used) $indexName1 = 'index_for_' . $bean->getMeta('type') . '_' . $property1; $indexName2 = 'index_for_' . $bean->getMeta('type') . '_' . $property2; $bean->setMeta('buildcommand.indexes', array($property1 => $indexName1, $property2 => $indexName2)); $this->oodb->store($bean1); $this->oodb->store($bean2); $bean->setMeta("cast.{$property1}", "id"); $bean->setMeta("cast.{$property2}", "id"); $bean->{$property1} = $bean1->id; $bean->{$property2} = $bean2->id; $results = array(); try { $id = $this->oodb->store($bean); //On creation, add constraints.... if (!$this->oodb->isFrozen() && $bean->getMeta('buildreport.flags.created')) { $bean->setMeta('buildreport.flags.created', 0); if (!$this->oodb->isFrozen()) { $this->writer->addConstraintForTypes($bean1->getMeta('type'), $bean2->getMeta('type')); } } $results[] = $id; } catch (RedBean_Exception_SQL $exception) { if (!$this->writer->sqlStateIn($exception->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) { throw $exception; } } return $results; }
/** * Nukes the entire database. */ public static function nuke() { if (!self::$redbean->isFrozen()) { self::$writer->wipeAll(); } }
/** * 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 function nuke() { if (!$this->redbean->isFrozen()) { $this->writer->wipeAll(); } }
/** * Executes SQL function but corrects for SQL states. * @param closure $func * @param mixed $default * @param string $sql * @param array $values * @return mixed $results */ private static function secureExec($func, $sql, $values, $default = NULL) { if (!self::$redbean->isFrozen()) { try { $rs = R::$adapter->{$func}($sql, $values); } catch (RedBean_Exception_SQL $e) { //die($e); if (self::$writer->sqlStateIn($e->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_TABLE))) { return $default; } else { throw $e; } } return $rs; } else { return R::$adapter->{$func}($sql, $values); } }