Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch '1.0.0-beta3'

  • Loading branch information...
commit 599c4e626d607efa924350b3d56c0d68acc0c746 2 parents 3b481b5 + be53a8e
Paul M. Jones pmjones authored
Showing with 1,526 additions and 610 deletions.
  1. +2 −9 .travis.yml
  2. +181 −14 README.md
  3. +24 −8 composer.json
  4. +1 −0  meta/authors.csv
  5. +22 −1 meta/changes.txt
  6. +1 −1  meta/require.csv
  7. +8 −2 src.php
  8. +170 −157 src/Aura/Sql/Adapter/AbstractAdapter.php
  9. +18 −15 src/Aura/Sql/Adapter/Mysql.php
  10. +20 −17 src/Aura/Sql/Adapter/Pgsql.php
  11. +35 −32 src/Aura/Sql/Adapter/Sqlite.php
  12. +17 −14 src/Aura/Sql/Adapter/Sqlsrv.php
  13. +9 −4 src/Aura/Sql/AdapterFactory.php
  14. +20 −14 src/Aura/Sql/Column.php
  15. +8 −2 src/Aura/Sql/ColumnFactory.php
  16. +23 −20 src/Aura/Sql/ConnectionManager.php
  17. +6 −1 src/Aura/Sql/Exception.php
  18. +7 −1 src/Aura/Sql/Exception/NoSuchMaster.php
  19. +7 −1 src/Aura/Sql/Exception/NoSuchSlave.php
  20. +17 −11 src/Aura/Sql/Profiler.php
  21. +11 −5 src/Aura/Sql/ProfilerInterface.php
  22. +87 −0 src/Aura/Sql/Query/AbstractQuery.php
  23. +64 −0 src/Aura/Sql/Query/Delete.php
  24. +40 −0 src/Aura/Sql/Query/Factory.php
  25. +63 −0 src/Aura/Sql/Query/Insert.php
  26. +175 −185 src/Aura/Sql/{ → Query}/Select.php
  27. +72 −0 src/Aura/Sql/Query/Update.php
  28. +88 −0 src/Aura/Sql/Query/ValuesTrait.php
  29. +91 −0 src/Aura/Sql/Query/WhereTrait.php
  30. +0 −11 src/Aura/Sql/SelectFactory.php
  31. +21 −3 tests/Aura/Sql/Adapter/AbstractAdapterTest.php
  32. +2 −2 tests/Aura/Sql/Adapter/Mock.php
  33. +31 −0 tests/Aura/Sql/ColumnTest.php
  34. +44 −0 tests/Aura/Sql/Query/AbstractQueryTest.php
  35. +26 −0 tests/Aura/Sql/Query/DeleteTest.php
  36. +32 −0 tests/Aura/Sql/Query/InsertTest.php
  37. +48 −80 tests/Aura/Sql/{ → Query}/SelectTest.php
  38. +35 −0 tests/Aura/Sql/Query/UpdateTest.php
