diff --git a/doc/book/zend.db.adapter.md b/doc/book/zend.db.adapter.md
new file mode 100644
index 0000000000..075c498f8b
--- /dev/null
+++ b/doc/book/zend.db.adapter.md
@@ -0,0 +1,389 @@
+# Zend\\Db\\Adapter
+
+The Adapter object is the most important sub-component of `Zend\Db`. It is responsible for adapting
+any code written in or for Zend\\Db to the targeted php extensions and vendor databases. In doing
+this, it creates an abstraction layer for the PHP extensions, which is called the "Driver" portion
+of the `Zend\Db` adapter. It also creates a lightweight abstraction layer, called the "Platform"
+portion of the adapter, for the various idiosyncrasies that each vendor-specific platform might have
+in its SQL/RDBMS implementation.
+
+## Creating an Adapter - Quickstart
+
+Creating an adapter can simply be done by instantiating the `Zend\Db\Adapter\Adapter` class. The
+most common use case, while not the most explicit, is to pass an array of configuration to the
+`Adapter`.
+
+```php
+$adapter = new Zend\Db\Adapter\Adapter($configArray);
+```
+
+This driver array is an abstraction for the extension level required parameters. Here is a table for
+the key-value pairs that should be in configuration array.
+
+> ## Note
+Other names will work as well. Effectively, if the PHP manual uses a particular naming, this naming
+will be supported by our Driver. For example, dbname in most cases will also work for 'database'.
+Another example is that in the case of Sqlsrv, UID will work in place of username. Which format you
+chose is up to you, but the above table represents the official abstraction names.
+
+So, for example, a MySQL connection using ext/mysqli:
+
+```php
+$adapter = new Zend\Db\Adapter\Adapter(array(
+ 'driver' => 'Mysqli',
+ 'database' => 'zend_db_example',
+ 'username' => 'developer',
+ 'password' => 'developer-password'
+));
+```
+
+Another example, of a Sqlite connection via PDO:
+
+```php
+$adapter = new Zend\Db\Adapter\Adapter(array(
+ 'driver' => 'Pdo_Sqlite',
+ 'database' => 'path/to/sqlite.db'
+));
+```
+
+It is important to know that by using this style of adapter creation, the `Adapter` will attempt to
+create any dependencies that were not explicitly provided. A Driver object will be created from the
+configuration array provided in the constructor. A Platform object will be created based off the
+type of Driver class that was instantiated. And lastly, a default ResultSet object is created and
+utilized. Any of these objects can be injected, to do this, see the next section.
+
+The list of officially supported drivers:
+
+- `Mysqli`: The ext/mysqli driver
+- `Pgsql`: The ext/pgsql driver
+- `Sqlsrv`: The ext/sqlsrv driver (from Microsoft)
+- `Pdo_Mysql`: MySQL through the PDO extension
+- `Pdo_Sqlite`: SQLite though the PDO extension
+- `Pdo_Pgsql`: PostgreSQL through the PDO extension
+
+## Creating an Adapter Using Dependency Injection
+
+The more expressive and explicit way of creating an adapter is by injecting all your dependencies up
+front. `Zend\Db\Adapter\Adapter` uses constructor injection, and all required dependencies are
+injected through the constructor, which has the following signature (in pseudo-code):
+
+```php
+use Zend\Db\Adapter\Platform\PlatformInterface;
+use Zend\Db\ResultSet\ResultSet;
+
+class Zend\Db\Adapter\Adapter {
+ public function __construct($driver, PlatformInterface $platform = null, ResultSet
+$queryResultSetPrototype = null)
+}
+```
+
+What can be injected:
+
+- $driver - an array of connection parameters (see above) or an instance of
+`Zend\Db\Adapter\Driver\DriverInterface`
+- $platform - (optional) an instance of `Zend\Db\Platform\PlatformInterface`, the default will be
+created based off the driver implementation
+- $queryResultSetPrototype - (optional) an instance of `Zend\Db\ResultSet\ResultSet`, to understand
+this object's role, see the section below on querying through the adapter
+
+## Query Preparation Through Zend\\Db\\Adapter\\Adapter::query()
+
+By default, query() prefers that you use "preparation" as a means for processing SQL statements.
+This generally means that you will supply a SQL statement with the values substituted by
+placeholders, and then the parameters for those placeholders are supplied separately. An example of
+this workflow with `Zend\Db\Adapter\Adapter` is:
+
+```php
+$adapter->query('SELECT * FROM `artist` WHERE `id` = ?', array(5));
+```
+
+The above example will go through the following steps:
+
+- create a new Statement object
+- prepare an array into a ParameterContainer if necessary
+- inject the ParameterContainer into the Statement object
+- execute the Statement object, producing a Result object
+- check the Result object to check if the supplied sql was a "query", or a result set producing
+statement
+- if it is a result set producing query, clone the ResultSet prototype, inject Result as datasource,
+return it
+- else, return the Result
+
+## Query Execution Through Zend\\Db\\Adapter\\Adapter::query()
+
+In some cases, you have to execute statements directly. The primary purpose for needing to execute
+sql instead of prepare and execute a sql statement, might be because you are attempting to execute a
+DDL statement (which in most extensions and vendor platforms), are un-preparable. An example of
+executing:
+
+```php
+$adapter->query('ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)',
+Adapter::QUERY_MODE_EXECUTE);
+```
+
+The primary difference to notice is that you must provide the Adapter::QUERY\_MODE\_EXECUTE
+(execute) as the second parameter.
+
+## Creating Statements
+
+While query() is highly useful for one-off and quick querying of a database through Adapter, it
+generally makes more sense to create a statement and interact with it directly, so that you have
+greater control over the prepare-then-execute workflow. To do this, Adapter gives you a routine
+called createStatement() that allows you to create a Driver specific Statement to use so you can
+manage your own prepare-then-execute workflow.
+
+```php
+// with optional parameters to bind up-front
+$statement = $adapter->createStatement($sql, $optionalParameters);
+$result = $statement->execute();
+```
+
+## Using the Driver Object
+
+The Driver object is the primary place where `Zend\Db\Adapter\Adapter` implements the connection
+level abstraction making it possible to use all of ZendDb's interfaces via the various ext/mysqli,
+ext/sqlsrv, PDO, and other PHP level drivers. To make this possible, each driver is composed of 3
+objects:
+
+- A connection: `Zend\Db\Adapter\Driver\ConnectionInterface`
+- A statement: `Zend\Db\Adapter\Driver\StatementInterface`
+- A result: `Zend\Db\Adapter\Driver\ResultInterface`
+
+Each of the built-in drivers practices "prototyping" as a means of creating objects when new
+instances are requested. The workflow looks like this:
+
+- An adapter is created with a set of connection parameters
+- The adapter chooses the proper driver to instantiate, for example `Zend\Db\Adapter\Driver\Mysqli`
+- That driver class is instantiated
+- If no connection, statement or result objects are injected, defaults are instantiated
+
+This driver is now ready to be called on when particular workflows are requested. Here is what the
+Driver API looks like:
+
+```php
+namespace Zend\Db\Adapter\Driver;
+
+ interface DriverInterface
+ {
+ const PARAMETERIZATION_POSITIONAL = 'positional';
+ const PARAMETERIZATION_NAMED = 'named';
+ const NAME_FORMAT_CAMELCASE = 'camelCase';
+ const NAME_FORMAT_NATURAL = 'natural';
+ public function getDatabasePlatformName($nameFormat = self::NAME_FORMAT_CAMELCASE);
+ public function checkEnvironment();
+ public function getConnection();
+ public function createStatement($sqlOrResource = null);
+ public function createResult($resource);
+ public function getPrepareType();
+ public function formatParameterName($name, $type = null);
+ public function getLastGeneratedValue();
+ }
+```
+
+From this DriverInterface, you can
+
+- Determine the name of the platform this driver supports (useful for choosing the proper platform
+object)
+- Check that the environment can support this driver
+- Return the Connection object
+- Create a Statement object which is optionally seeded by an SQL statement (this will generally be a
+clone of a prototypical statement object)
+- Create a Result object which is optionally seeded by a statement resource (this will generally be
+a clone of a prototypical result object)
+- Format parameter names, important to distinguish the difference between the various ways
+parameters are named between extensions
+- Retrieve the overall last generated value (such as an auto-increment value)
+
+Statement objects generally look like this:
+
+```php
+namespace Zend\Db\Adapter\Driver;
+
+interface StatementInterface extends StatementContainerInterface
+{
+ public function getResource();
+ public function prepare($sql = null);
+ public function isPrepared();
+ public function execute($parameters = null);
+
+ /** Inherited from StatementContainerInterface */
+ public function setSql($sql);
+ public function getSql();
+ public function setParameterContainer(ParameterContainer $parameterContainer);
+ public function getParameterContainer();
+}
+```
+
+Result objects generally look like this:
+
+```php
+namespace Zend\Db\Adapter\Driver;
+
+interface ResultInterface extends \Countable, \Iterator
+{
+ public function buffer();
+ public function isQueryResult();
+ public function getAffectedRows();
+ public function getGeneratedValue();
+ public function getResource();
+ public function getFieldCount();
+}
+```
+
+## Using The Platform Object
+
+The Platform object provides an API to assist in crafting queries in a way that is specific to the
+SQL implementation of a particular vendor. Nuances such as how identifiers or values are quoted, or
+what the identifier separator character is are handled by this object. To get an idea of the
+capabilities, the interface for a platform object looks like this:
+
+```php
+namespace Zend\Db\Adapter\Platform;
+
+interface PlatformInterface
+{
+ public function getName();
+ public function getQuoteIdentifierSymbol();
+ public function quoteIdentifier($identifier);
+ public function quoteIdentifierChain($identiferChain)
+ public function getQuoteValueSymbol();
+ public function quoteValue($value);
+ public function quoteValueList($valueList);
+ public function getIdentifierSeparator();
+ public function quoteIdentifierInFragment($identifier, array $additionalSafeWords = array());
+}
+```
+
+While one can instantiate your own Platform object, generally speaking, it is easier to get the
+proper Platform instance from the configured adapter (by default the Platform type will match the
+underlying driver implementation):
+
+```php
+$platform = $adapter->getPlatform();
+// or
+$platform = $adapter->platform; // magic property access
+```
+
+The following is a couple of example of Platform usage:
+
+```php
+```
+
+> linenos
+/*\* @var $adapter ZendDbAdapterAdapter*/ /*\* @var $platform ZendDbAdapterPlatformSql92*/ $platform
+= $adapter->getPlatform();
+// "first\_name" echo $platform->quoteIdentifier('first\_name');
+// " echo $platform->getQuoteIdentifierSymbol();
+// "schema"."mytable" echo $platform->quoteIdentifierChain(array('schema','mytable')));
+// ' echo $platform->getQuoteValueSymbol();
+// 'myvalue' echo $platform->quoteValue('myvalue');
+// 'value', 'Foo O\\'Bar' echo $platform->quoteValueList(array('value',"Foo O'Bar")));
+// . echo $platform->getIdentifierSeparator();
+// "foo" as "bar" echo $platform->quoteIdentifierInFragment('foo as bar');
+// additionally, with some safe words: // ("foo"."bar" = "boo"."baz") echo
+$platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '='));
+
+## Using The Parameter Container
+
+The ParameterContainer object is a container for the various parameters that need to be passed into
+a Statement object to fulfill all the various parameterized parts of the SQL statement. This object
+implements the ArrayAccess interface. Below is the ParameterContainer API:
+
+```php
+namespace Zend\Db\Adapter;
+
+ class ParameterContainer implements \Iterator, \ArrayAccess, \Countable {
+ public function __construct(array $data = array())
+
+ /** methods to interact with values */
+ public function offsetExists($name)
+ public function offsetGet($name)
+ public function offsetSetReference($name, $from)
+ public function offsetSet($name, $value, $errata = null)
+ public function offsetUnset($name)
+
+ /** set values from array (will reset first) */
+ public function setFromArray(Array $data)
+
+ /** methods to interact with value errata */
+ public function offsetSetErrata($name, $errata)
+ public function offsetGetErrata($name)
+ public function offsetHasErrata($name)
+ public function offsetUnsetErrata($name)
+
+ /** errata only iterator */
+ public function getErrataIterator()
+
+ /** get array with named keys */
+ public function getNamedArray()
+
+ /** get array with int keys, ordered by position */
+ public function getPositionalArray()
+
+ /** iterator: */
+ public function count()
+ public function current()
+ public function next()
+ public function key()
+ public function valid()
+ public function rewind()
+
+ /** merge existing array of parameters with existing parameters */
+ public function merge($parameters)
+ }
+```
+
+In addition to handling parameter names and values, the container will assist in tracking parameter
+types for PHP type to SQL type handling. For example, it might be important that:
+
+```php
+$container->offsetSet('limit', 5);
+```
+
+be bound as an integer. To achieve this, pass in the ParameterContainer::TYPE\_INTEGER constant as
+the 3rd parameter:
+
+```php
+$container->offsetSet('limit', 5, $container::TYPE_INTEGER);
+```
+
+This will ensure that if the underlying driver supports typing of bound parameters, that this
+translated information will also be passed along to the actual php database driver.
+
+## Examples
+
+Creating a Driver and Vendor portable Query, Preparing and Iterating Result
+
+```php
+$adapter = new Zend\Db\Adapter\Adapter($driverConfig);
+
+$qi = function($name) use ($adapter) { return $adapter->platform->quoteIdentifier($name); };
+$fp = function($name) use ($adapter) { return $adapter->driver->formatParameterName($name); };
+
+$sql = 'UPDATE ' . $qi('artist')
+ . ' SET ' . $qi('name') . ' = ' . $fp('name')
+ . ' WHERE ' . $qi('id') . ' = ' . $fp('id');
+
+/** @var $statement Zend\Db\Adapter\Driver\StatementInterface */
+$statement = $adapter->query($sql);
+
+$parameters = array(
+ 'name' => 'Updated Artist',
+ 'id' => 1
+);
+
+$statement->execute($parameters);
+
+// DATA INSERTED, NOW CHECK
+
+/* @var $statement Zend\Db\Adapter\DriverStatementInterface */
+$statement = $adapter->query('SELECT * FROM '
+ . $qi('artist')
+ . ' WHERE id = ' . $fp('id'));
+
+/* @var $results Zend\Db\ResultSet\ResultSet */
+$results = $statement->execute(array('id' => 1));
+
+$row = $results->current();
+$name = $row['name'];
+```
diff --git a/doc/book/zend.db.metadata.md b/doc/book/zend.db.metadata.md
new file mode 100644
index 0000000000..2052bf78b0
--- /dev/null
+++ b/doc/book/zend.db.metadata.md
@@ -0,0 +1,223 @@
+# Zend\\Db\\Metadata
+
+`Zend\Db\Metadata` is as sub-component of Zend\\Db that makes it possible to get metadata
+information about tables, columns, constraints, triggers, and other information from a database in a
+standardized way. The primary interface for the Metadata objects is:
+
+```php
+interface MetadataInterface
+{
+ public function getSchemas();
+
+ public function getTableNames($schema = null, $includeViews = false);
+ public function getTables($schema = null, $includeViews = false);
+ public function getTable($tableName, $schema = null);
+
+ public function getViewNames($schema = null);
+ public function getViews($schema = null);
+ public function getView($viewName, $schema = null);
+
+ public function getColumnNames($table, $schema = null);
+ public function getColumns($table, $schema = null);
+ public function getColumn($columnName, $table, $schema = null);
+
+ public function getConstraints($table, $schema = null);
+ public function getConstraint($constraintName, $table, $schema = null);
+ public function getConstraintKeys($constraint, $table, $schema = null);
+
+ public function getTriggerNames($schema = null);
+ public function getTriggers($schema = null);
+ public function getTrigger($triggerName, $schema = null);
+}
+```
+
+## Basic Usage
+
+Usage of `Zend\Db\Metadata` is very straight forward. The top level class
+Zend\\Db\\Metadata\\Metadata will, given an adapter, choose the best strategy (based on the database
+platform being used) for retrieving metadata. In most cases, information will come from querying the
+INFORMATION\_SCHEMA tables generally accessible to all database connections about the currently
+accessible schema.
+
+Metadata::get\*Names() methods will return an array of strings, while the other methods will return
+specific value objects with the containing information. This is best demonstrated by the script
+below.
+
+```php
+$metadata = new Zend\Db\Metadata\Metadata($adapter);
+
+// get the table names
+$tableNames = $metadata->getTableNames();
+
+foreach ($tableNames as $tableName) {
+ echo 'In Table ' . $tableName . PHP_EOL;
+
+ $table = $metadata->getTable($tableName);
+
+
+ echo ' With columns: ' . PHP_EOL;
+ foreach ($table->getColumns() as $column) {
+ echo ' ' . $column->getName()
+ . ' -> ' . $column->getDataType()
+ . PHP_EOL;
+ }
+
+ echo PHP_EOL;
+ echo ' With constraints: ' . PHP_EOL;
+
+ foreach ($metadata->getConstraints($tableName) as $constraint) {
+ /** @var $constraint Zend\Db\Metadata\Object\ConstraintObject */
+ echo ' ' . $constraint->getName()
+ . ' -> ' . $constraint->getType()
+ . PHP_EOL;
+ if (!$constraint->hasColumns()) {
+ continue;
+ }
+ echo ' column: ' . implode(', ', $constraint->getColumns());
+ if ($constraint->isForeignKey()) {
+ $fkCols = array();
+ foreach ($constraint->getReferencedColumns() as $refColumn) {
+ $fkCols[] = $constraint->getReferencedTableName() . '.' . $refColumn;
+ }
+ echo ' => ' . implode(', ', $fkCols);
+ }
+ echo PHP_EOL;
+
+ }
+
+ echo '----' . PHP_EOL;
+}
+```
+
+Metadata returns value objects that provide an interface to help developers better explore the
+metadata. Below is the API for the various value objects:
+
+The TableObject:
+
+```php
+class Zend\Db\Metadata\Object\TableObject
+{
+ public function __construct($name);
+ public function setColumns(array $columns);
+ public function getColumns();
+ public function setConstraints($constraints);
+ public function getConstraints();
+ public function setName($name);
+ public function getName();
+}
+```
+
+The ColumnObject:
+
+```php
+class Zend\Db\Metadata\Object\ColumnObject {
+ public function __construct($name, $tableName, $schemaName = null);
+ public function setName($name);
+ public function getName();
+ public function getTableName();
+ public function setTableName($tableName);
+ public function setSchemaName($schemaName);
+ public function getSchemaName();
+ public function getOrdinalPosition();
+ public function setOrdinalPosition($ordinalPosition);
+ public function getColumnDefault();
+ public function setColumnDefault($columnDefault);
+ public function getIsNullable();
+ public function setIsNullable($isNullable);
+ public function isNullable();
+ public function getDataType();
+ public function setDataType($dataType);
+ public function getCharacterMaximumLength();
+ public function setCharacterMaximumLength($characterMaximumLength);
+ public function getCharacterOctetLength();
+ public function setCharacterOctetLength($characterOctetLength);
+ public function getNumericPrecision();
+ public function setNumericPrecision($numericPrecision);
+ public function getNumericScale();
+ public function setNumericScale($numericScale);
+ public function getNumericUnsigned();
+ public function setNumericUnsigned($numericUnsigned);
+ public function isNumericUnsigned();
+ public function getErratas();
+ public function setErratas(array $erratas);
+ public function getErrata($errataName);
+ public function setErrata($errataName, $errataValue);
+}
+```
+
+The ConstraintObject:
+
+```php
+class Zend\Db\Metadata\Object\ConstraintObject
+{
+ public function __construct($name, $tableName, $schemaName = null);
+ public function setName($name);
+ public function getName();
+ public function setSchemaName($schemaName);
+ public function getSchemaName();
+ public function getTableName();
+ public function setTableName($tableName);
+ public function setType($type);
+ public function getType();
+ public function hasColumns();
+ public function getColumns();
+ public function setColumns(array $columns);
+ public function getReferencedTableSchema();
+ public function setReferencedTableSchema($referencedTableSchema);
+ public function getReferencedTableName();
+ public function setReferencedTableName($referencedTableName);
+ public function getReferencedColumns();
+ public function setReferencedColumns(array $referencedColumns);
+ public function getMatchOption();
+ public function setMatchOption($matchOption);
+ public function getUpdateRule();
+ public function setUpdateRule($updateRule);
+ public function getDeleteRule();
+ public function setDeleteRule($deleteRule);
+ public function getCheckClause();
+ public function setCheckClause($checkClause);
+ public function isPrimaryKey();
+ public function isUnique();
+ public function isForeignKey();
+ public function isCheck();
+
+}
+```
+
+The TriggerObject:
+
+```php
+class Zend\Db\Metadata\Object\TriggerObject
+{
+ public function getName();
+ public function setName($name);
+ public function getEventManipulation();
+ public function setEventManipulation($eventManipulation);
+ public function getEventObjectCatalog();
+ public function setEventObjectCatalog($eventObjectCatalog);
+ public function getEventObjectSchema();
+ public function setEventObjectSchema($eventObjectSchema);
+ public function getEventObjectTable();
+ public function setEventObjectTable($eventObjectTable);
+ public function getActionOrder();
+ public function setActionOrder($actionOrder);
+ public function getActionCondition();
+ public function setActionCondition($actionCondition);
+ public function getActionStatement();
+ public function setActionStatement($actionStatement);
+ public function getActionOrientation();
+ public function setActionOrientation($actionOrientation);
+ public function getActionTiming();
+ public function setActionTiming($actionTiming);
+ public function getActionReferenceOldTable();
+ public function setActionReferenceOldTable($actionReferenceOldTable);
+ public function getActionReferenceNewTable();
+ public function setActionReferenceNewTable($actionReferenceNewTable);
+ public function getActionReferenceOldRow();
+ public function setActionReferenceOldRow($actionReferenceOldRow);
+ public function getActionReferenceNewRow();
+ public function setActionReferenceNewRow($actionReferenceNewRow);
+ public function getCreated();
+ public function setCreated($created);
+}
+```
diff --git a/doc/book/zend.db.result-set.md b/doc/book/zend.db.result-set.md
new file mode 100644
index 0000000000..1cfa5bf602
--- /dev/null
+++ b/doc/book/zend.db.result-set.md
@@ -0,0 +1,117 @@
+# Zend\\Db\\ResultSet
+
+`Zend\Db\ResultSet` is a sub-component of Zend\\Db for abstracting the iteration of rowset producing
+queries. While data sources for this can be anything that is iterable, generally a
+`Zend\Db\Adapter\Driver\ResultInterface` based object is the primary source for retrieving data.
+
+`Zend\Db\ResultSet`'s must implement the `Zend\Db\ResultSet\ResultSetInterface` and all
+sub-components of Zend\\Db that return a ResultSet as part of their API will assume an instance of a
+`ResultSetInterface` should be returned. In most casts, the Prototype pattern will be used by
+consuming object to clone a prototype of a ResultSet and return a specialized ResultSet with a
+specific data source injected. The interface of ResultSetInterface looks like this:
+
+```php
+interface ResultSetInterface extends \Traversable, \Countable
+{
+ public function initialize($dataSource);
+ public function getFieldCount();
+}
+```
+
+## Quickstart
+
+`Zend\Db\ResultSet\ResultSet` is the most basic form of a ResultSet object that will expose each row
+as either an ArrayObject-like object or an array of row data. By default, `Zend\Db\Adapter\Adapter`
+will use a prototypical `Zend\Db\ResultSet\ResultSet` object for iterating when using the
+`Zend\Db\Adapter\Adapter::query()` method.
+
+The following is an example workflow similar to what one might find inside
+`Zend\Db\Adapter\Adapter::query()`:
+
+```php
+use Zend\Db\Adapter\Driver\ResultInterface;
+use Zend\Db\ResultSet\ResultSet;
+
+$stmt = $driver->createStatement('SELECT * FROM users');
+$stmt->prepare();
+$result = $stmt->execute($parameters);
+
+if ($result instanceof ResultInterface && $result->isQueryResult()) {
+ $resultSet = new ResultSet;
+ $resultSet->initialize($result);
+
+ foreach ($resultSet as $row) {
+ echo $row->my_column . PHP_EOL;
+ }
+}
+```
+
+## Zend\\Db\\ResultSet\\ResultSet and Zend\\Db\\ResultSet\\AbstractResultSet
+
+For most purposes, either a instance of `Zend\Db\ResultSet\ResultSet` or a derivative of
+`Zend\Db\ResultSet\AbstractResultSet` will be being used. The implementation of the
+`AbstractResultSet` offers the following core functionality:
+
+```php
+abstract class AbstractResultSet implements Iterator, ResultSetInterface
+{
+ public function initialize($dataSource)
+ public function getDataSource()
+ public function getFieldCount()
+
+ /** Iterator */
+ public function next()
+ public function key()
+ public function current()
+ public function valid()
+ public function rewind()
+
+ /** countable */
+ public function count()
+
+ /** get rows as array */
+ public function toArray()
+}
+```
+
+## Zend\\Db\\ResultSet\\HydratingResultSet
+
+`Zend\Db\ResultSet\HydratingResultSet` is a more flexible `ResultSet` object that allows the
+developer to choose an appropriate "hydration strategy" for getting row data into a target object.
+While iterating over results, `HydratingResultSet` will take a prototype of a target object and
+clone it once for each row. The `HydratingResultSet` will then hydrate that clone with the row data.
+
+In the example below, rows from the database will be iterated, and during iteration,
+`HydratingRowSet` will use the Reflection based hydrator to inject the row data directly into the
+protected members of the cloned UserEntity object:
+
+```php
+use Zend\Db\Adapter\Driver\ResultInterface;
+use Zend\Db\ResultSet\HydratingResultSet;
+use Zend\Stdlib\Hydrator\Reflection as ReflectionHydrator;
+
+class UserEntity {
+ protected $first_name;
+ protected $last_name;
+ public function getFirstName() { return $this->first_name; }
+ public function getLastName() { return $this->last_name; }
+ public function setFirstName($first_name) { $this->first_name = $first_name; }
+ public function setLastName($last_name) { $this->last_name = $last_name; }
+}
+
+$stmt = $driver->createStatement($sql);
+$stmt->prepare($parameters);
+$result = $stmt->execute();
+
+if ($result instanceof ResultInterface && $result->isQueryResult()) {
+ $resultSet = new HydratingResultSet(new ReflectionHydrator, new UserEntity);
+ $resultSet->initialize($result);
+
+ foreach ($resultSet as $user) {
+ echo $user->getFirstName() . ' ' . $user->getLastName() . PHP_EOL;
+ }
+}
+```
+
+For more information, see the `Zend\Stdlib\Hydrator` documentation to get a better sense of the
+different strategies that can be employed in order to populate a target object.
diff --git a/doc/book/zend.db.row-gateway.md b/doc/book/zend.db.row-gateway.md
new file mode 100644
index 0000000000..e63d956aa3
--- /dev/null
+++ b/doc/book/zend.db.row-gateway.md
@@ -0,0 +1,89 @@
+# Zend\\Db\\RowGateway
+
+`Zend\Db\RowGateway` is a sub-component of Zend\\Db that implements the Row Gateway pattern from
+PoEAA. This effectively means that Row Gateway objects primarily model a row in a database, and have
+methods such as save() and delete() that will help persist this row-as-an-object in the database
+itself. Likewise, after a row from the database is retrieved, it can then be manipulated and
+save()'d back to the database in the same position (row), or it can be delete()'d from the table.
+
+The interface for a Row Gateway object simply adds save() and delete() and this is the interface
+that should be assumed when a component has a dependency that is expected to be an instance of a
+RowGateway object:
+
+```php
+interface RowGatewayInterface
+{
+ public function save();
+ public function delete();
+}
+```
+
+## Quickstart
+
+While most of the time, RowGateway will be used in conjunction with other Zend\\Db\\ResultSet
+producing objects, it is possible to use it standalone. To use it standalone, you simply need an
+Adapter and a set of data to work with. The following use case demonstrates
+Zend\\Db\\RowGateway\\RowGateway usage in its simplest form:
+
+```php
+use Zend\Db\RowGateway\RowGateway;
+
+// query the database
+$resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', array(2));
+
+// get array of data
+$rowData = $resultSet->current()->getArrayCopy();
+
+// row gateway
+$rowGateway = new RowGateway('id', 'my_table', $adapter);
+$rowGateway->populate($rowData, true);
+
+$rowGateway->first_name = 'New Name';
+$rowGateway->save();
+
+// or delete this row:
+$rowGateway->delete();
+```
+
+The workflow described above is greatly simplified when RowGateway is used in conjunction with the
+TableGateway feature. What this achieves is a Table Gateway object that when select()'ing from a
+table, will produce a ResultSet that is then capable of producing valid Row Gateway objects. Its
+usage looks like this:
+
+```php
+use Zend\Db\TableGateway\Feature\RowGatewayFeature;
+use Zend\Db\TableGateway\TableGateway;
+
+$table = new TableGateway('artist', $adapter, new RowGatewayFeature('id'));
+$results = $table->select(array('id' => 2));
+
+$artistRow = $results->current();
+$artistRow->name = 'New Name';
+$artistRow->save();
+```
+
+## ActiveRecord Style Objects
+
+If you wish to have custom behaviour for your RowGateway objects (essentially making them behave
+similarly to the ActiveRecord pattern), pass a prototype object implementing the
+`RowGatewayInterface` to the `RowGatewayFeature` constructor instead of a primary key:
+
+```php
+use Zend\Db\TableGateway\Feature\RowGatewayFeature;
+use Zend\Db\TableGateway\TableGateway;
+use Zend\Db\RowGateway\RowGatewayInterface;
+
+class Artist implements RowGatewayInterface
+{
+ protected $adapter;
+
+ public function __construct($adapter)
+ {
+ $this->adapter = $adapter;
+ }
+
+ // ... save() and delete() implementations
+}
+
+$table = new TableGateway('artist', $adapter, new RowGatewayFeature(new Artist($adapter)));
+```
diff --git a/doc/book/zend.db.sql.ddl.md b/doc/book/zend.db.sql.ddl.md
new file mode 100644
index 0000000000..8a34b40109
--- /dev/null
+++ b/doc/book/zend.db.sql.ddl.md
@@ -0,0 +1,247 @@
+# Zend\\Db\\Sql\\Ddl
+
+`Zend\Db\Sql\Ddl` is a sub-component of `Zend\Db\Sql` that allows consumers to create statement
+objects that will produce DDL (Data Definition Language) SQL statements. When combined with a
+platform specific `Zend\Db\Sql\Sql` object, these DDL objects are capable of producing
+platform-specific `CREATE TABLE` statements, with specialized data types, constraints, and indexes
+for a database/schema.
+
+The following platforms have platform specializations for DDL:
+
+- MySQL
+- All databases compatible with ANSI SQL92
+
+## Creating Tables
+
+Like `Zend\Db\Sql` objects, each statement type is represented by a class. For example, `CREATE
+TABLE` is modeled by a `CreateTable` object; this is likewise the same for `ALTER TABLE` (as
+`AlterTable`), and `DROP TABLE` (as `DropTable`). These classes exist in the `Zend\Db\Sql\Ddl`
+namespace. To initiate the building of a DDL statement, such as `CreateTable`, one needs to
+instantiate the object. There are a couple of valid patterns for this:
+
+```php
+use Zend\Db\Sql\Ddl;
+
+$table = new Ddl\CreateTable();
+
+// or with table
+$table = new Ddl\CreateTable('bar');
+
+// optionally, as a temporary table
+$table = new Ddl\CreateTable('bar', true);
+```
+
+You can also set the table after instantiation:
+
+```php
+$table->setTable('bar');
+```
+
+Currently, columns are added by creating a column object, described in the data type table in the
+data type section below:
+
+```php
+use Zend\Db\Sql\Ddl\Column;
+$table->addColumn(new Column\Integer('id'));
+$table->addColumn(new Column\Varchar('name', 255));
+```
+
+Beyond adding columns to a table, constraints can also be added:
+
+```php
+use Zend\Db\Sql\Ddl\Constraint;
+$table->addConstraint(new Constraint\PrimaryKey('id'));
+$table->addConstraint(
+ new Constraint\UniqueKey(['name', 'foo'], 'my_unique_key')
+);
+```
+
+## Altering Tables
+
+Similarly to `CreateTable`, you may also instantiate `AlterTable`:
+
+```php
+use Zend\Db\Sql\Ddl;
+
+$table = new Ddl\AlterTable();
+
+// or with table
+$table = new Ddl\AlterTable('bar');
+
+// optionally, as a temporary table
+$table = new Ddl\AlterTable('bar', true);
+```
+
+The primary difference between a `CreateTable` and `AlterTable` is that the `AlterTable` takes into
+account that the table and its assets already exist. Therefore, while you still have `addColumn()`
+and `addConstraint()`, you will also see the ability to change existing columns:
+
+```php
+use Zend\Db\Sql\Ddl\Column;
+$table->changeColumn('name', Column\Varchar('new_name', 50));
+```
+
+You may also drop existing columns or constraints:
+
+```php
+$table->dropColumn('foo');
+$table->dropConstraint('my_index');
+```
+
+## Dropping Tables
+
+To drop a table, create a `DropTable` statement object:
+
+```php
+$drop = new Ddl\DropTable('bar');
+```
+
+## Executing DDL Statements
+
+After a DDL statement object has been created and configured, at some point you will want to execute
+the statement. To do this, you will need two other objects: an `Adapter` instance, and a properly
+seeded `Sql` instance.
+
+The workflow looks something like this, with `$ddl` being a `CreateTable`, `AlterTable`, or
+`DropTable` instance:
+
+```php
+use Zend\Db\Sql\Sql;
+
+// existence of $adapter is assumed
+$sql = new Sql($adapter);
+
+$adapter->query(
+ $sql->getSqlStringForSqlObject($ddl),
+ $adapter::QUERY_MODE_EXECUTE
+);
+```
+
+By passing the `$ddl` object through the `$sql` object's `getSqlStringForSqlObject()` method, we
+ensure that any platform specific specializations/modifications are utilized to create a platform
+specific SQL statement.
+
+Next, using the constant `Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE` ensures that the SQL
+statement is not prepared, as many DDL statements on a variety of platforms cannot be prepared, only
+executed.
+
+## Currently Supported Data Types
+
+These types exist in the `Zend\Db\Sql\Ddl\Column` namespace. Data types must implement
+`Zend\Db\Sql\Ddl\Column\ColumnInterface`.
+
+In alphabetical order:
+
+
+
+
+
+
+
+
+
+
+
+BigInteger |
+$name, $nullable = false, $default = null, array $options =
+array() |
+
+
+Blob |
+$name, $length, $nullable = false, $default = null, array $options =
+array() |
+
+
+Boolean |
+$name |
+
+
+Char |
+$name, $length |
+
+
+Column (generic) |
+$name = null |
+
+
+Date |
+$name |
+
+
+Decimal |
+$name, $precision, $scale = null |
+
+
+Float |
+$name, $digits, $decimal (Note: this class is deprecated as of 2.4.0;
+use Floating instead |
+
+
+Floating |
+$name, $digits, $decimal |
+
+
+Integer |
+$name, $nullable = false, $default = null, array $options =
+array() |
+
+
+Time |
+$name |
+
+
+Varchar |
+$name, $length |
+
+
+
+
+Each of the above types can be utilized in any place that accepts a `Column\ColumnInterface`
+instance. Currently, this is primarily in `CreateTable::addColumn()` and `AlterTable`'s
+`addColumn()` and `changeColumn()` methods.
+
+## Currently Supported Constraint Types
+
+These types exist in the `Zend\Db\Sql\Ddl\Constraint` namespace. Data types must implement
+`Zend\Db\Sql\Ddl\Constraint\ConstraintInterface`.
+
+In alphabetical order:
+
+
+
+
+
+
+
+
+
+
+
+Check |
+$expression, $name |
+
+
+ForeignKey |
+$name, $column, $referenceTable, $referenceColumn, $onDeleteRule = null,
+$onUpdateRule = null |
+
+
+PrimaryKey |
+$columns |
+
+
+UniqueKey |
+$column, $name = null |
+
+
+
+
+Each of the above types can be utilized in any place that accepts a `Column\ConstraintInterface`
+instance. Currently, this is primarily in `CreateTable::addConstraint()` and
+`AlterTable::addConstraint()`.
diff --git a/doc/book/zend.db.sql.md b/doc/book/zend.db.sql.md
new file mode 100644
index 0000000000..51b1a6d9d2
--- /dev/null
+++ b/doc/book/zend.db.sql.md
@@ -0,0 +1,621 @@
+# Zend\\Db\\Sql
+
+`Zend\Db\Sql` is a SQL abstraction layer for building platform specific SQL queries via an
+object-oriented API. The end result of an `Zend\Db\Sql` object will be to either produce a Statement
+and Parameter container that represents the target query, or a full string that can be directly
+executed against the database platform. To achieve this, `Zend\Db\Sql` objects require a
+`Zend\Db\Adapter\Adapter` object in order to produce the desired results.
+
+## Zend\\Db\\Sql\\Sql (Quickstart)
+
+As there are four primary tasks associated with interacting with a database (from the DML, or Data
+Manipulation Language): selecting, inserting, updating and deleting. As such, there are four primary
+objects that developers can interact or building queries, `Zend\Db\Sql\Select`, `Insert`, `Update`
+and `Delete`.
+
+Since these four tasks are so closely related, and generally used together within the same
+application, `Zend\Db\Sql\Sql` objects help you create them and produce the result you are
+attempting to achieve.
+
+```php
+use Zend\Db\Sql\Sql;
+$sql = new Sql($adapter);
+$select = $sql->select(); // @return Zend\Db\Sql\Select
+$insert = $sql->insert(); // @return Zend\Db\Sql\Insert
+$update = $sql->update(); // @return Zend\Db\Sql\Update
+$delete = $sql->delete(); // @return Zend\Db\Sql\Delete
+```
+
+As a developer, you can now interact with these objects, as described in the sections below, to
+specialize each query. Once they have been populated with values, they are ready to either be
+prepared or executed.
+
+To prepare (using a Select object):
+
+```php
+use Zend\Db\Sql\Sql;
+$sql = new Sql($adapter);
+$select = $sql->select();
+$select->from('foo');
+$select->where(array('id' => 2));
+
+$statement = $sql->prepareStatementForSqlObject($select);
+$results = $statement->execute();
+```
+
+To execute (using a Select object)
+
+```php
+use Zend\Db\Sql\Sql;
+$sql = new Sql($adapter);
+$select = $sql->select();
+$select->from('foo');
+$select->where(array('id' => 2));
+
+$selectString = $sql->buildSqlString($select);
+$results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE);
+```
+
+Zend\\Db\\Sql\\Sql objects can also be bound to a particular table so that in getting a select,
+insert, update, or delete object, they are all primarily seeded with the same table when produced.
+
+```php
+use Zend\Db\Sql\Sql;
+$sql = new Sql($adapter, 'foo');
+$select = $sql->select();
+$select->where(array('id' => 2)); // $select already has the from('foo') applied
+```
+
+## Zend\\Db\\Sql's Select, Insert, Update and Delete
+
+Each of these objects implements the following (2) interfaces:
+
+```php
+interface PreparableSqlInterface {
+ public function prepareStatement(Adapter $adapter, StatementInterface $statement);
+}
+interface SqlInterface {
+ public function getSqlString(PlatformInterface $adapterPlatform = null);
+}
+```
+
+These are the functions you can call to either produce (a) a prepared statement, or (b) a string to
+be executed.
+
+## Zend\\Db\\Sql\\Select
+
+`Zend\Db\Sql\Select` is an object who's primary function is to present a unified API for building
+platform specific SQL SELECT queries. The class can be instantiated and consumed without
+`Zend\Db\Sql\Sql`:
+
+```php
+use Zend\Db\Sql\Select;
+$select = new Select();
+// or, to produce a $select bound to a specific table
+$select = new Select('foo');
+```
+
+If a table is provided to the Select object, then from() cannot be called later to change the name
+of the table.
+
+Once you have a valid Select object, the following API can be used to further specify various select
+statement parts:
+
+```php
+class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface
+{
+ const JOIN_INNER = 'inner';
+ const JOIN_OUTER = 'outer';
+ const JOIN_LEFT = 'left';
+ const JOIN_RIGHT = 'right';
+ const SQL_STAR = '*';
+ const ORDER_ASCENDING = 'ASC';
+ const ORDER_DESCENDING = 'DESC';
+
+ public $where; // @param Where $where
+
+ public function __construct($table = null);
+ public function from($table);
+ public function columns(array $columns, $prefixColumnsWithTable = true);
+ public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER);
+ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND);
+ public function group($group);
+ public function having($predicate, $combination = Predicate\PredicateSet::OP_AND);
+ public function order($order);
+ public function limit($limit);
+ public function offset($offset);
+}
+```
+
+### from():
+
+```php
+// as a string:
+$select->from('foo');
+
+// as an array to specify an alias:
+// produces SELECT "t".* FROM "table" AS "t"
+
+$select->from(array('t' => 'table'));
+
+// using a Sql\TableIdentifier:
+// same output as above
+
+$select->from(new TableIdentifier(array('t' => 'table')));
+```
+
+### columns():
+
+```php
+// as array of names
+$select->columns(array('foo', 'bar'));
+
+// as an associative array with aliases as the keys:
+// produces 'bar' AS 'foo', 'bax' AS 'baz'
+
+$select->columns(array('foo' => 'bar', 'baz' => 'bax'));
+```
+
+### join():
+
+```php
+$select->join(
+ 'foo', // table name
+ 'id = bar.id', // expression to join on (will be quoted by platform object before insertion),
+ array('bar', 'baz'), // (optional) list of columns, same requirements as columns() above
+ $select::JOIN_OUTER // (optional), one of inner, outer, left, right also represented by constants
+in the API
+);
+
+$select->from(array('f' => 'foo')) // base table
+ ->join(array('b' => 'bar'), // join table with alias
+ 'f.foo_id = b.foo_id'); // join expression
+```
+
+### where(), having():
+
+The `Zend\Db\Sql\Select` object provides bit of flexibility as it regards to what kind of parameters
+are acceptable when calling where() or having(). The method signature is listed as:
+
+```php
+/**
+ * Create where clause
+ *
+ * @param Where|\Closure|string|array $predicate
+ * @param string $combination One of the OP_* constants from Predicate\PredicateSet
+ * @return Select
+ */
+public function where($predicate, $combination = Predicate\PredicateSet::OP_AND);
+```
+
+As you can see, there are a number of different ways to pass criteria to both having() and where().
+
+If you provide a `Zend\Db\Sql\Where` object to where() or a `Zend\Db\Sql\Having` object to having(),
+the internal objects for Select will be replaced completely. When the where/having() is processed,
+this object will be iterated to produce the WHERE or HAVING section of the SELECT statement.
+
+If you provide a `Closure` to where() or having(), this function will be called with the Select's
+`Where` object as the only parameter. So the following is possible:
+
+```php
+$spec = function (Where $where) {
+ $where->like('username', 'ralph%');
+};
+
+$select->where($spec);
+```
+
+If you provide a string, this string will be used to instantiate a
+`Zend\Db\Sql\Predicate\Expression` object so that it's contents will be applied as is. This means
+that there will be no quoting in the fragment provided.
+
+Consider the following code:
+
+```php
+// SELECT "foo".* FROM "foo" WHERE x = 5
+$select->from('foo')->where('x = 5');
+```
+
+If you provide an array who's values are keyed by an integer, the value can either be a string that
+will be then used to build a `Predicate\Expression` or any object that implements
+`Predicate\PredicateInterface`. These objects are pushed onto the Where stack with the $combination
+provided.
+
+Consider the following code:
+
+```php
+// SELECT "foo".* FROM "foo" WHERE x = 5 AND y = z
+$select->from('foo')->where(array('x = 5', 'y = z'));
+```
+
+If you provide an array who's values are keyed with a string, these values will be handled in the
+following:
+
+- PHP value nulls will be made into a `Predicate\IsNull` object
+- PHP value array()s will be made into a `Predicate\In` object
+- PHP value strings will be made into a `Predicate\Operator` object such that the string key will be
+identifier, and the value will target value.
+
+Consider the following code:
+
+```php
+// SELECT "foo".* FROM "foo" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL
+$select->from('foo')->where(array(
+ 'c1' => null,
+ 'c2' => array(1, 2, 3),
+ new \Zend\Db\Sql\Predicate\IsNotNull('c3')
+));
+```
+
+### order():
+
+```php
+$select = new Select;
+$select->order('id DESC'); // produces 'id' DESC
+
+$select = new Select;
+$select->order('id DESC')
+ ->order('name ASC, age DESC'); // produces 'id' DESC, 'name' ASC, 'age' DESC
+
+$select = new Select;
+$select->order(array('name ASC', 'age DESC')); // produces 'name' ASC, 'age' DESC
+```
+
+### limit() and offset():
+
+```php
+$select = new Select;
+$select->limit(5); // always takes an integer/numeric
+$select->offset(10); // similarly takes an integer/numeric
+```
+
+## Zend\\Db\\Sql\\Insert
+
+The Insert API:
+
+```php
+class Insert implements SqlInterface, PreparableSqlInterface
+{
+ const VALUES_MERGE = 'merge';
+ const VALUES_SET = 'set';
+
+ public function __construct($table = null);
+ public function into($table);
+ public function columns(array $columns);
+ public function values(array $values, $flag = self::VALUES_SET);
+}
+```
+
+Similarly to Select objects, the table can be set at construction time or via into().
+
+### columns():
+
+```php
+$insert->columns(array('foo', 'bar')); // set the valid columns
+```
+
+### values():
+
+```php
+// default behavior of values is to set the values
+// successive calls will not preserve values from previous calls
+$insert->values(array(
+ 'col_1' => 'value1',
+ 'col_2' => 'value2'
+));
+```
+
+```php
+// merging values with previous calls
+$insert->values(array('col_2' => 'value2'), $insert::VALUES_MERGE);
+```
+
+## Zend\\Db\\Sql\\Update
+
+```php
+class Update
+{
+ const VALUES_MERGE = 'merge';
+ const VALUES_SET = 'set';
+
+ public $where; // @param Where $where
+ public function __construct($table = null);
+ public function table($table);
+ public function set(array $values, $flag = self::VALUES_SET);
+ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND);
+}
+```
+
+### set():
+
+```php
+$update->set(array('foo' => 'bar', 'baz' => 'bax'));
+```
+
+### where():
+
+See where section below.
+
+## Zend\\Db\\Sql\\Delete
+
+```php
+class Delete
+{
+ public $where; // @param Where $where
+ public function __construct($table = null);
+ public function from($table);
+ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND);
+}
+```
+
+### where():
+
+See where section below.
+
+## Zend\\Db\\Sql\\Where & Zend\\Db\\Sql\\Having
+
+In the following, we will talk about Where, Having is implies as being the same API.
+
+Effectively, Where and Having extend from the same base object, a Predicate (and PredicateSet). All
+of the parts that make up a where or having that are and'ed or or'd together are called predicates.
+The full set of predicates is called a PredicateSet. This object set generally contains the values
+(and identifiers) separate from the fragment they belong to until the last possible moment when the
+statement is either used to be prepared (parameteritized), or executed. In parameterization, the
+parameters will be replaced with their proper placeholder (a named or positional parameter), and the
+values stored inside a Adapter\\ParameterContainer. When executed, the values will be interpolated
+into the fragments they belong to and properly quoted.
+
+It is important to know that in this API, a distinction is made between what elements are considered
+identifiers (TYPE\_IDENTIFIER) and which of those is a value (TYPE\_VALUE). There is also a special
+use case type for literal values (TYPE\_LITERAL). These are all exposed via the
+`Zend\Db\Sql\ExpressionInterface` interface.
+
+> ## Note
+In ZF 2.1, an actual `Literal` type was added. `Zend\Db\Sql` now makes the distinction that Literals
+will not have any parameters that need interpolating whereas it is expected that `Expression`
+objects *might* have parameters that need interpolating. In cases where there are parameters in an
+`Expression`, `Zend\Db\Sql\AbstractSql` will do its best to identify placeholders when the
+Expression is processed during statement creation. In short, if you don't have parameters, use
+`Literal` objects.
+
+The Zend\\Db\\Sql\\Where (Predicate/PredicateSet) API:
+
+```php
+// Where & Having:
+class Predicate extends PredicateSet
+{
+ public $and;
+ public $or;
+ public $AND;
+ public $OR;
+ public $NEST;
+ public $UNNEST;
+
+ public function nest();
+ public function setUnnest(Predicate $predicate);
+ public function unnest();
+ public function equalTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType =
+self::TYPE_VALUE);
+ public function notEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType =
+self::TYPE_VALUE);
+ public function lessThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType =
+self::TYPE_VALUE);
+ public function greaterThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType =
+self::TYPE_VALUE);
+ public function lessThanOrEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType
+= self::TYPE_VALUE);
+ public function greaterThanOrEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER,
+$rightType = self::TYPE_VALUE);
+ public function like($identifier, $like);
+ public function literal($literal);
+ public function expression($expression, $parameter);
+ public function isNull($identifier);
+ public function isNotNull($identifier);
+ public function in($identifier, array $valueSet = array());
+ public function between($identifier, $minValue, $maxValue);
+
+
+ // Inherited From PredicateSet
+
+ public function addPredicate(PredicateInterface $predicate, $combination = null);
+ public function getPredicates();
+ public function orPredicate(PredicateInterface $predicate);
+ public function andPredicate(PredicateInterface $predicate);
+ public function getExpressionData();
+ public function count();
+}
+```
+
+Each method in the Where API will produce a corresponding Predicate object of a similarly named
+type, described below, with the full API of the object:
+
+### equalTo(), lessThan(), greaterThan(), lessThanOrEqualTo(), greaterThanOrEqualTo():
+
+```php
+$where->equalTo('id', 5);
+
+// same as the following workflow
+$where->addPredicate(
+ new Predicate\Operator($left, Operator::OPERATOR_EQUAL_TO, $right, $leftType, $rightType)
+);
+
+class Operator implements PredicateInterface
+{
+ const OPERATOR_EQUAL_TO = '=';
+ const OP_EQ = '=';
+ const OPERATOR_NOT_EQUAL_TO = '!=';
+ const OP_NE = '!=';
+ const OPERATOR_LESS_THAN = '<';
+ const OP_LT = '<';
+ const OPERATOR_LESS_THAN_OR_EQUAL_TO = '<=';
+ const OP_LTE = '<=';
+ const OPERATOR_GREATER_THAN = '>';
+ const OP_GT = '>';
+ const OPERATOR_GREATER_THAN_OR_EQUAL_TO = '>=';
+ const OP_GTE = '>=';
+
+ public function __construct($left = null, $operator = self::OPERATOR_EQUAL_TO, $right = null,
+$leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE);
+ public function setLeft($left);
+ public function getLeft();
+ public function setLeftType($type);
+ public function getLeftType();
+ public function setOperator($operator);
+ public function getOperator();
+ public function setRight($value);
+ public function getRight();
+ public function setRightType($type);
+ public function getRightType();
+ public function getExpressionData();
+}
+```
+
+### like($identifier, $like):
+
+```php
+$where->like($identifier, $like):
+
+// same as
+$where->addPredicate(
+ new Predicate\Like($identifier, $like)
+);
+
+// full API
+
+class Like implements PredicateInterface
+{
+ public function __construct($identifier = null, $like = null);
+ public function setIdentifier($identifier);
+ public function getIdentifier();
+ public function setLike($like);
+ public function getLike();
+}
+```
+
+### literal($literal);
+
+```php
+$where->literal($literal);
+
+// same as
+$where->addPredicate(
+ new Predicate\Literal($literal)
+);
+
+// full API
+class Literal implements ExpressionInterface, PredicateInterface
+{
+ const PLACEHOLDER = '?';
+ public function __construct($literal = '');
+ public function setLiteral($literal);
+ public function getLiteral();
+}
+```
+
+### expression($expression, $parameter);
+
+```php
+$where->expression($expression, $parameter);
+
+// same as
+$where->addPredicate(
+ new Predicate\Expression($expression, $parameter)
+);
+
+// full API
+class Expression implements ExpressionInterface, PredicateInterface
+{
+ const PLACEHOLDER = '?';
+ public function __construct($expression = null, $valueParameter = null /*[, $valueParameter, ...
+]*/);
+ public function setExpression($expression);
+ public function getExpression();
+ public function setParameters($parameters);
+ public function getParameters();
+ public function setTypes(array $types);
+ public function getTypes();
+}
+```
+
+### isNull($identifier);
+
+```php
+$where->isNull($identifier);
+
+// same as
+$where->addPredicate(
+ new Predicate\IsNull($identifier)
+);
+
+// full API
+class IsNull implements PredicateInterface
+{
+ public function __construct($identifier = null);
+ public function setIdentifier($identifier);
+ public function getIdentifier();
+}
+```
+
+### isNotNull($identifier);
+
+```php
+$where->isNotNull($identifier);
+
+// same as
+$where->addPredicate(
+ new Predicate\IsNotNull($identifier)
+);
+
+// full API
+class IsNotNull implements PredicateInterface
+{
+ public function __construct($identifier = null);
+ public function setIdentifier($identifier);
+ public function getIdentifier();
+}
+```
+
+### in($identifier, array $valueSet = array());
+
+```php
+$where->in($identifier, array $valueSet = array());
+
+// same as
+$where->addPredicate(
+ new Predicate\In($identifier, $valueSet)
+);
+
+// full API
+class In implements PredicateInterface
+{
+ public function __construct($identifier = null, array $valueSet = array());
+ public function setIdentifier($identifier);
+ public function getIdentifier();
+ public function setValueSet(array $valueSet);
+ public function getValueSet();
+}
+```
+
+### between($identifier, $minValue, $maxValue);
+
+```php
+$where->between($identifier, $minValue, $maxValue);
+
+// same as
+$where->addPredicate(
+ new Predicate\Between($identifier, $minValue, $maxValue)
+);
+
+// full API
+class Between implements PredicateInterface
+{
+ public function __construct($identifier = null, $minValue = null, $maxValue = null);
+ public function setIdentifier($identifier);
+ public function getIdentifier();
+ public function setMinValue($minValue);
+ public function getMinValue();
+ public function setMaxValue($maxValue);
+ public function getMaxValue();
+ public function setSpecification($specification);
+}
+```
diff --git a/doc/book/zend.db.table-gateway.md b/doc/book/zend.db.table-gateway.md
new file mode 100644
index 0000000000..ef7751fe97
--- /dev/null
+++ b/doc/book/zend.db.table-gateway.md
@@ -0,0 +1,179 @@
+# Zend\\Db\\TableGateway
+
+The Table Gateway object is intended to provide an object that represents a table in a database, and
+the methods of this object mirror the most common operations on a database table. In code, the
+interface for such an object looks like this:
+
+```php
+interface Zend\Db\TableGateway\TableGatewayInterface
+{
+ public function getTable();
+ public function select($where = null);
+ public function insert($set);
+ public function update($set, $where = null);
+ public function delete($where);
+}
+```
+
+There are two primary implementations of the `TableGatewayInterface` that are of the most useful:
+`AbstractTableGateway` and `TableGateway`. The `AbstractTableGateway` is an abstract basic
+implementation that provides functionality for `select()`, `insert()`, `update()`, `delete()`, as
+well as an additional API for doing these same kinds of tasks with explicit SQL objects. These
+methods are `selectWith()`, `insertWith()`, `updateWith()` and `deleteWith()`. In addition,
+AbstractTableGateway also implements a "Feature" API, that allows for expanding the behaviors of the
+base `TableGateway` implementation without having to extend the class with this new functionality.
+The `TableGateway` concrete implementation simply adds a sensible constructor to the
+`AbstractTableGateway` class so that out-of-the-box, `TableGateway` does not need to be extended in
+order to be consumed and utilized to its fullest.
+
+## Basic Usage
+
+The quickest way to get up and running with Zend\\Db\\TableGateway is to configure and utilize the
+concrete implementation of the `TableGateway`. The API of the concrete `TableGateway` is:
+
+```php
+class TableGateway extends AbstractTableGateway
+{
+ public $lastInsertValue;
+ public $table;
+ public $adapter;
+
+ public function __construct($table, Adapter $adapter, $features = null, ResultSet
+$resultSetPrototype = null, Sql $sql = null)
+
+ /** Inherited from AbstractTableGateway */
+
+ public function isInitialized();
+ public function initialize();
+ public function getTable();
+ public function getAdapter();
+ public function getColumns();
+ public function getFeatureSet();
+ public function getResultSetPrototype();
+ public function getSql();
+ public function select($where = null);
+ public function selectWith(Select $select);
+ public function insert($set);
+ public function insertWith(Insert $insert);
+ public function update($set, $where = null);
+ public function updateWith(Update $update);
+ public function delete($where);
+ public function deleteWith(Delete $delete);
+ public function getLastInsertValue();
+}
+```
+
+The concrete `TableGateway` object practices constructor injection for getting dependencies and
+options into the instance. The table name and an instance of an Adapter are all that is needed to
+setup a working `TableGateway` object.
+
+Out of the box, this implementation makes no assumptions about table structure or metadata, and when
+`select()` is executed, a simple ResultSet object with the populated Adapter's Result (the
+datasource) will be returned and ready for iteration.
+
+```php
+use Zend\Db\TableGateway\TableGateway;
+$projectTable = new TableGateway('project', $adapter);
+$rowset = $projectTable->select(array('type' => 'PHP'));
+
+echo 'Projects of type PHP: ';
+foreach ($rowset as $projectRow) {
+ echo $projectRow['name'] . PHP_EOL;
+}
+
+// or, when expecting a single row:
+$artistTable = new TableGateway('artist', $adapter);
+$rowset = $artistTable->select(array('id' => 2));
+$artistRow = $rowset->current();
+
+var_dump($artistRow);
+```
+
+The `select()` method takes the same arguments as `Zend\Db\Sql\Select::where()` with the addition of
+also being able to accept a closure, which in turn, will be passed the current Select object that is
+being used to build the SELECT query. The following usage is possible:
+
+```php
+use Zend\Db\TableGateway\TableGateway;
+use Zend\Db\Sql\Select;
+$artistTable = new TableGateway('artist', $adapter);
+
+// search for at most 2 artists who's name starts with Brit, ascending
+$rowset = $artistTable->select(function (Select $select) {
+ $select->where->like('name', 'Brit%');
+ $select->order('name ASC')->limit(2);
+});
+```
+
+## TableGateway Features
+
+The Features API allows for extending the functionality of the base `TableGateway` object without
+having to polymorphically extend the base class. This allows for a wider array of possible mixing
+and matching of features to achieve a particular behavior that needs to be attained to make the base
+implementation of `TableGateway` useful for a particular problem.
+
+With the `TableGateway` object, features should be injected though the constructor. The constructor
+can take Features in 3 different forms: as a single feature object, as a FeatureSet object, or as an
+array of Feature objects.
+
+There are a number of features built-in and shipped with Zend\\Db:
+
+- GlobalAdapterFeature: the ability to use a global/static adapter without needing to inject it into
+a `TableGateway` instance. This is more useful when you are extending the `AbstractTableGateway`
+implementation:
+
+```php
+use Zend\Db\TableGateway\AbstractTableGateway;
+use Zend\Db\TableGateway\Feature;
+
+class MyTableGateway extends AbstractTableGateway
+{
+ public function __construct()
+ {
+ $this->table = 'my_table';
+ $this->featureSet = new Feature\FeatureSet();
+ $this->featureSet->addFeature(new Feature\GlobalAdapterFeature());
+ $this->initialize();
+ }
+}
+
+// elsewhere in code, in a bootstrap
+Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter);
+
+// in a controller, or model somewhere
+$table = new MyTableGateway(); // adapter is statically loaded
+```
+
+- MasterSlaveFeature: the ability to use a master adapter for insert(), update(), and delete() while
+using a slave adapter for all select() operations.
+
+```php
+$table = new TableGateway('artist', $adapter, new Feature\MasterSlaveFeature($slaveAdapter));
+```
+
+- MetadataFeature: the ability populate `TableGateway` with column information from a Metadata
+object. It will also store the primary key information in case RowGatewayFeature needs to consume
+this information.
+
+```php
+$table = new TableGateway('artist', $adapter, new Feature\MetadataFeature());
+```
+
+- EventFeature: the ability utilize a `TableGateway` object with Zend\\EventManager and to be able
+to subscribe to various events in a `TableGateway` lifecycle.
+
+```php
+$table = new TableGateway('artist', $adapter, new Feature\EventFeature($eventManagerInstance));
+```
+
+- RowGatewayFeature: the ability for `select()` to return a ResultSet object that upon iteration
+will return a `RowGateway` object for each row.
+
+```php
+$table = new TableGateway('artist', $adapter, new Feature\RowGatewayFeature('id'));
+$results = $table->select(array('id' => 2));
+
+$artistRow = $results->current();
+$artistRow->name = 'New Name';
+$artistRow->save();
+```
diff --git a/doc/bookdown.json b/doc/bookdown.json
new file mode 100644
index 0000000000..3a60f4f9d1
--- /dev/null
+++ b/doc/bookdown.json
@@ -0,0 +1,13 @@
+{
+ "title": "Zend\\Db",
+ "target": "html/",
+ "content": [
+ "book/zend.db.adapter.md",
+ "book/zend.db.result-set.md",
+ "book/zend.db.sql.md",
+ "book/zend.db.sql.ddl.md",
+ "book/zend.db.table-gateway.md",
+ "book/zend.db.row-gateway.md",
+ "book/zend.db.metadata.md"
+ ]
+}
\ No newline at end of file