Exemplo n.º 1
0
 /**
  * Write metadata files for all the listed tables.
  *
  * @param string $path
  * @param DbAdapter $db
  * @param array $tables
  * @return void
  */
 protected function writeMetadataFiles($path, DbAdapter $db, array $tables)
 {
     $inflector = new Inflector();
     foreach ($tables as $table) {
         $columns = $db->describeTable($table);
         $references = $db->listForeignKeyReferences($table);
         $uniqueConstraints = $db->listUniqueConstraints($table);
         $title = $inflector->titleize($table);
         $replacements = array('{{singular}}' => $inflector->singularize($title), '{{plural}}' => $inflector->pluralize($title), '{{columns}}' => var_export($columns, true), '{{references}}' => var_export($references, true), '{{uniqueConstraints}}' => var_export($uniqueConstraints, true));
         file_put_contents("{$path}/{$table}.php", str_replace(array_keys($replacements), $replacements, file_get_contents(__DIR__ . '/db-metadata/template.tpl')));
     }
 }
Exemplo n.º 2
0
 /**
  * Load the metadata for the options table.
  *
  * @throws \Dewdrop\Exception
  * @return array
  */
 protected function loadTableMetadata()
 {
     if (!$this->tableName) {
         throw new DewdropException('Table name must be set prior to loading metadata.');
     }
     return $this->dbAdapter->getTableMetadata($this->tableName);
 }
