diff --git a/phalcon/DM/Pdo/Connection.zep b/phalcon/DM/Pdo/Connection.zep
new file mode 100644
index 0000000000..a6855d5e7f
--- /dev/null
+++ b/phalcon/DM/Pdo/Connection.zep
@@ -0,0 +1,163 @@
+/**
+ * This file is part of the Phalcon Framework.
+ *
+ * (c) Phalcon Team <team@phalcon.io>
+ *
+ * For the full copyright and license information, please view the LICENSE.txt
+ * file that was distributed with this source code.
+ *
+ * Implementation of this file has been influenced by AtlasPHP
+ *
+ * @link    https://github.com/atlasphp/Atlas.Pdo
+ * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md
+ */
+
+namespace Phalcon\DM\Pdo;
+
+use InvalidArgumentException;
+use Phalcon\DM\Pdo\Connection\AbstractConnection;
+use Phalcon\DM\Pdo\Parser\ParserInterface;
+use Phalcon\DM\Pdo\Profiler\Profiler;
+use Phalcon\DM\Pdo\Profiler\ProfilerInterface;
+
+/**
+ * Provides array quoting, profiling, a new `perform()` method, new `fetch*()`
+ * methods
+ *
+ * @property array             $args
+ * @property ParserInterface   $parser
+ * @property PDO               $pdo
+ * @property ProfilerInterface $profiler
+ */
+class Connection extends AbstractConnection
+{
+    /**
+     * @var array
+     */
+    protected arguments = [];
+
+    /**
+     * Constructor.
+     *
+     * This overrides the parent so that it can take connection attributes as a
+     * constructor parameter, and set them after connection.
+     *
+     * @param string            $dsn
+     * @param string            $username
+     * @param string            $password
+     * @param array             $options
+     * @param array             $queries
+     * @param ProfilerInterface $profiler
+     */
+    public function __construct(
+        string dsn,
+        string username = null,
+        string password = null,
+        array options = [],
+        array queries = [],
+        <ProfilerInterface> profiler = null
+    ) {
+        var parser, parts;
+        array available;
+
+        let parts     = explode(":", dsn),
+            available = [
+                "mysql"  : true,
+                "pgsql"  : true,
+                "sqlite" : true,
+                "mssql"  : true
+            ];
+
+        if !isset available[parts[0]] {
+            throw new InvalidArgumentException(
+                "Driver not supported [" . parts[0] . "]"
+            );
+        }
+
+
+        // if no error mode is specified, use exceptions
+        if !isset options[\PDO::ATTR_ERRMODE] {
+            let options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;
+        }
+
+        // Arguments store
+        let this->args = [
+            dsn,
+            username,
+            password,
+            options,
+            queries
+        ];
+
+        // Create a new profiler if none has been passed
+        if profiler === null {
+            let profiler = new Profiler();
+        }
+        this->setProfiler(profiler);
+
+        // Set the new Query parser
+        let parser = this->newParser(parts[0]);
+        this->setParser(parser);
+
+        // Quotes
+        let this->quote = this->getQuoteNames(parts[0]);
+    }
+
+    /**
+     * The purpose of this method is to hide sensitive data from stack traces.
+     *
+     * @return array
+     */
+    public function __debugInfo() -> array
+    {
+        return [
+            "arguments" : [
+                this->arguments[0],
+                "****",
+                "****",
+                this->arguments[3],
+                this->arguments[4]
+            ]
+        ];
+    }
+
+    /**
+     * Connects to the database.
+     */
+    public function connect() -> void
+    {
+        var dsn, options, password, query, queries, username;
+
+        if !this->pdo {
+            // connect
+            this->profiler->start(__FUNCTION__);
+
+            let dsn      = this->arguments[0],
+                username = this->arguments[1],
+                password = this->arguments[2],
+                options  = this->arguments[3],
+                queries  = this->arguments[4];
+
+            let this->pdo = new \PDO(dsn, username, password, options);
+
+            this->profiler->finish();
+
+            // connection-time queries
+            for query in queries {
+                this->exec(query);
+            }
+        }
+    }
+
+    /**
+     * Disconnects from the database.
+     */
+    public function disconnect() -> void
+    {
+        this->profiler->start(__FUNCTION__);
+
+        let this->pdo = null;
+
+        this->profiler->finish();
+    }
+}
diff --git a/phalcon/DM/Pdo/Connection/AbstractConnection.zep b/phalcon/DM/Pdo/Connection/AbstractConnection.zep
index 669773aaf7..f6146de317 100644
--- a/phalcon/DM/Pdo/Connection/AbstractConnection.zep
+++ b/phalcon/DM/Pdo/Connection/AbstractConnection.zep
@@ -16,7 +16,6 @@
 namespace Phalcon\DM\Pdo\Connection;
 
 use BadMethodCallException;