11 .travis.yml
View
@@ -1,15 +1,8 @@
language: php
env:
- DB=sqlite
- - DB=mysql:
- adapter: mysql2
- database: test
- username:
- encoding: utf8
- - DB=postgres:
- adapter: postgresql
- database: test
- username: postgres
+ - DB=mysql
+ - DB=postgres
php:
- 5.4
before_script:
195 README.md
View
@@ -1,8 +1,16 @@
Aura SQL
========
-The Aura SQL package provides adapters to connect to and query against SQL data sources such as MySQL, PostgreSQL, and Sqlite. The adapters are mostly wrappers around [PDO](http://php.net/PDO) connections.
+The Aura SQL package provides adapters to connect to and query against SQL
+data sources such as MySQL, PostgreSQL, and Sqlite. The adapters are mostly
+wrappers around [PDO](http://php.net/PDO) connections.
+This package is compliant with [PSR-0][], [PSR-1][], and [PSR-2][]. If you
+notice compliance oversights, please send a patch via pull request.
+
+[PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
+[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
Getting Started
===============
@@ -10,7 +18,8 @@ Getting Started
Instantiation
-------------
-The easiest way to get started is to use the `scripts/instance.php` script to get an `AdapterFactory` and create your adapter through it:
+The easiest way to get started is to use the `scripts/instance.php` script to
+get an `AdapterFactory` and create your adapter through it:
<?php
$adapter_factory = include '/path/to/Aura.Sql/scripts/instance.php';
@@ -30,19 +39,23 @@ The easiest way to get started is to use the `scripts/instance.php` script to ge
'password'
);
-Alternatively, you can add `'/path/to/Aura.Sql/src` to your autoloader and build an adapter factory manually:
+Alternatively, you can add `'/path/to/Aura.Sql/src` to your autoloader and
+build an adapter factory manually:
<?php
use Aura\Sql\AdapterFactory;
$adapter_factory = new AdapterFactory;
$sql = $adapter_factory->newInstance(...);
-Aura SQL comes with three adapters: `'mysql'` for MySQL, `'pgsql'` for PostgreSQL, and `'sqlite'` for SQLite3.
+Aura SQL comes with three adapters: `'mysql'` for MySQL, `'pgsql'` for
+PostgreSQL, and `'sqlite'` for SQLite3.
Connecting
----------
-The adapter will lazy-connect to the database the first time you issue a query of any sort. This means you can create the adapter object, and if you never issue a query, it will never connect to the database.
+The adapter will lazy-connect to the database the first time you issue a query
+of any sort. This means you can create the adapter object, and if you never
+issue a query, it will never connect to the database.
You can connect manually by issuing `connect()`:
@@ -53,7 +66,8 @@ You can connect manually by issuing `connect()`:
Fetching Results
----------------
-Once you have an adapter connection, you can begin to fetch results from the database.
+Once you have an adapter connection, you can begin to fetch results from the
+database.
<?php
// returns all rows
@@ -77,9 +91,13 @@ You can fetch results using these methods:
Preventing SQL Injection
------------------------
-Usually you will need to incorporate user-provided data into the query. This means you should quote all values interpolated into the query text as a security measure to [prevent SQL injection](http://bobby-tables.com/).
+Usually you will need to incorporate user-provided data into the query. This
+means you should quote all values interpolated into the query text as a
+security measure to [prevent SQL injection](http://bobby-tables.com/).
-Although Aura SQL provides quoting methods, you should instead use value binding into prepared statements. To do so, put named placeholders in the query text, then pass an array of values to bind to the placeholders:
+Although Aura SQL provides quoting methods, you should instead use value
+binding into prepared statements. To do so, put named placeholders in the
+query text, then pass an array of values to bind to the placeholders:
<?php
// the text of the query
@@ -114,7 +132,9 @@ Aura SQL recognizes array values and quotes them as comma-separated lists:
Modifying Rows
--------------
-Aura SQL comes with three convenience methods for modifying data: `insert()`, `update()`, and `delete()`. You can also retrieve the last inserted ID using `lastInsertId()`.
+Aura SQL comes with three convenience methods for modifying data: `insert()`,
+`update()`, and `delete()`. You can also retrieve the last inserted ID using
+`lastInsertId()`.
First, to insert a row:
@@ -133,7 +153,9 @@ First, to insert a row:
// now get the last inserted ID
$id = $sql->lastInsertId();
-(N.b.: Because of the way PostgreSQL creates auto-incremented columns, the `pgsql` adapter needs to know the table and column name to get the last inserted ID; for example, `$id = $sql->lastInsertId($table, 'id');`.)
+(N.b.: Because of the way PostgreSQL creates auto-incremented columns, the
+`pgsql` adapter needs to know the table and column name to get the last
+inserted ID; for example, `$id = $sql->lastInsertId($table, 'id');`.)
Next, to update rows:
@@ -155,7 +177,9 @@ Next, to update rows:
// perform the update; result is number of rows affected
$result = $sql->update($table, $cols, $cond, $data);
-(N.b.: Both `$cols` and `$data` are bound into the update query, but `$cols` takes precedence. Be sure that the keys in `$cols` and `$data` do not conflict.)
+(N.b.: Both `$cols` and `$data` are bound into the update query, but `$cols`
+takes precedence. Be sure that the keys in `$cols` and `$data` do not
+conflict.)
Finally, to delete rows:
@@ -172,6 +196,7 @@ Finally, to delete rows:
// perform the deletion; result is number of rows affected
$result = $sql->delete($table, $cond, $data);
+
Retrieving Table Information
----------------------------
@@ -225,7 +250,10 @@ Each column description is a `Column` object with the following properties:
Transactions
------------
-Aura SQL adapters always start in autocommit mode (the same as PDO). However, you can turn off autocommit mode and start a transaction with `beginTransaction()`, then either `commit()` or `rollBack()` the transaction. Commits and rollbacks cause the adapter to go back into autocommit mode.
+Aura SQL adapters always start in autocommit mode (the same as PDO). However,
+you can turn off autocommit mode and start a transaction with
+`beginTransaction()`, then either `commit()` or `rollBack()` the transaction.
+Commits and rollbacks cause the adapter to go back into autocommit mode.
<?php
// turn off autocommit and start a transaction
@@ -246,14 +274,16 @@ Aura SQL adapters always start in autocommit mode (the same as PDO). However, yo
Manual Queries
--------------
-You can, of course, build and issue your own queries by hand. Use the `query()` method to do so:
+You can, of course, build and issue your own queries by hand. Use the
+`query()` method to do so:
<?php
$text = "SELECT * FROM foo WHERE id = :id";
$data = ['id' => 1];
$stmt = $sql->query($text, $data)
-The returned `$stmt` is a [PDOStatement](http://php.net/PDOStatement) that you may manipulate as you wish.
+The returned `$stmt` is a [PDOStatement](http://php.net/PDOStatement) that you
+may manipulate as you wish.
Profiling
---------
@@ -284,3 +314,140 @@ Each profile object has these properties:
- `trace`: (array) A [debug_backtrace](http://php.net/debug_backtrace) so
you can tell where the query came from.
+
+Query Objects
+=============
+
+Aura SQL provides four types of query objects so you can write your SQL
+queries in an object-oriented way.
+
+Select
+------
+
+To get a new `Select` object, invoke the `newSelect()` method on an adapter.
+You can then modify the `Select` object and pass it to the `query()` or
+`fetch*()` method.
+
+```php
+<?php
+// create a new Select object
+$select = $sql->newSelect();
+
+// SELECT * FROM foo WHERE bar > :bar ORDER BY baz
+$select->cols(['*'])
+ ->from('foo')
+ ->where('bar > :bar')
+ ->orderBy('baz');
+
+$data['foo' => '88'];
+
+$list = $sql->fetchAll($select, $data);
+```
+
+The `Select` object has these methods and more; please read the source code
+for more information.
+
+- `distinct()`: Set to `true` for a `SELECT DISTINCT`.
+
+- `cols()`: Select these columns.
+
+- `from()`: Select from these tables.
+
+- `join()`: Join these tables on specified conditions.
+
+- `where()`: `WHERE` these conditions are met (using `AND`).
+
+- `orWhere()`: `WHERE` these conditions are met (using `OR`).
+
+- `groupBy()`: `GROUP BY` these columns.
+
+- `having()`: `HAVING` these conditions met (using `AND`).
+
+- `orHaving()`: `HAVING` these conditions met (using `OR`).
+
+- `orderBy()`: `ORDER BY` these columns.
+
+- `limit()`: `LIMIT` to this many rows.
+
+- `offset()`: `OFFSET` by this many rows.
+
+- `union()`: `UNION` with a followup `SELECT`.
+
+- `unionAll()`: `UNION ALL` with a followup `SELECT`.
+
+Insert
+------
+
+To get a new `Insert` object, invoke the `newInsert()` method on an adapter.
+You can then modify the `Insert` object and pass it to the `query()` method.
+
+```php
+<?php
+// create a new Insert object
+$insert = $sql->newInsert();
+
+// INSERT INTO foo (bar, baz, date) VALUES (:foo, :bar, NOW());
+$insert->into('foo')
+ ->cols(['bar', 'baz'])
+ ->set('date', 'NOW()');
+
+$data[
+ 'foo' => null,
+ 'bar' => 'zim',
+];
+
+$stmt = $sql->query($insert, $data);
+```
+
+Update
+------
+
+To get a new `Update` object, invoke the `newUpdate()` method on an adapter.
+You can then modify the `Update` object and pass it to the `query()` method.
+
+```php
+<?php
+// create a new Update object
+$update = $sql->newUpdate();
+
+// UPDATE foo SET bar = :bar, baz = :baz, date = NOW() WHERE zim = :zim OR gir = :gir
+$update->table('foo')
+ ->cols(['bar', 'baz'])
+ ->set('date', 'NOW()')
+ ->where('zim = :zim')
+ ->orWhere('gir = :gir');
+
+$data[
+ 'foo' => null,
+ 'bar' => 'barbar',
+ 'baz' => 99,
+ 'zim' => 'dib',
+ 'gir' => 'doom',
+];
+
+$stmt = $sql->query($update, $data);
+```
+
+Delete
+------
+
+To get a new `Delete` object, invoke the `newDelete()` method on an adapter.
+You can then modify the `Delete` object and pass it to the `query()` method.
+
+```php
+<?php
+// create a new Delete object
+$delete = $sql->newDelete();
+
+// DELETE FROM WHERE zim = :zim OR gir = :gir
+$delete->from('foo')
+ ->where('zim = :zim')
+ ->orWhere('gir = :gir');
+
+$data[
+ 'zim' => 'dib',
+ 'gir' => 'doom',
+];
+
+$stmt = $sql->query($delete, $data);
+```
32 composer.json
View
@@ -1,7 +1,7 @@
{
- "name": "Aura/Sql",
+ "name": "aura/sql",
"type": "library",
- "description": "A wrapper around PDO that provides adapters and convenience methods for MySQL, PostgreSQL, SQLite, and SQL Server.",
+ "description": "The Aura Sql package is a wrapper around PDO that provides adapters and convenience methods for MySQL, PostgreSQL, SQLite, and SQL Server.",
"keywords": [
"mysql",
"pdo",
@@ -9,20 +9,36 @@
"postgres",
"postgresql",
"sqlite",
- "sql server",
- "sqlserver"
+ "sql server"
],
"homepage": "http://auraphp.github.com/Aura.Sql",
- "version": "1.0.0-dev",
+ "version": "1.0.0-beta3",
+ "time": "2012-07-30",
"license": "BSD",
"authors": [
{
- "name": "Aura Contributors",
- "homepage": "https://github.com/auraphp/Aura.Signal/contributors"
+ "name": "Aura.Sql Contributors",
+ "homepage": "https://github.com/auraphp/Aura.Sql/contributors"
+ },
+ {
+ "name": "Paul M. Jones",
+ "email": "pmjones88@gmail.com",
+ "homepage": "http://paul-m-jones.com"
+ },
+ {
+ "name": "Roy Gu",
+ "email": "cnwggu@gmail.com",
+ "homepage": null
}
],
"minimum-stability": "dev",
"require": {
- "php": ">=5.4.0"
+ "php": ">=5.4"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-0": {
+ "Aura\\Sql": "src/"
+ }
}
}
1  meta/authors.csv
View
@@ -1 +1,2 @@
lead,pmjones,Paul M. Jones,pmjones88@gmail.com,http://paul-m-jones.com
+developer,cnwggu,Roy Gu,cnwggu@gmail.com
23 meta/changes.txt
View
@@ -1 +1,22 @@
-Initial release (beta2 name notwithstanding).
+- [NEW] Select object and SelectFactory.
+
+- [ADD] AbstractAdapter::newSelect() to return a new Select object.
+
+- [CHG] AbstractAdapter::query() can now take a Select object directly.
+
+- [FIX] In ConnectionManager::getMaster() and getSlate(), use `=== null` when
+ comparing connection names; this allows integer zero keys in the pool
+ arrays.
+
+- [FIX] Profiler output now numbers queries correctly.
+
+- [ADD] Method Column::__set_state() to make it easier to var_export() a
+ Column object.
+
+- [CHG] In tests, you can now specify your own globals.php file to set local
+ database connection params.
+
+- [CHG] AbstractAdapter::update() $data values can now be literals instead
+ of just key-value pairs.
+
+- [CHG] PSR-1 and 2 compliance.
2  meta/require.csv
View
@@ -1 +1 @@
-php, >= 5.4
+php,>=5.4
10 src.php
View
@@ -13,5 +13,11 @@
require_once __DIR__ . '/src/Aura/Sql/Exception/NoSuchSlave.php';
require_once __DIR__ . '/src/Aura/Sql/ProfilerInterface.php';
require_once __DIR__ . '/src/Aura/Sql/Profiler.php';
-require_once __DIR__ . '/src/Aura/Sql/Select.php';
-require_once __DIR__ . '/src/Aura/Sql/SelectFactory.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/ValuesTrait.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/WhereTrait.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/AbstractQuery.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/Delete.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/Factory.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/Insert.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/Select.php';
+require_once __DIR__ . '/src/Aura/Sql/Query/Update.php';
327 src/Aura/Sql/Adapter/AbstractAdapter.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -10,8 +12,8 @@
use Aura\Sql\ColumnFactory;
use Aura\Sql\ProfilerInterface;
-use Aura\Sql\Select;
-use Aura\Sql\SelectFactory;
+use Aura\Sql\Query\AbstractQuery;
+use Aura\Sql\Query\Factory as QueryFactory;
use PDO;
use PDOStatement;
@@ -32,7 +34,7 @@
*
*/
protected $column_factory;
-
+
/**
*
* The PDO DSN for the connection. This can be an array of key-value pairs
@@ -42,7 +44,7 @@
*
*/
protected $dsn;
-
+
/**
*
* The PDO type prefix.
@@ -51,7 +53,7 @@
*
*/
protected $dsn_prefix;
-
+
/**
*
* PDO options for the connection.
@@ -60,7 +62,7 @@
*
*/
protected $options = [];
-
+
/**
*
* The password for the connection.
@@ -69,7 +71,7 @@
*
*/
protected $password;
-
+
/**
*
* The PDO connection object.
@@ -78,7 +80,7 @@
*
*/
protected $pdo;
-
+
/**
*
* The prefix to use when quoting identifier names.
@@ -87,7 +89,7 @@
*
*/
protected $quote_name_prefix;
-
+
/**
*
* The suffix to use when quoting identifier names.
@@ -96,7 +98,7 @@
*
*/
protected $quote_name_suffix;
-
+
/**
*
* The username for the connection.
@@ -105,11 +107,17 @@
*
*/
protected $username;
-
+
/**
*
* Constructor.
*
+ * @param ProfilerInterface $profiler A query profiler.
+ *
+ * @param ColumnFactory $column_factory A column object factory.
+ *
+ * @param QueryFactory $query_factory A query object factory.
+ *
* @param mixed $dsn DSN parameters for the PDO connection.
*
* @param string $username The username for the PDO connection.
@@ -122,7 +130,7 @@
public function __construct(
ProfilerInterface $profiler,
ColumnFactory $column_factory,
- SelectFactory $select_factory,
+ QueryFactory $query_factory,
$dsn,
$username = null,
$password = null,
@@ -130,13 +138,13 @@ public function __construct(
) {
$this->profiler = $profiler;
$this->column_factory = $column_factory;
- $this->select_factory = $select_factory;
+ $this->query_factory = $query_factory;
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->options = array_merge($this->options, $options);
}
-
+
/**
*
* Returns the profiler object.
@@ -148,7 +156,7 @@ public function getProfiler()
{
return $this->profiler;
}
-
+
/**
*
* Returns the column factory object.
@@ -160,19 +168,19 @@ public function getColumnFactory()
{
return $this->column_factory;
}
-
+
/**
*
- * Returns the select factory object.
+ * Returns the query factory object.
*
- * @return SelectFactory
+ * @return QueryFactory
*
*/
- public function getSelectFactory()
+ public function getQueryFactory()
{
- return $this->select_factory;
+ return $this->query_factory;
}
-
+
/**
*
* Returns the DSN string used by the PDO connection.
@@ -193,10 +201,10 @@ public function getDsnString()
} else {
$dsn_string = $this->dsn;
}
-
+
return "{$this->dsn_prefix}:{$dsn_string}";
}
-
+
/**
*
* Returns the PDO connection object; if it does not exist, creates it to
@@ -212,7 +220,7 @@ public function getPdo()
}
return $this->pdo;
}
-
+
/**
*
* Connects to the database by creating the PDO object.
@@ -226,7 +234,7 @@ public function connect()
$this->pdo = $this->newPdo();
$this->postConnect();
}
-
+
/**
*
* A hook that executes before the database connection is created.
@@ -237,7 +245,7 @@ public function connect()
public function preConnect()
{
}
-
+
/**
*
* A hook that executes after the database connection is created.
@@ -248,14 +256,14 @@ public function preConnect()
public function postConnect()
{
}
-
+
/**
*
* Prepares and executes an SQL query, optionally binding values
* to named placeholders in the query text.
*
- * @param string|Select $spec The text of the SQL query; or, a Select
- * object.
+ * @param string|AbstractQuery $query The text of the SQL query; or, a
+ * query object.
*
* @param array $data An associative array of data to bind to named
* placeholders in the query.
@@ -263,18 +271,14 @@ public function postConnect()
* @return PDOStatement
*
*/
- public function query($spec, array $data = [])
+ public function query($query, array $data = [])
{
- if ($spec instanceof Select) {
- $text = $spec->__toString();
- } else {
- $text = $spec;
- }
- $stmt = $this->prepare($text, $data);
+ // casts objects to string via __toString()
+ $stmt = $this->prepare((string) $query, $data);
$this->profiler->exec($stmt, $data);
return $stmt;
}
-
+
/**
*
* Begins a database transaction and turns off autocommit.
@@ -290,7 +294,7 @@ public function beginTransaction()
};
return $this->profiler->call($func, '__BEGIN_TRANSACTION__');
}
-
+
/**
*
* Commits the current database transaction and turns autocommit back on.
@@ -306,7 +310,7 @@ public function commit()
};
return $this->profiler->call($func, '__COMMIT__');
}
-
+
/**
*
* Rolls back the current database transaction and turns autocommit back
@@ -323,7 +327,7 @@ public function rollback()
};
return $this->profiler->call($func, '__ROLLBACK__');
}
-
+
/**
*
* Creates a prepared PDOStatment and binds data values to placeholders.
@@ -348,15 +352,15 @@ public function prepare($text, array $data)
{
// need the PDO object regardless
$pdo = $this->getPdo();
-
+
// was data passed for binding?
if (! $data) {
return $pdo->prepare($text);
}
-
+
// a list of placeholders to bind at the end
$bind = array();
-
+
// find all text parts not inside quotes or backslashed-quotes
$apos = "'";
$quot = '"';
@@ -366,21 +370,21 @@ public function prepare($text, array $data)
-1,
PREG_SPLIT_DELIM_CAPTURE
);
-
+
// loop through the non-quoted parts (0, 3, 6, 9, etc.)
$k = count($parts);
for ($i = 0; $i <= $k; $i += 3) {
-
+
// get the part as a reference so it can be modified in place
$part =& $parts[$i];
-
+
// find all :placeholder matches in the part
preg_match_all(
"/\W:([a-zA-Z_][a-zA-Z0-9_]*)/m",
$part . PHP_EOL,
$matches
);
-
+
// for each of the :placeholder matches ...
foreach ($matches[1] as $key) {
// is the corresponding data element an array?
@@ -396,22 +400,22 @@ public function prepare($text, array $data)
}
}
}
-
+
// bring the parts back together in case they were modified
$text = implode('', $parts);
-
+
// prepare the statement
$stmt = $pdo->prepare($text);
-
+
// for the placeholders we found, bind the corresponding data values
foreach ($bind as $key) {
$stmt->bindValue($key, $data[$key]);
}
-
+
// done!
return $stmt;
}
-
+
/**
*
* Fetches all rows from the database using sequential keys.
@@ -430,7 +434,7 @@ public function fetchAll($text, $data = [])
$stmt = $this->query($text, $data);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
-
+
/**
*
* Fetches all rows from the database using associative keys (defined by
@@ -458,7 +462,7 @@ public function fetchAssoc($text, array $data = [])
}
return $data;
}
-
+
/**
*
* Fetches the first column of all rows as a sequential array.
@@ -477,7 +481,7 @@ public function fetchCol($text, array $data = [])
$stmt = $this->query($text, $data);
return $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
}
-
+
/**
*
* Fetches the very first value (i.e., first column of the first row).
@@ -496,7 +500,7 @@ public function fetchValue($text, array $data = [])
$stmt = $this->query($text, $data);
return $stmt->fetchColumn(0);
}
-
+
/**
*
* Fetches an associative array of all rows as key-value pairs (first
@@ -520,7 +524,7 @@ public function fetchPairs($text, array $data = [])
}
return $data;
}
-
+
/**
*
* Fetches one row from the database.
@@ -539,7 +543,7 @@ public function fetchOne($text, array $data = [])
$stmt = $this->query($text, $data);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
-
+
/**
*
* Safely quotes a value for an SQL statement.
@@ -570,7 +574,7 @@ public function quote($val)
return $pdo->quote($val);
}
}
-
+
/**
*
* Quotes a value and places into a piece of text at a placeholder; the
@@ -594,36 +598,36 @@ public function quoteInto($text, $data)
// no replacements needed
return $text;
}
-
+
// only one placeholder?
if ($count == 1) {
$data = $this->quote($data);
$text = str_replace('?', $data, $text);
return $text;
}
-
+
// more than one placeholder
$offset = 0;
foreach ((array) $data as $val) {
-
+
// find the next placeholder
$pos = strpos($text, '?', $offset);
if ($pos === false) {
// no more placeholders, exit the data loop
break;
}
-
+
// replace this question mark with a quoted value
$val = $this->quote($val);
$text = substr_replace($text, $val, $pos, 1);
-
+
// update the offset to move us past the quoted value
$offset = $pos + strlen($val);
}
-
+
return $text;
}
-
+
/**
*
* Quote multiple text-and-value pieces.
@@ -667,14 +671,14 @@ public function quoteMulti($list, $sep)
} else {
// string $key means a phrase with a placeholder, and
// $val should be bound into it.
- $text[] = $this->quoteInto($key, $val);
+ $text[] = $this->quoteInto($key, $val);
}
}
-
+
// return the condition list
return implode($sep, $text);
}
-
+
/**
*
* Quotes a single identifier name (table, table alias, table column,
@@ -700,7 +704,7 @@ public function quoteName($spec)
{
// remove extraneous spaces
$spec = trim($spec);
-
+
// `original` AS `alias` ... note the 'rr' in strripos
$pos = strripos($spec, ' AS ');
if ($pos) {
@@ -711,7 +715,7 @@ public function quoteName($spec)
// done
return "$orig AS $alias";
}
-
+
// `original` `alias`
$pos = strrpos($spec, ' ');
if ($pos) {
@@ -722,7 +726,7 @@ public function quoteName($spec)
// done
return "$orig $alias";
}
-
+
// `table`.`column`
$pos = strrpos($spec, '.');
if ($pos) {
@@ -731,11 +735,11 @@ public function quoteName($spec)
$col = $this->replaceName(substr($spec, $pos + 1));
return "$table.$col";
}
-
+
// `name`
return $this->replaceName($spec);
}
-
+
/**
*
* Quotes all fully-qualified identifier names ("table.col") in a string,
@@ -759,7 +763,7 @@ public function quoteNamesIn($text)
// single and double quotes
$apos = "'";
$quot = '"';
-
+
// look for ', ", \', or \" in the string.
// match closing quotes against the same number of opening quotes.
$list = preg_split(
@@ -768,12 +772,12 @@ public function quoteNamesIn($text)
-1,
PREG_SPLIT_DELIM_CAPTURE
);
-
+
// concat the pieces back together, quoting names as we go.
$text = null;
$last = count($list) - 1;
foreach ($list as $key => $val) {
-
+
// skip elements 2, 5, 8, 11, etc. as artifacts of the back-
// referenced split; these are the trailing/ending quote
// portions, and already included in the previous element.
@@ -781,11 +785,11 @@ public function quoteNamesIn($text)
if (($key+1) % 3 == 0) {
continue;
}
-
+
// is there an apos or quot anywhere in the part?
$is_string = strpos($val, $apos) !== false ||
strpos($val, $quot) !== false;
-
+
if ($is_string) {
// string literal
$text .= $val;
@@ -801,16 +805,16 @@ public function quoteNamesIn($text)
$val = substr($val, 0, $pos) . " AS $alias";
}
}
-
+
// now quote names in the language.
$text .= $this->replaceNamesIn($val);
}
}
-
+
// done!
return $text;
}
-
+
/**
*
* Inserts a row of data into a table.
@@ -825,29 +829,13 @@ public function quoteNamesIn($text)
*/
public function insert($table, array $cols)
{
- // the base command text
- $text = 'INSERT INTO ' . $this->quoteName($table);
-
- // col names
- $keys = array_keys($cols);
-
- // quote the col names for a list
- $names = [];
- foreach ($keys as $key) {
- $names[] = $this->quoteName($key);
- }
-
- // add quoted names as a comma-separated list
- $text .= '(' . implode(', ', $names) . ') ';
-
- // add value placeholders (use unquoted key names)
- $text .= 'VALUES (:' . implode(', :', $keys) . ')';
-
- // execute the statement
- $stmt = $this->query($text, $cols);
+ $insert = $this->newInsert();
+ $insert->into($table);
+ $insert->cols(array_keys($cols));
+ $stmt = $this->query($insert, $cols);
return $stmt->rowCount();
}
-
+
/**
*
* Updates a table with specified data based on WHERE conditions.
@@ -859,42 +847,26 @@ public function insert($table, array $cols)
*
* @param string $cond Conditions for a WHERE clause.
*
- * @param array $data Additional data to bind to the query; note that the
- * $cols values will take precedence over these additional values.
+ * @param array $data Additional data to bind to the query; these are not
+ * part of the update, and note that the $cols values will take precedence
+ * over these additional values.
*
* @return int The number of rows affected.
*
*/
public function update($table, array $cols, $cond, array $data = [])
{
- // the base command text
- $text = 'UPDATE ' . $this->quoteName($table) . ' SET ';
-
- // add "col = :col" pairs to the statement
- $list = [];
- foreach ($cols as $col => $val) {
- if (is_int($col)) {
- $list[] = $this->quoteNamesIn($val);
- } else {
- $list[] = $this->quoteName($col) . " = :$col";
- }
- }
- $text .= implode(', ', $list);
-
- // add the where clause
+ $update = $this->newUpdate();
+ $update->table($table);
+ $update->cols(array_keys($cols));
if ($cond) {
- $text .= ' WHERE ' . $this->quoteNamesIn($cond);
+ $update->where($cond);
}
-
- // merge cols and extra data. note that the cols take precedence over
- // the extra data.
$data = array_merge($data, $cols);
-
- // execute the statement
- $stmt = $this->query($text, $data);
+ $stmt = $this->query($update, $data);
return $stmt->rowCount();
}
-
+
/**
*
* Deletes rows from the table based on WHERE conditions.
@@ -910,23 +882,63 @@ public function update($table, array $cols, $cond, array $data = [])
*/
public function delete($table, $cond, array $data = [])
{
- // the base command text
- $text = 'DELETE FROM ' . $this->quoteName($table);
-
- // add the where clause
+ $delete = $this->newDelete();
+ $delete->from($table);
if ($cond) {
- $text .= ' WHERE ' . $this->quoteNamesIn($cond);
+ $delete->where($cond);
}
-
- $stmt = $this->query($text, $data);
+ $stmt = $this->query($delete, $data);
return $stmt->rowCount();
}
-
+
+ /**
+ *
+ * Returns a new Select object.
+ *
+ * @return Select
+ *
+ */
public function newSelect()
{
- return $this->select_factory->newInstance($this);
+ return $this->query_factory->newInstance('select', $this);
+ }
+
+ /**
+ *
+ * Returns a new Insert object.
+ *
+ * @return Insert
+ *
+ */
+ public function newInsert()
+ {
+ return $this->query_factory->newInstance('insert', $this);
}
-
+
+ /**
+ *
+ * Returns a new Update object.
+ *
+ * @return Update
+ *
+ */
+ public function newUpdate()
+ {
+ return $this->query_factory->newInstance('update', $this);
+ }
+
+ /**
+ *
+ * Returns a new Delete object.
+ *
+ * @return Update
+ *
+ */
+ public function newDelete()
+ {
+ return $this->query_factory->newInstance('delete', $this);
+ }
+
/**
*
* Modifies an SQL string **in place** to add a `LIMIT ... OFFSET` clause.
@@ -944,7 +956,7 @@ public function limit(&$text, $count, $offset = 0)
{
$count = (int) $count;
$offset = (int) $offset;
-
+
if ($count && $offset) {
$text .= "LIMIT $count OFFSET $offset" . PHP_EOL;
} elseif ($count) {
@@ -953,7 +965,7 @@ public function limit(&$text, $count, $offset = 0)
$text .= "OFFSET $offset" . PHP_EOL;
}
}
-
+
/**
*
* Creates a new PDO object.
@@ -964,15 +976,15 @@ public function limit(&$text, $count, $offset = 0)
protected function newPdo()
{
$pdo = new PDO(
- $this->getDsnString(),
- $this->username,
- $this->password,
+ $this->getDsnString(),
+ $this->username,
+ $this->password,
$this->options
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
-
+
/**
*
* Quotes an identifier name (table, index, etc); ignores empty values and
@@ -996,7 +1008,7 @@ protected function replaceName($name)
. $this->quote_name_suffix;
}
}
-
+
/**
*
* Quotes all fully-qualified identifier names ("table.col") in a string.
@@ -1012,9 +1024,9 @@ protected function replaceName($name)
protected function replaceNamesIn($text)
{
$word = "[a-z_][a-z0-9_]+";
-
+
$find = "/(\\b)($word)\\.($word)(\\b)/i";
-
+
$repl = '$1'
. $this->quote_name_prefix
. '$2'
@@ -1025,12 +1037,12 @@ protected function replaceNamesIn($text)
. $this->quote_name_suffix
. '$4'
;
-
+
$text = preg_replace($find, $repl, $text);
-
+
return $text;
}
-
+
/**
*
* Given a column specification, parse into datatype, size, and
@@ -1048,7 +1060,7 @@ protected function getTypeSizeScope($spec)
$type = null;
$size = null;
$scale = null;
-
+
// find the parens, if any
$pos = strpos($spec, '(');
if ($pos === false) {
@@ -1057,11 +1069,11 @@ protected function getTypeSizeScope($spec)
} else {
// find the type first.
$type = substr($spec, 0, $pos);
-
+
// there were parens, so there's at least a size.
// remove parens to get the size.
$size = trim(substr($spec, $pos), '()');
-
+
// a comma in the size indicates a scale.
$pos = strpos($size, ',');
if ($pos !== false) {
@@ -1069,10 +1081,10 @@ protected function getTypeSizeScope($spec)
$size = substr($size, 0, $pos);
}
}
-
+
return [$type, $size, $scale];
}
-
+
/**
*
* Returns an list of tables in the database.
@@ -1084,7 +1096,7 @@ protected function getTypeSizeScope($spec)
*
*/
abstract public function fetchTableList($schema = null);
-
+
/**
*
* Returns an array of columns in a table.
@@ -1097,7 +1109,7 @@ protected function getTypeSizeScope($spec)
*
*/
abstract public function fetchTableCols($spec);
-
+
/**
*
* Splits an identifier name into two parts, based on the location of the
@@ -1120,3 +1132,4 @@ protected function splitName($name)
}
}
}
+
33 src/Aura/Sql/Adapter/Mysql.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -32,7 +34,7 @@ class Mysql extends AbstractAdapter
'unix_socket' => null,
'charset' => null,
];
-
+
/**
*
* The PDO type prefix.
@@ -41,7 +43,7 @@ class Mysql extends AbstractAdapter
*
*/
protected $dsn_prefix = 'mysql';
-
+
/**
*
* The prefix to use when quoting identifier names.
@@ -50,7 +52,7 @@ class Mysql extends AbstractAdapter
*
*/
protected $quote_name_prefix = '`';
-
+
/**
*
* The suffix to use when quoting identifier names.
@@ -59,7 +61,7 @@ class Mysql extends AbstractAdapter
*
*/
protected $quote_name_suffix = '`';
-
+
/**
*
* Returns an list of tables in the database.
@@ -78,7 +80,7 @@ public function fetchTableList($schema = null)
}
return $this->fetchCol($text);
}
-
+
/**
*
* Returns an array of columns in a table.
@@ -93,28 +95,28 @@ public function fetchTableList($schema = null)
public function fetchTableCols($spec)
{
list($schema, $table) = $this->splitName($spec);
-
+
$table = $this->quoteName($table);
$text = "SHOW COLUMNS FROM $table";
-
+
if ($schema) {
$schema = preg_replace('/[^\w]/', '', $schema);
$schema = $this->replaceName($schema);
$text .= " IN $schema";
}
-
+
// get the column descriptions
$raw_cols = $this->fetchAll($text);
-
+
// where the column info will be stored
$cols = [];
-
+
// loop through the result rows; each describes a column.
foreach ($raw_cols as $val) {
-
+
$name = $val['Field'];
list($type, $size, $scale) = $this->getTypeSizeScope($val['Type']);
-
+
// save the column description
$cols[$name] = $this->column_factory->newInstance(
$name,
@@ -127,11 +129,11 @@ public function fetchTableCols($spec)
(bool) ($val['Key'] == 'PRI')
);
}
-
+
// done!
return $cols;
}
-
+
/**
*
* A helper method to get the default value for a column.
@@ -152,7 +154,7 @@ protected function getDefault($default)
return $default;
}
}
-
+
/**
*
* Returns the last ID inserted on the connection.
@@ -166,3 +168,4 @@ public function lastInsertId()
return $pdo->lastInsertId();
}
}
+
37 src/Aura/Sql/Adapter/Pgsql.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -32,7 +34,7 @@ class Pgsql extends AbstractAdapter
'user' => null,
'password' => null,
];
-
+
/**
*
* The PDO type prefix.
@@ -41,7 +43,7 @@ class Pgsql extends AbstractAdapter
*
*/
protected $dsn_prefix = 'pgsql';
-
+
/**
*
* The prefix to use when quoting identifier names.
@@ -50,7 +52,7 @@ class Pgsql extends AbstractAdapter
*
*/
protected $quote_name_prefix = '"';
-
+
/**
*
* The suffix to use when quoting identifier names.
@@ -59,7 +61,7 @@ class Pgsql extends AbstractAdapter
*
*/
protected $quote_name_suffix = '"';
-
+
/**
*
* Returns a list of all tables in the database.
@@ -86,10 +88,10 @@ public function fetchTableList($schema = null)
AND table_schema != 'information_schema'
";
}
-
+
return $this->fetchCol($cmd, array('schema' => $schema));
}
-
+
/**
*
* Returns an array of columns in a table.
@@ -104,7 +106,7 @@ public function fetchTableList($schema = null)
public function fetchTableCols($spec)
{
list($schema, $table) = $this->splitName($spec);
-
+
// modified from Zend_Db_Adapter_Pdo_Pgsql
$cmd = "
SELECT
@@ -123,22 +125,22 @@ public function fetchTableCols($spec)
ON (d.adrelid = c.oid AND d.adnum = a.attnum)
WHERE a.attnum > 0 AND c.relname = :table
";
-
+
if ($schema) {
$cmd .= " AND n.nspname = :schema";
}
-
+
$cmd .= "\n ORDER BY a.attnum";
-
+
// where the columns are stored
$cols = array();
-
+
// get the column descriptions
$raw_cols = $this->fetchAll($cmd, array(
'table' => $table,
'schema' => $schema,
));
-
+
// loop through the result rows; each describes a column.
foreach ($raw_cols as $val) {
$name = $val['name'];
@@ -154,11 +156,11 @@ public function fetchTableCols($spec)
(bool) ($val['primary'])
);
}
-
+
// done
return $cols;
}
-
+
/**
*
* Given a native column SQL default value, finds a PHP literal value.
@@ -177,7 +179,7 @@ protected function getDefault($default)
if (is_numeric($default)) {
return $default;
}
-
+
// string literal?
$k = substr($default, 0, 1);
if ($k == '"' || $k == "'") {
@@ -186,11 +188,11 @@ protected function getDefault($default)
// also remove the leading and trailing quotes
return substr($default, 1, $pos-2);
}
-
+
// null or non-literal
return null;
}
-
+
/**
*
* Returns the last ID inserted on the connection for a given table
@@ -214,3 +216,4 @@ public function lastInsertId($table, $col)
return $pdo->lastInsertId($name);
}
}
+
67 src/Aura/Sql/Adapter/Sqlite.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -27,7 +29,7 @@ class Sqlite extends AbstractAdapter
*
*/
protected $autoinc_string = 'INTEGER PRIMARY KEY AUTOINCREMENT';
-
+
/**
*
* The PDO DSN for the connection, typically a file path.
@@ -36,7 +38,7 @@ class Sqlite extends AbstractAdapter
*
*/
protected $dsn = null;
-
+
/**
*
* The PDO type prefix.
@@ -45,7 +47,7 @@ class Sqlite extends AbstractAdapter
*
*/
protected $dsn_prefix = 'sqlite';
-
+
/**
*
* The quote character before an entity name (table, index, etc).
@@ -54,7 +56,7 @@ class Sqlite extends AbstractAdapter
*
*/
protected $quote_name_prefix = '"';
-
+
/**
*
* The quote character after an entity name (table, index, etc).
@@ -63,7 +65,7 @@ class Sqlite extends AbstractAdapter
*
*/
protected $quote_name_suffix = '"';
-
+
/**
*
* Returns a list of tables in the database.
@@ -89,10 +91,10 @@ public function fetchTableList($schema = null)
ORDER BY name
";
}
-
+
return $this->fetchCol($cmd);
}
-
+
/**
*
* Describes the columns in a table.
@@ -107,51 +109,51 @@ public function fetchTableList($schema = null)
public function fetchTableCols($spec)
{
list($schema, $table) = $this->splitName($spec);
-
+
// strip non-word characters to try and prevent SQL injections
$table = preg_replace('/[^\w]/', '', $table);
-
+
// is there a schema?
if ($schema) {
// sanitize and add a dot
$schema = preg_replace('/[^\w]/', '', $schema) . '.';
}
-
+
// where the description will be stored
$cols = array();
-
+
// get the CREATE TABLE sql; need this for finding autoincrement cols
$cmd = "
SELECT sql FROM {$schema}sqlite_master
WHERE type = 'table' AND name = :table
";
$create_table = $this->fetchValue($cmd, array('table' => $table));
-
+
// get the column descriptions
$table = $this->quoteName($table);
$raw_cols = $this->fetchAll("PRAGMA {$schema}TABLE_INFO($table)");
-
+
// loop through the result rows; each describes a column.
foreach ($raw_cols as $val) {
$name = $val['name'];
list($type, $size, $scale) = $this->getTypeSizeScope($val['type']);
-
+
// find autoincrement column in CREATE TABLE sql.
$autoinc_find = str_replace(' ', '\s+', $this->autoinc_string);
- $find = "(\"$name\"|\'$name\'|`$name`|\[$name\]|\\b$name)"
+ $find = "(\"$name\"|\'$name\'|`$name`|\[$name\]|\\b$name)"
. "\s+$autoinc_find";
-
+
$autoinc = preg_match(
"/$find/Ui",
$create_table,
$matches
);
-
+
$default = null;
if ($val['dflt_value'] && $val['dflt_value'] != 'NULL') {
$default = trim($val['dflt_value'], "'");
}
-
+
$cols[$name] = array(
'name' => $name,
'type' => $type,
@@ -163,50 +165,50 @@ public function fetchTableCols($spec)
'autoinc' => (bool) $autoinc,
);
}
-
+
// For defaults using keywords, SQLite always reports the keyword
// *value*, not the keyword itself (e.g., '2007-03-07' instead of
// 'CURRENT_DATE').
- //
+ //
// The allowed keywords are CURRENT_DATE, CURRENT_TIME, and
// CURRENT_TIMESTAMP.
- //
+ //
// <http://www.sqlite.org/lang_createtable.html>
- //
+ //
// Check the table-creation SQL for the default value to see if it's
// a keyword and report 'null' in those cases.
-
+
// get the list of column names
$names = array_keys($cols);
-
+
// how many are there?
$last = count($names) - 1;
-
+
// loop through each column and find out if its default is a keyword
foreach ($names as $curr => $name) {
-
+
// if there is a default value ...
if ($cols[$name]['default']) {
-
+
// look for :curr_col :curr_type . DEFAULT CURRENT_(*)
$find = $cols[$name]['name'] . '\s+'
. $cols[$name]['type']
. '.*\s+DEFAULT\s+CURRENT_';
-
+
// if not at the end, don't look further than the next coldef
if ($curr < $last) {
$next = $names[$curr + 1];
$find .= '.*' . $cols[$next]['name'] . '\s+'
. $cols[$next]['type'];
}
-
+
// is the default a keyword?
preg_match("/$find/ims", $create_table, $matches);
if (! empty($matches)) {
$cols[$name]['default'] = null;
}
}
-
+
// convert to a column object
$cols[$name] = $this->column_factory->newInstance(
$cols[$name]['name'],
@@ -219,11 +221,11 @@ public function fetchTableCols($spec)
$cols[$name]['primary']
);
}
-
+
// done!
return $cols;
}
-
+
/**
*
* Returns the last ID inserted on the connection.
@@ -237,3 +239,4 @@ public function lastInsertId()
return $pdo->lastInsertId();
}
}
+
31 src/Aura/Sql/Adapter/Sqlsrv.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -29,7 +31,7 @@ class Sqlsrv extends AbstractAdapter
'Server' => null,
'Database' => null,
];
-
+
/**
*
* The PDO type prefix.
@@ -38,7 +40,7 @@ class Sqlsrv extends AbstractAdapter
*
*/
protected $dsn_prefix = 'sqlsrv';
-
+
/**
*
* The prefix to use when quoting identifier names.
@@ -47,7 +49,7 @@ class Sqlsrv extends AbstractAdapter
*
*/
protected $quote_name_prefix = '[';
-
+
/**
*
* The suffix to use when quoting identifier names.
@@ -56,7 +58,7 @@ class Sqlsrv extends AbstractAdapter
*
*/
protected $quote_name_suffix = ']';
-
+
/**
*
* Returns a list of all tables in the database.
@@ -74,7 +76,7 @@ public function fetchTableList($schema = null)
$text = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
return $this->fetchCol($text);
}
-
+
/**
*
* Returns an array of columns in a table.
@@ -91,11 +93,11 @@ public function fetchTableList($schema = null)
public function fetchTableCols($spec)
{
list($schema, $table) = $this->splitIdent($spec);
-
+
// get column info
$text = "exec sp_columns @table_name = " . $this->quoteName($table);
$raw_cols = $this->fetchAll($text);
-
+
// get primary key info
$text = "exec sp_pkeys @table_owner = " . $raw_cols[0]['TABLE_OWNER']
. ", @table_name = " . $this->quoteName($table);
@@ -104,19 +106,19 @@ public function fetchTableCols($spec)
foreach ($raw_keys as $row) {
$keys[] = $row['COLUMN_NAME'];
}
-
+
$cols = [];
foreach ($raw_cols as $row) {
-
+
$name = $row['COLUMN_NAME'];
-
+
$pos = strpos($row['TYPE_NAME'], ' ');
if ($pos === false) {
$type = $row['TYPE_NAME'];
} else {
$type = substr($row['TYPE_NAME'], 0, $pos);
}
-
+
// save the column description
$cols[$name] = $this->column_factory->newInstance(
$name,
@@ -129,10 +131,10 @@ public function fetchTableCols($spec)
in_array($name, $keys)
);
}
-
+
return $cols;
}
-
+
/**
*
* Modifies an SQL string **in place** to add a `TOP` or
@@ -151,7 +153,7 @@ public function limit(&$text, $count, $offset = 0)
{
$count = (int) $count;
$offset = (int) $offset;
-
+
if ($count && ! $offset) {
// count, but no offset, so we can use TOP
$text = preg_replace('/^(SELECT( DISTINCT)?)/', "$1 TOP $count", $text);
@@ -162,3 +164,4 @@ public function limit(&$text, $count, $offset = 0)
}
}
}
+
13 src/Aura/Sql/AdapterFactory.php
View
@@ -3,11 +3,15 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
namespace Aura\Sql;
+use Aura\Sql\Query\Factory as QueryFactory;
+
/**
*
* A factory for adapter objects.
@@ -29,7 +33,7 @@ class AdapterFactory
'pgsql' => 'Aura\Sql\Adapter\Pgsql',
'sqlite' => 'Aura\Sql\Adapter\Sqlite',
];
-
+
/**
*
* Constructor.
@@ -41,7 +45,7 @@ public function __construct(array $map = [])
{
$this->map = array_merge($this->map, $map);
}
-
+
/**
*
* Returns a new adapter instance.
@@ -69,11 +73,11 @@ public function newInstance(
$class = $this->map[$name];
$profiler = new Profiler;
$column_factory = new ColumnFactory;
- $select_factory = new SelectFactory;
+ $query_factory = new QueryFactory;
return new $class(
$profiler,
$column_factory,
- $select_factory,
+ $query_factory,
$dsn,
$username,
$password,
@@ -81,3 +85,4 @@ public function newInstance(
);
}
}
+
34 src/Aura/Sql/Column.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -25,7 +27,7 @@ class Column
*
*/
protected $name;
-
+
/**
*
* The datatype of the column.
@@ -33,8 +35,8 @@ class Column
* @var string
*
*/
- protected $type;
-
+ protected $type;
+
/**
*
* The size of the column; typically, this is a number of bytes or
@@ -44,7 +46,7 @@ class Column
*
*/
protected $size;
-
+
/**
*
* The scale of the column (i.e., the number of decimal places).
@@ -53,7 +55,7 @@ class Column
*
*/
protected $scale;
-
+
/**
*
* Is the column marked as `NOT NULL`?
@@ -62,7 +64,7 @@ class Column
*
*/
protected $notnull;
-
+
/**
*
* The default value of the column.
@@ -71,7 +73,7 @@ class Column
*
*/
protected $default;
-
+
/**
*
* Is the column auto-incremented?
@@ -80,7 +82,7 @@ class Column
*
*/
protected $autoinc;
-
+
/**
*
* Is the column part of the primary key?
@@ -89,7 +91,7 @@ class Column
*
*/
protected $primary;
-
+
/**
*
* Constructor.
@@ -103,6 +105,9 @@ class Column
* @param int $scale The scale of the column (i.e., the number of digits
* after the decimal point).
*
+ * @param bool $notnull Is the column defined as NOT NULL (i.e.,
+ * required) ?
+ *
* @param mixed $default The default value of the column.
*
* @param bool $autoinc Is the column auto-incremented?
@@ -112,7 +117,7 @@ class Column
*/
public function __construct(
$name,
- $type,
+ $type,
$size,
$scale,
$notnull,
@@ -121,7 +126,7 @@ public function __construct(
$primary
) {
$this->name = $name;
- $this->type = $type;
+ $this->type = $type;
$this->size = $size;
$this->scale = $scale;
$this->notnull = (bool) $notnull;
@@ -129,7 +134,7 @@ public function __construct(
$this->autoinc = (bool) $autoinc;
$this->primary = (bool) $primary;
}
-
+
/**
*
* Returns property values.
@@ -160,7 +165,7 @@ public function __get($key)
* @return object \Aura\Sql\Column.
*
*/
- public static function __set_state($array)
+ public static function __set_state($array)
{
$column = new \Aura\Sql\Column(
$array['name'],
@@ -172,7 +177,8 @@ public static function __set_state($array)
$array['autoinc'],
$array['primary']
);
-
+
return $column;
}
}
+
10 src/Aura/Sql/ColumnFactory.php
View
@@ -3,6 +3,8 @@
*
* This file is part of the Aura Project for PHP.
*
+ * @package Aura.Sql
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
*/
@@ -30,6 +32,9 @@ class ColumnFactory
* @param int $scale The scale of the column (i.e., the number of digits
* after the decimal point).
*
+ * @param bool $notnull Is the column defined as NOT NULL (i.e.,