Exemplo n.º 3
0
 /**
  * Delete any existing settings from the database.  Done inside a transaction
  * while saving new settings.
  *
  * @return void
  */
 public function deleteCurrentSettings()
 {
     $this->dbAdapter->delete('dewdrop_field_groups', $this->dbAdapter->quoteInto('dewdrop_field_group_id IN (
                 SELECT dewdrop_field_group_id
                 FROM dewdrop_sorted_fields
                 WHERE component = ?
             )', $this->componentName));
     $this->dbAdapter->delete('dewdrop_sorted_fields', $this->dbAdapter->quoteInto('component = ?', $this->componentName));
 }
Exemplo n.º 4
0
 private function getMissingIndexesByTable()
 {
     $missingIndexesByTable = [];
     foreach ($this->db->listTables() as $tableName) {
         $missingIndexes = $this->db->listMissingForeignKeyIndexes($tableName);
         if (count($missingIndexes)) {
             $missingIndexesByTable[$tableName] = $missingIndexes;
         }
     }
     return $missingIndexesByTable;
 }
Exemplo n.º 5
0
 /**
  * Get an array representing the columns in the root table's primary
  * key.  The returned array's keys will be the column names and the values
  * will be the metadata for that column as returned by
  * \Dewdrop\Db\Adapter::describeTable().
  *
  * @return array
  */
 protected function getEntityPrimaryKey()
 {
     if (!$this->entityPrimaryKey) {
         $meta = $this->db->getTableMetadata($this->tableName);
         $pkey = array();
         foreach ($meta['columns'] as $name => $column) {
             if ($column['PRIMARY']) {
                 $pkey[$name] = $column;
             }
         }
         $this->entityPrimaryKey = $pkey;
     }
     return $this->entityPrimaryKey;
 }
Exemplo n.º 6
0
 /**
  * Returns the column descriptions for a table.
  *
  * The return value is an associative array keyed by the column name,
  * as returned by the RDBMS.
  *
  * The value of each array element is an associative array
  * with the following keys:
  *
  * SCHEMA_NAME      => string; name of database or schema
  * TABLE_NAME       => string;
  * COLUMN_NAME      => string; column name
  * COLUMN_POSITION  => number; ordinal position of column in table
  * DATA_TYPE        => string; SQL datatype name of column
  * DEFAULT          => string; default expression of column, null if none
  * NULLABLE         => boolean; true if column can have nulls
  * LENGTH           => number; length of CHAR/VARCHAR
  * SCALE            => number; scale of NUMERIC/DECIMAL
  * PRECISION        => number; precision of NUMERIC/DECIMAL
  * UNSIGNED         => boolean; unsigned property of an integer type
  * PRIMARY          => boolean; true if column is part of the primary key
  * PRIMARY_POSITION => integer; position of column in primary key
  * IDENTITY         => integer; true if column is auto-generated with unique values
  *
  * @param string $tableName
  * @return array
  */
 public function describeTable($tableName)
 {
     $sql = "SELECT\n                a.attnum,\n                n.nspname,\n                c.relname,\n                a.attname AS colname,\n                t.typname AS type,\n                a.atttypmod,\n                FORMAT_TYPE(a.atttypid, a.atttypmod) AS complete_type,\n                d.adsrc AS default_value,\n                a.attnotnull AS notnull,\n                a.attlen AS length,\n                co.contype,\n                ARRAY_TO_STRING(co.conkey, ',') AS conkey\n            FROM pg_attribute AS a\n                JOIN pg_class AS c ON a.attrelid = c.oid\n                JOIN pg_namespace AS n ON c.relnamespace = n.oid\n                JOIN pg_type AS t ON a.atttypid = t.oid\n                LEFT OUTER JOIN pg_constraint AS co ON (co.conrelid = c.oid\n                    AND a.attnum = ANY(co.conkey) AND co.contype = 'p')\n                LEFT OUTER JOIN pg_attrdef AS d ON d.adrelid = c.oid AND d.adnum = a.attnum\n            WHERE a.attnum > 0 AND c.relname = " . $this->adapter->quote($tableName) . ' ORDER BY a.attnum';
     $result = $this->fetchAll($sql, array(), Adapter::ARRAY_N);
     $attnum = 0;
     $nspname = 1;
     $relname = 2;
     $colname = 3;
     $type = 4;
     $atttypemod = 5;
     $complete_type = 6;
     $default_value = 7;
     $notnull = 8;
     $length = 9;
     $contype = 10;
     $conkey = 11;
     $desc = array();
     foreach ($result as $key => $row) {
         $defaultValue = $row[$default_value];
         if ($row[$type] == 'varchar' || $row[$type] == 'bpchar') {
             if (preg_match('/character(?: varying)?(?:\\((\\d+)\\))?/', $row[$complete_type], $matches)) {
                 if (isset($matches[1])) {
                     $row[$length] = $matches[1];
                 } else {
                     $row[$length] = null;
                     // unlimited
                 }
             }
             if (preg_match("/^'(.*?)'::(?:character varying|bpchar)\$/", $defaultValue, $matches)) {
                 $defaultValue = $matches[1];
             }
         }
         if ($row[$type] === 'bool' && $row[$default_value]) {
             $defaultValue = 'true' === $row[$default_value] ? 1 : 0;
         }
         if (false !== strpos($defaultValue, '(')) {
             $defaultValue = null;
         }
         list($primary, $primaryPosition, $identity) = array(false, null, false);
         if ($row[$contype] == 'p') {
             $primary = true;
             $primaryPosition = array_search($row[$attnum], explode(',', $row[$conkey])) + 1;
             $identity = (bool) preg_match('/^nextval/', $row[$default_value]);
         }
         $desc[$this->adapter->foldCase($row[$colname])] = array('SCHEMA_NAME' => $this->adapter->foldCase($row[$nspname]), 'TABLE_NAME' => $this->adapter->foldCase($row[$relname]), 'COLUMN_NAME' => $this->adapter->foldCase($row[$colname]), 'COLUMN_POSITION' => $row[$attnum], 'DATA_TYPE' => $row[$type], 'GENERIC_TYPE' => $this->mapNativeTypeToGenericType($row[$type], $length), 'DEFAULT' => $defaultValue, 'NULLABLE' => (bool) ($row[$notnull] != 't'), 'LENGTH' => $row[$length], 'SCALE' => null, 'PRECISION' => null, 'UNSIGNED' => null, 'PRIMARY' => $primary, 'PRIMARY_POSITION' => $primaryPosition, 'IDENTITY' => $identity);
     }
     return $desc;
 }
Exemplo n.º 7
0
 /**
  * Get the values for any foreign keys in the DB table that reference the user
  * object's table.  Allows the filter to be applied on a per-user basis.
  *
  * @return array
  */
 protected function getUserReferenceValues()
 {
     $user = $this->getUser();
     if (!$user) {
         return [];
     }
     $out = [];
     $userTable = $user->getTable();
     $metadata = $this->dbAdapter->getTableMetadata($this->dbTableName);
     foreach ($metadata['references'] as $foreignKey => $reference) {
         if ($reference['table'] === $userTable->getTableName()) {
             $out[$foreignKey] = $user->get($reference['column']);
         }
     }
     return $out;
 }
Exemplo n.º 8
0
 public function testDelete()
 {
     $table = 'dewdrop_test_fruits';
     $idField = 'dewdrop_test_fruit_id';
     $fetchAllSql = "SELECT * FROM {$table} ORDER BY {$idField}";
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(5, count($fruits));
     $this->assertEquals(1, $fruits[0][$idField]);
     $fruit = $this->table->find(1);
     $this->assertSame(1, $fruit->delete());
     $this->assertNull($fruit->get('dewdrop_test_fruit_id'));
     $this->assertNull($fruit->get('name'));
     $this->assertNull($fruit->get('is_delicious'));
     $this->assertNull($fruit->get('level_of_deliciousness'));
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(4, count($fruits));
     $this->assertEquals(2, $fruits[0][$idField]);
 }
Exemplo n.º 9
0
 /**
  * Render LIMIT OFFSET clause
  *
  * @param string   $sql SQL query
  * @return string
  */
 protected function renderLimitoffset($sql)
 {
     $count = 0;
     $offset = 0;
     if (!empty($this->parts[self::LIMIT_OFFSET])) {
         $offset = (int) $this->parts[self::LIMIT_OFFSET];
         $count = PHP_INT_MAX;
     }
     if (!empty($this->parts[self::LIMIT_COUNT])) {
         $count = (int) $this->parts[self::LIMIT_COUNT];
     }
     /*
      * Add limits clause
      */
     if ($count > 0) {
         $sql = trim($this->adapter->limit($sql, $count, $offset));
     }
     return $sql;
 }
Exemplo n.º 10
0
 public function testDelete()
 {
     $table = 'dewdrop_test_fruits';
     $idField = 'dewdrop_test_fruit_id';
     $fetchAllSql = "SELECT * FROM {$table} ORDER BY {$idField}";
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(5, count($fruits));
     $this->assertEquals(1, $fruits[0][$idField]);
     $this->assertSame(1, $this->table->delete("{$idField} = 1"));
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(4, count($fruits));
     $this->assertEquals(2, $fruits[0][$idField]);
     $this->assertSame(0, $this->table->delete("{$idField} = 7"));
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(4, count($fruits));
     $this->assertEquals(2, $fruits[0][$idField]);
     $this->assertSame(1, $this->table->delete(array("{$idField} = 2", 'is_delicious')));
     $fruits = $this->db->fetchAll($fetchAllSql);
     $this->assertSame(3, count($fruits));
     $this->assertEquals(3, $fruits[0][$idField]);
 }
Exemplo n.º 11
0
 /**
  * Determine a reasonable value to use as a title for a foreign key
  * reference.  We'll look for a name or title in the referenced table.  If
  * neither is present, we just grab the first column, which is probably the
  * ID itself.
  *
  * However, you can call setReferenceTitleColumn() to supply a different
  * column to use or an Expr object.
  *
  * @param $localColumn
  * @param array $reference
  * @param string $alias
  * @return string|Expr
  */
 private function findReferenceTitleColumn($localColumn, array $reference, $alias)
 {
     if (array_key_exists($localColumn, $this->referenceTitleColumns)) {
         $value = $this->referenceTitleColumns[$localColumn];
         if (is_callable($value)) {
             $value = call_user_func($value, $alias);
             if (!is_string($value) && !$value instanceof Expr) {
                 throw new Exception('Title column callbacks should return a string or Expr.');
             }
         }
         return $value;
     }
     $metadata = $this->db->getTableMetadata($reference['table']);
     $columns = array_keys($metadata['columns']);
     if (in_array('name', $columns)) {
         return 'name';
     } elseif (in_array('title', $columns)) {
         return 'title';
     } else {
         return array_shift($columns);
     }
 }
Exemplo n.º 12
0
 public function testGetDriver()
 {
     $this->assertInstanceOf('\\Dewdrop\\Db\\Driver\\DriverInterface', $this->db->getDriver());
 }
Exemplo n.º 13
0
 /**
  * Build a WHERE clause for use in deleting cross-reference values while
  * saving.  If we have no cross-reference values, we delete all cross-reference
  * rows with the given anchor value.  Otherwise, we only delete those rows
  * that are not related to the newly supplied $xrefValues.
  *
  * @param DbAdapter $db
  * @param array $xrefValues
  * @param mixed $anchorValue
  * @return string
  */
 private function buildDeleteWhereClause(DbAdapter $db, array $xrefValues, $anchorValue)
 {
     $anchorName = $db->quoteIdentifier("{$this->xrefTableName}.{$this->getXrefAnchorColumnName()}");
     if (!count($xrefValues) || $this->allowDuplicateValues) {
         $where = "{$anchorName} = ?";
         $where = $db->quoteInto($where, $anchorValue);
     } else {
         $refName = $db->quoteIdentifier("{$this->xrefTableName}.{$this->getXrefReferenceColumnName()}");
         $where = "{$anchorName} = ? AND {$refName} NOT IN (?)";
         $where = $db->quoteInto($where, $anchorValue, null, 1);
         $where = $db->quoteInto($where, $xrefValues, null, 1);
     }
     return $where;
 }
Exemplo n.º 14
0
 /**
  * Check to see if the changelog table exists in the database already.
  *
  * @return bool
  */
 protected function tableExists()
 {
     return in_array($this->tableName, $this->dbAdapter->listTables());
 }
Exemplo n.º 15
0
 /**
  * Assemble SQL for finding a row by its primary key.
  *
  * @param array $args The primary key values
  * @return string
  */
 private function assembleFindSql(array $args)
 {
     $sql = sprintf('SELECT * FROM %s WHERE %s', $this->db->quoteIdentifier($this->tableName), $this->assembleFindWhere($args));
     return $sql;
 }
Exemplo n.º 16
0
 /**
  * Define the DB resource for Pimple.
  *
  * @return Wp
  */
 public function defineDb()
 {
     $this->pimple['db'] = $this->pimple->share(function () {
         global $wpdb;
         $adapter = new DbAdapter();
         $driver = new WpdbDriver($adapter, $wpdb);
         $adapter->setDriver($driver);
         return $adapter;
     });
     return $this;
 }
Exemplo n.º 17
0
 /**
  * Use MySQL's FOUND_ROWS() facility to retrieve the total number of rows
  * that would have been fetched on the previous statement if no LIMIT was
  * applied.
  *
  * @param array $resultSet
  * @return integer
  */
 public function fetchTotalRowCount(array $resultSet)
 {
     return $this->adapter->fetchOne('SELECT FOUND_ROWS()');
 }
Exemplo n.º 18
0
 public function generateAnalyzeTableStatement($tableName)
 {
     return sprintf('ANALYZE %s;', $this->adapter->quoteIdentifier($tableName));
 }