Skip to content

Commit

Permalink
Fixed PEAR sequence table problem in phpws2
Browse files Browse the repository at this point in the history
phpws2 db worked with PEAR sequence tables, but only if one was
already established. Update creates the table and added the first
id.
  • Loading branch information
Stardog committed Nov 14, 2017
1 parent 1d653bb commit f990048
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 30 deletions.
21 changes: 17 additions & 4 deletions src-phpws2/src/Database/Engine/mysql/Table.php
Expand Up @@ -9,6 +9,7 @@
*/
class Table extends \phpws2\Database\Table
{

private $storage_engine = 'InnoDB';

/**
Expand Down Expand Up @@ -109,7 +110,7 @@ public function getSchemaQuery($column_name = null)

if (isset($column_name)) {
$column = new \phpws2\Variable\Attribute($column_name);
$sql_query.= ' AND information_schema.columns.column_name=\'' .
$sql_query .= ' AND information_schema.columns.column_name=\'' .
$column->get() . '\'';
}
return $sql_query;
Expand Down Expand Up @@ -158,10 +159,12 @@ public function getDataType($column_name)
}
$schema = $this->getSchema($column_name);
if (empty($schema)) {
throw new \Exception(sprintf('Unable to retrieve information about column %s', $column_name));
throw new \Exception(sprintf('Unable to retrieve information about column %s',
$column_name));
}
$column_type = $schema['DATA_TYPE'];
$dt = \phpws2\Database\Datatype::factory($this, $column_name, $column_type);
$dt = \phpws2\Database\Datatype::factory($this, $column_name,
$column_type);

$indexes = $this->getIndexes();
if (!empty($indexes)) {
Expand Down Expand Up @@ -244,6 +247,15 @@ public function hasPearSequenceTable()
$seq_table_name = $this->getFullName(false) . '_seq';
return $this->db->tableExists($seq_table_name);
}


protected function createPearSequenceTable()
{
$sequence_name = $this->getPearSequenceName();
$query = "CREATE TABLE $sequence_name (id int not null auto_increment, primary key (id))";
$this->db->exec($query);
$this->firstSequenceValue();
}

/**
* Switches from PHPWS_DB's PEAR sequence table dependence to one using
Expand Down Expand Up @@ -287,7 +299,8 @@ public function createPrimaryIndexId()
* @param \phpws2\Database\Datatype $old
* @param \phpws2\Database\Datatype $new
*/
public function alter(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype $new)
public function alter(\phpws2\Database\Datatype $old,
\phpws2\Database\Datatype $new)
{
$table_name = $this->getFullName();
$old_column_name = $old->getName();
Expand Down
28 changes: 21 additions & 7 deletions src-phpws2/src/Database/Engine/pgsql/Table.php
Expand Up @@ -9,6 +9,7 @@
*/
class Table extends \phpws2\Database\Table
{

/**
* Table name is NOT included after "using" in a delete query
* @var boolean
Expand Down Expand Up @@ -166,7 +167,8 @@ public function getDataType($column_name)
$schema = $this->getSchema($column_name);

$column_type = $schema['data_type'];
$dt = \phpws2\Database\Datatype::factory($this, $column_name, $column_type);
$dt = \phpws2\Database\Datatype::factory($this, $column_name,
$column_type);

$indexes = $this->getIndexes();
if (!empty($indexes)) {
Expand All @@ -188,7 +190,8 @@ public function getDataType($column_name)
$dt->setIsNull($schema['is_nullable'] != 'NO');

if ($find_default) {
$default = preg_replace("/::\w[\w\s]+/", '', $schema['column_default']);
$default = preg_replace("/::\w[\w\s]+/", '',
$schema['column_default']);

if (strtolower($default) == 'null') {
$default = null;
Expand All @@ -212,13 +215,21 @@ public function hasPearSequenceTable()
return (bool) $result;
}

protected function createPearSequenceTable()
{
$sequence_name = $this->getPearSequenceName();
$query = 'CREATE SEQUENCE $sequence_name INCREMENT 1 START 1';
$this->db->exec($query);
$this->firstSequenceValue();
}

public function getLastPearSequence()
{
$seq_table = $this->getPearSequenceName();
$result = DB::$PDO->query("select nextval('$seq_table')");
return $result->fetchColumn();
}

/**
* Changes id in the Postgresql to serial coupled to its sequence table.
*/
Expand Down Expand Up @@ -266,7 +277,8 @@ public function createPrimaryIndexId()
* @param \phpws2\Database\Datatype $old
* @param \phpws2\Database\Datatype $new
*/
public function alter(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype $new)
public function alter(\phpws2\Database\Datatype $old,
\phpws2\Database\Datatype $new)
{
$this->alterColumnParameters($new);
$this->alterNullStatus($old, $new);
Expand All @@ -278,7 +290,8 @@ public function alter(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype
* @param \phpws2\Database\Datatype $old
* @param \phpws2\Database\Datatype $new
*/
private function alterNullStatus(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype $new)
private function alterNullStatus(\phpws2\Database\Datatype $old,
\phpws2\Database\Datatype $new)
{
$table_name = $this->getFullName();
$column_name = $new->getName();
Expand All @@ -303,7 +316,8 @@ private function alterNullStatus(\phpws2\Database\Datatype $old, \phpws2\Databas
* @param \phpws2\Database\Datatype $old
* @param \phpws2\Database\Datatype $new
*/
private function alterDefaultStatus(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype $new)
private function alterDefaultStatus(\phpws2\Database\Datatype $old,
\phpws2\Database\Datatype $new)
{
$old_default = $old->getDefault();
$new_default = $new->getDefault();
Expand Down Expand Up @@ -339,7 +353,7 @@ private function alterColumnParameters(\phpws2\Database\Datatype $new)
EOF;
$this->db->exec($query);
}

public function getPrimaryKeySequenceName()
{
$sql_query = 'SELECT pg_get_serial_sequence(\'' . $this->getFullName(false) . '\', \'id\')';
Expand Down
80 changes: 61 additions & 19 deletions src-phpws2/src/Database/Table.php
Expand Up @@ -23,6 +23,7 @@
*/
abstract class Table extends Resource
{

const default_foreign_key_name = 'default_foreign_key';

/**
Expand Down Expand Up @@ -148,7 +149,8 @@ abstract public function columnExists($column_name);

abstract public function constraintTypeAfterName();

abstract public function alter(\phpws2\Database\Datatype $old, \phpws2\Database\Datatype $new);
abstract public function alter(\phpws2\Database\Datatype $old,
\phpws2\Database\Datatype $new);

/**
* Serializes the primary key in the current table. This is a one time method
Expand All @@ -169,7 +171,8 @@ abstract public function rename($new_name);
* @param \phpws2\Database\Field $field Field to change
* @param string $new_name Name to change field to.
*/
abstract public function renameField(\phpws2\Database\Field $field, $new_name);
abstract public function renameField(\phpws2\Database\Field $field,
$new_name);

/**
* Return the type of database column the current column is.
Expand Down Expand Up @@ -219,6 +222,11 @@ abstract public function getLastPearSequence();

abstract public function getPrimaryKeySequenceName();

/**
* Creates a Pear sequence table based of MDB2 query
*/
abstract protected function createPearSequenceTable();

/**
* @param string $name Name of the table
* @param string $alias Alias used in place of table name
Expand Down Expand Up @@ -270,10 +278,29 @@ private function checkConstraintTable(Constraint $constraint)
{
$source_table_name = $constraint->getSourceTable()->getFullName();
if ($source_table_name != $this->getFullName()) {
throw new \Exception(sprintf('Source column table %s does not match current table %s', $source_table_name, $this->getFullName()));
throw new \Exception(sprintf('Source column table %s does not match current table %s',
$source_table_name, $this->getFullName()));
}
}

/**
* Gets the max id of a table. Used by createPearSequenceTable
*/
protected function getMaxId()
{
$tableName = $this->getFullName(true);
$pdo = $this->db->query("select max(id) from $tableName");
return $pdo->fetchColumn(0);
}

protected function firstSequenceValue()
{
$sequence_name = $this->getPearSequenceName();
$startId = (int) $this->getMaxId();
$insertQuery = "insert into $sequence_name (id) values ($startId)";
$this->db->exec($insertQuery);
}

/**
* Adds an associative array of values to the table for an update or
* insert execution. If this is a multi-tier array, multiple value
Expand Down Expand Up @@ -355,7 +382,8 @@ public function addValue($column, $value = null, $value_key = 0)
public function getValue($column_name, $value = null)
{
if (!$this->db->allowed($column_name)) {
throw new \Exception(sprintf('Improper column name: "%s"', $column_name));
throw new \Exception(sprintf('Improper column name: "%s"',
$column_name));
}
if ($value instanceof \phpws2\Variable) {
$value = $value->toDatabase();
Expand Down Expand Up @@ -415,27 +443,32 @@ public function usePearSequence($use = null)
*/
public function insertQuery($use_bind_vars = true)
{
$use_pear = false;
if ($this->hasPearSequenceTable()) {
$use_pear = $this->usePearSequence();
if (is_null($use_pear)) {
throw new \Exception('This table uses a PEAR sequence table. Cannot insert until usePearSequence is set.');
}
if ($this->usePearSequence() && !$this->hasPearSequenceTable()) {
$this->createPearSequenceTable();
}

if (!$this->usePearSequence() && $this->hasPearSequenceTable()) {
throw new \Exception('This table uses a PEAR sequence table. Cannot insert until usePearSequence is set.');
}

$column_values = array();
/**
* If insert select is present, we run with it and stop. The columns are ignored below.
*/
if ($this->insert_select) {
if (empty($this->insert_select_columns)) {
return sprintf('insert into %s %s;', $this->getFullName(), $this->insert_select);
return sprintf('insert into %s %s;', $this->getFullName(),
$this->insert_select);
} else {
return sprintf('insert into %s (%s) %s;', $this->getFullName(), implode(', ', $this->insert_select_columns), $this->insert_select);
return sprintf('insert into %s (%s) %s;', $this->getFullName(),
implode(', ', $this->insert_select_columns),
$this->insert_select);
}
}

if (empty($this->values)) {
throw new \Exception(sprintf(sprintf('No columns to insert in table: %s'), $this->getFullName()));
throw new \Exception(sprintf(sprintf('No columns to insert in table: %s'),
$this->getFullName()));
}
foreach ($this->values as $val_listing) {
$columns = array();
Expand All @@ -450,7 +483,8 @@ public function insertQuery($use_bind_vars = true)
# If we are using bind vars, they will be supplied in the DB::insert method
if ($use_bind_vars) {
$column_values = $set_names;
array_walk($column_values, function(&$value) {
array_walk($column_values,
function(&$value) {
$value = ':' . $value;
});
} else {
Expand All @@ -465,12 +499,13 @@ public function insertQuery($use_bind_vars = true)
}
reset($this->values);

if ($use_pear) {
if ($this->usePearSequence()) {
$set_names[] = 'id';
$column_values[] = ':id';
}

return sprintf('insert into %s (%s) values (%s);', $this->getFullName(), implode(', ', $set_names), implode(', ', $column_values));
return sprintf('insert into %s (%s) values (%s);', $this->getFullName(),
implode(', ', $set_names), implode(', ', $column_values));
}

/**
Expand Down Expand Up @@ -522,7 +557,8 @@ public function setPrimaryKey()
call_user_func_array(array('self', 'setPrimaryKey'), $col);
$recursion = false;
} elseif (is_string($col)) {
$this->primary_key[] = new \phpws2\Database\Field($this, $col, null, false);
$this->primary_key[] = new \phpws2\Database\Field($this, $col,
null, false);
} else {
throw new \Exception('Could not use supplied parameters');
}
Expand Down Expand Up @@ -723,7 +759,8 @@ public function getDelimiter()
protected function getConstraintString($create_query = false)
{
foreach ($this->constraints as $c) {
if ($create_query && !is_a($c, '\phpws2\Database\TableCreateConstraint')) {
if ($create_query && !is_a($c,
'\phpws2\Database\TableCreateConstraint')) {
throw new \Exception('This constraint is not allowed during table creation');
}
$sql[] = $c->getConstraintString();
Expand Down Expand Up @@ -781,7 +818,12 @@ public function insert()
}
if ($id_column_exists) {
if ($this->usePearSequence()) {
$data['id'] = $this->getLastPearSequence() + 1;
$lastSeq = $this->getLastPearSequence();
if ($lastSeq === false) {
$data['id'] = 1;
} else {
$data['id'] = $lastSeq + 1;
}
}
}
$prep->execute($data);
Expand Down

0 comments on commit f990048

Please sign in to comment.