-use PDO;
 use PDOStatement;
 use Phalcon\DM\Pdo\Exception\CannotBindValue;
 use Phalcon\DM\Pdo\Parser\ParserInterface;
@@ -237,8 +236,10 @@ abstract class AbstractConnection implements ConnectionInterface
         let data = [],
             sth  = this->perform(statement, values);
 
-        while (row = sth->$fetch(\PDO::FETCH_ASSOC)) {
+        let row = sth->$fetch(\PDO::FETCH_ASSOC);
+        while (row) {
             let data[current(row)] = row;
+            let row = sth->$fetch(\PDO::FETCH_ASSOC);
         }
 
         return data;
@@ -415,7 +416,7 @@ abstract class AbstractConnection implements ConnectionInterface
      *
      * @return PDO
      */
-    public function getAdapter() -> <PDO>
+    public function getAdapter() -> <\PDO>
     {
         this->connect();
 
@@ -488,6 +489,7 @@ abstract class AbstractConnection implements ConnectionInterface
     public function getQuoteNames(string driver = "") -> array
     {
         var option;
+        array quotes;
 
         let option = driver;
         if empty option {
@@ -496,29 +498,34 @@ abstract class AbstractConnection implements ConnectionInterface
 
         switch option {
             case "mysql":
-                return [
+                let quotes = [
                     "prefix"  : "`",
                     "suffix"  : "`",
                     "find"    : "`",
-                    "replace" : "``",
+                    "replace" : "``"
                 ];
+                break;
 
             case "sqlsrv":
-                return [
+                let quotes = [
                     "prefix"  : "[",
                     "suffix"  : "]",
                     "find"    : "]",
-                    "replace" : "][",
+                    "replace" : "]["
                 ];
+                break;
 
             default:
-                return [
+                let quotes = [
                     "prefix"  : "\"",
                     "suffix"  : "\"",
                     "find"    : "\"",
-                    "replace" : "\"\"",
+                    "replace" : "\"\""
                 ];
+                break;
         }
+
+        return quotes;
     }
 
     /**
@@ -587,7 +594,7 @@ abstract class AbstractConnection implements ConnectionInterface
      * @return PDOStatement
      * @throws CannotBindValue
      */
-    public function perform(string statement, array values = []) -> <PDOStatement>
+    public function perform(string statement, array values = []) -> <\PDOStatement>
     {
         var sth;
 
@@ -630,7 +637,7 @@ abstract class AbstractConnection implements ConnectionInterface
      * @return PDOStatement|false
      * @throws CannotBindValue
      */
-    public function prepareWithValues(string statement, array values = []) -> <PDOStatement>
+    public function prepareWithValues(string statement, array values = []) -> <\PDOStatement>
     {
         var key, parser, parts, statement, value, values;
         array valueNames = [];
@@ -844,7 +851,7 @@ abstract class AbstractConnection implements ConnectionInterface
      * @return bool
      * @throws CannotBindValue
      */
-    protected function bindValue(<PDOStatement> statement, var key, var value) -> bool
+    protected function bindValue(<\PDOStatement> statement, var key, var value) -> bool
     {
         var type;
 
diff --git a/phalcon/DM/Pdo/Connection/ConnectionInterface.zep b/phalcon/DM/Pdo/Connection/ConnectionInterface.zep
index 5d5a7c1b9d..6ad80bf76f 100644
--- a/phalcon/DM/Pdo/Connection/ConnectionInterface.zep
+++ b/phalcon/DM/Pdo/Connection/ConnectionInterface.zep
@@ -15,8 +15,6 @@
 
 namespace Phalcon\DM\Pdo\Connection;
 
-use PDO;
-use PDOStatement;
 use Phalcon\DM\Pdo\Exception\CannotBindValue;
 use Phalcon\DM\Pdo\Parser\ParserInterface;
 use Phalcon\DM\Pdo\Profiler\ProfilerInterface;
@@ -187,7 +185,7 @@ interface ConnectionInterface extends PdoInterface
      *
      * @return PDO
      */
-    public function getAdapter() -> <PDO>;
+    public function getAdapter() -> <\PDO>;
 
     /**
      * Returns the Parser instance.
@@ -222,7 +220,7 @@ interface ConnectionInterface extends PdoInterface
      * @return PDOStatement
      * @throws CannotBindValue
      */
-    public function perform(string statement, array values = []) -> <PDOStatement>;
+    public function perform(string statement, array values = []) -> <\PDOStatement>;
 
     /**
      * Sets the Parser instance.
diff --git a/phalcon/DM/Pdo/Connection/Decorated.zep b/phalcon/DM/Pdo/Connection/Decorated.zep
new file mode 100644
index 0000000000..2be734574c
--- /dev/null
+++ b/phalcon/DM/Pdo/Connection/Decorated.zep
@@ -0,0 +1,75 @@
+
+/**
+ * This file is part of the Phalcon Framework.
+ *
+ * (c) Phalcon Team <team@phalcon.io>
+ *
+ * For the full copyright and license information, please view the LICENSE.txt
+ * file that was distributed with this source code.
+ *
+ * Implementation of this file has been influenced by AtlasPHP
+ *
+ * @link    https://github.com/atlasphp/Atlas.Pdo
+ * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md
+ */
+
+namespace Phalcon\DM\Pdo\Connection;
+
+use Phalcon\DM\Pdo\Exception\CannotDisconnect;
+use Phalcon\DM\Pdo\Profiler\Profiler;
+use Phalcon\DM\Pdo\Profiler\ProfilerInterface;
+
+/**
+ * Decorates an existing PDO instance with the extended methods.
+ */
+class Decorated extends AbstractConnection
+{
+    /**
+     *
+     * Constructor.
+     *
+     * This overrides the parent so that it can take an existing PDO instance
+     * and decorate it with the extended methods.
+     *
+     * @param PDO                    $pdo
+     * @param ProfilerInterface|null $profiler
+     *
+     */
+    public function __construct(<\PDO> pdo, <ProfilerInterface> profiler = null)
+    {
+        var driver;
+
+        let this->pdo = pdo;
+
+        if null === profiler {
+            let profiler = new Profiler();
+        }
+        this->setProfiler(profiler);
+
+        let driver = pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
+
+        this->setParser(this->newParser(driver));
+
+        let this->quote = this->getQuoteNames(driver);
+    }
+
+    /**
+     * Connects to the database.
+     */
+    public function connect() -> void
+    {
+        // already connected
+    }
+
+    /**
+     * Disconnects from the database; disallowed with decorated PDO connections.
+     *
+     * @throws CannotDisconnect
+     */
+    public function disconnect() -> void
+    {
+        throw new CannotDisconnect(
+            "Cannot disconnect a Decorated connection instance"
+        );
+    }
+}
diff --git a/phalcon/DM/Pdo/Connection/PdoInterface.zep b/phalcon/DM/Pdo/Connection/PdoInterface.zep
index b308f2b0dd..830dcabf21 100644
--- a/phalcon/DM/Pdo/Connection/PdoInterface.zep
+++ b/phalcon/DM/Pdo/Connection/PdoInterface.zep
@@ -15,8 +15,6 @@
 
 namespace Phalcon\DM\Pdo\Connection;
 
-use PDO;
-use PDOStatement;
 use Phalcon\DM\Pdo\Exception\CannotBindValue;
 
 /**
@@ -107,7 +105,7 @@ interface PdoInterface
      *
      * @return PDOStatement|false
      */
-    public function prepare(string statement, array options = []) -> <PDOStatement> | bool;
+    public function prepare(string statement, array options = []) -> <\PDOStatement> | bool;
 
     /**
      * Prepares an SQL statement with bound values. The method only binds values
@@ -122,7 +120,7 @@ interface PdoInterface
      * @return PDOStatement|false
      * @throws CannotBindValue
      */
-    public function prepareWithValues(string statement, array values = []) -> <PDOStatement>;
+    public function prepareWithValues(string statement, array values = []) -> <\PDOStatement>;
 
     /**
      * Queries the database and returns a PDOStatement. If the profiler is
@@ -133,7 +131,7 @@ interface PdoInterface
      *
      * @return PDOStatement|false
      */
-    public function query(string statement) -> <PDOStatement> | bool;
+    public function query(string statement) -> <\PDOStatement> | bool;
 
     /**
      * Quotes a value for use in an SQL statement. This differs from
@@ -181,5 +179,5 @@ interface PdoInterface
      *
      * @return bool
      */
-    public function setAttribute(int attribute, mixed value) -> bool;
+    public function setAttribute(int attribute, var value) -> bool;
 }
diff --git a/phalcon/DM/Pdo/ConnectionLocator.zep b/phalcon/DM/Pdo/ConnectionLocator.zep
new file mode 100644
index 0000000000..d68eb87f13
--- /dev/null
+++ b/phalcon/DM/Pdo/ConnectionLocator.zep
@@ -0,0 +1,219 @@
+/**
+ * This file is part of the Phalcon Framework.
+ *
+ * (c) Phalcon Team <team@phalcon.io>
+ *
+ * For the full copyright and license information, please view the LICENSE.txt
+ * file that was distributed with this source code.
+ *
+ * Implementation of this file has been influenced by AtlasPHP
+ *
+ * @link    https://github.com/atlasphp/Atlas.Pdo
+ * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md
+ */
+
+namespace Phalcon\DM\Pdo;
+
+use Phalcon\DM\Pdo\Connection\ConnectionInterface;
+use Phalcon\DM\Pdo\Exception\ConnectionNotFound;
+
+/**
+ * Manages Connection instances for default, read, and write connections.
+ *
+ * @property callable $master
+ * @property array    $read
+ * @property array    $write
+ */
+class ConnectionLocator implements ConnectionLocatorInterface
+{
+    /**
+     * A default Connection connection factory/instance.
+     *
+     * @var callable
+     */
+    protected master;
+
+    /**
+     * A registry of Connection "read" factories/instances.
+     *
+     * @var array
+     */
+    protected read = [];
+
+    /**
+     * A registry of Connection "write" factories/instances.
+     *
+     * @var array
+     */
+    protected write = [];
+
+    /**
+     * Collection of resolved instances
+     *
+     * @var array
+     */
+    private instances = [];
+
+    /**
+     * Constructor.
+     *
+     * @param callable $master
+     * @param array    $read
+     * @param array    $write
+     */
+    public function __construct(
+        callable master,
+        array read = [],
+        array write = []
+    ) {
+        var name, callableObject;
+
+        if master {
+            this->setMaster(master);
+        }
+
+        for name, callableObject in read {
+            this->setRead(name, callableObject);
+        }
+
+        for name, callableObject in write {
+            this->setWrite(name, callableObject);
+        }
+    }
+
+    /**
+     * Returns the default connection object.
+     *
+     * @return ConnectionInterface
+     */
+    public function getMaster() -> <ConnectionInterface>
+    {
+        return this->master;
+    }
+
+    /**
+     * Returns a read connection by name; if no name is given, picks a
+     * random connection; if no read connections are present, returns the
+     * default connection.
+     *
+     * @param string $name
+     *
+     * @return ConnectionInterface
+     * @throws ConnectionNotFound
+     */
+    public function getRead(string name = "") -> <ConnectionInterface>
+    {
+        return this->getConnection("read", name);
+    }
+
+    /**
+     * Returns a write connection by name; if no name is given, picks a
+     * random connection; if no write connections are present, returns the
+     * default connection.
+     *
+     * @param string $name
+     *
+     * @return ConnectionInterface
+     * @throws ConnectionNotFound
+     */
+    public function getWrite(string name = "") -> <ConnectionInterface>
+    {
+        return this->getConnection("write", name);
+    }
+
+    /**
+     * Sets the default connection factory.
+     *
+     * @param callable|null $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setMaster(callable callableObject) -> <ConnectionLocatorInterface>
+    {
+        let this->master = callableObject;
+
+        return this;
+    }
+
+    /**
+     * Sets a read connection factory by name.
+     *
+     * @param string   $name
+     * @param callable $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setRead(
+        string name,
+        callable callableObject
+    ) -> <ConnectionLocatorInterface> {
+        let this->read[name] = callableObject;
+
+        return this;
+    }
+
+    /**
+     * Sets a write connection factory by name.
+     *
+     * @param string   $name
+     * @param callable $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setWrite(
+        string name,
+        callable callableObject
+    ) -> <ConnectionLocatorInterface> {
+        let this->write[name] = callableObject;
+
+        return this;
+    }
+
+    protected function getConnection(
+        string type,
+        string name = ""
+    ) -> <ConnectionInterface> {
+        var collection, instanceName, instances, requested;
+
+        let collection = this->{type},
+            requested  = name,
+            instances  = this->instances;
+
+        /**
+         * No collection returns the master
+         */
+        if empty collection {
+            return this->getMaster();
+        }
+
+        /**
+         * If the requested name is empty, get a random connection
+         */
+        if "" === requested {
+            let requested = array_rand(collection);
+        }
+
+        /**
+         * If the connection name does not exist, send an exception back
+         */
+        if !isset collection[requested] {
+            throw new ConnectionNotFound(
+                "Connection not found: " . type . ":" . requested
+            );
+        }
+
+        /**
+         * Check if the connection has been resolved already, if yes return
+         * it, otherwise resolve it. The keys in the `resolved` array are
+         * formatted as "type-name"
+         */
+        let instanceName = this->{type} . "-" . requested;
+
+        if !isset instances[instanceName] {
+            let instances[instanceName] = call_user_func(collection[requested]),
+                this->instances         = instances;
+        }
+
+        return instances[instanceName];
+    }
+}
diff --git a/phalcon/DM/Pdo/ConnectionLocatorInterface.zep b/phalcon/DM/Pdo/ConnectionLocatorInterface.zep
new file mode 100644
index 0000000000..913c97af8a
--- /dev/null
+++ b/phalcon/DM/Pdo/ConnectionLocatorInterface.zep
@@ -0,0 +1,82 @@
+
+/**
+ * This file is part of the Phalcon Framework.
+ *
+ * (c) Phalcon Team <team@phalcon.io>
+ *
+ * For the full copyright and license information, please view the LICENSE.txt
+ * file that was distributed with this source code.
+ *
+ * Implementation of this file has been influenced by AtlasPHP
+ *
+ * @link    https://github.com/atlasphp/Atlas.Pdo
+ * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md
+ */
+
+namespace Phalcon\DM\Pdo;
+
+use Phalcon\DM\Pdo\Connection\ConnectionInterface;
+
+/**
+ * Locates PDO connections for default, read, and write databases.
+ */
+interface ConnectionLocatorInterface
+{
+    /**
+     * Returns the default connection object.
+     *
+     * @return ConnectionInterface
+     */
+    public function getMaster() -> <ConnectionInterface>;
+
+    /**
+     * Returns a read connection by name; if no name is given, picks a
+     * random connection; if no read connections are present, returns the
+     * default connection.
+     *
+     * @param string $name
+     *
+     * @return ConnectionInterface
+     */
+    public function getRead(string name = "") -> <ConnectionInterface>;
+
+    /**
+     * Returns a write connection by name; if no name is given, picks a
+     * random connection; if no write connections are present, returns the
+     * default connection.
+     *
+     * @param string $name
+     *
+     * @return ConnectionInterface
+     */
+    public function getWrite(string name = "") -> <ConnectionInterface>;
+
+    /**
+     * Sets the default connection registry entry.
+     *
+     * @param callable $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setMaster(callable callableObject) -> <ConnectionLocatorInterface>;
+
+    /**
+     * Sets a read connection registry entry by name.
+     *
+     * @param string   $name
+     * @param callable $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setRead(string name, callable callableObject) -> <ConnectionLocatorInterface>;
+
+    /**
+     * Sets a write connection registry entry by name.
+     *
+     * @param string   $name
+     * @param callable $callable
+     *
+     * @return ConnectionLocatorInterface
+     */
+    public function setWrite(string name, callable callableObject) -> <ConnectionLocatorInterface>;
+}