diff --git a/src/Adapter/AdapterInterface.php b/src/Adapter/AdapterInterface.php
index d0ca171..ca7ee53 100644
--- a/src/Adapter/AdapterInterface.php
+++ b/src/Adapter/AdapterInterface.php
@@ -3,6 +3,7 @@
 namespace Ulmus\Adapter;
 
 use Ulmus\Common\PdoObject;
+use Ulmus\Migration\FieldDefinition;
 
 interface AdapterInterface {
     public const IDENTIFIER_FIELD = 1;
@@ -10,10 +11,16 @@ interface AdapterInterface {
     public const IDENTIFIER_DATABASE = 3;
     public const IDENTIFIER_SCHEMA = 4;
     public const IDENTIFIER_VALUE = 5;
-    
+
     public function connect() : object /* | PdoObject|mixed */;
     public function buildDataSourceName() : string;
     public function setup(array $configuration) : void;
     public function escapeIdentifier(string $segment, int $type) : string;
     public function defaultEngine() : ? string;
+    public function databaseName() : string;
+    public function mapFieldType(FieldDefinition $field) : string;
+    public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection */;
+    public function repositoryClass() : string;
+    public function queryBuilderClass() : string;
+    public function tableSyntax() : array;
 }
diff --git a/src/Adapter/DefaultAdapterTrait.php b/src/Adapter/DefaultAdapterTrait.php
new file mode 100644
index 0000000..4fee52b
--- /dev/null
+++ b/src/Adapter/DefaultAdapterTrait.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Ulmus\Adapter;
+
+use Ulmus\{Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder};
+
+trait DefaultAdapterTrait
+{
+    public function repositoryClass() : string
+    {
+        return Repository::class;
+    }
+
+    public function queryBuilderClass() : string
+    {
+        return QueryBuilder::class;
+    }
+
+    public function tableSyntax() : array
+    {
+        return [
+            'ai' => "AUTO_INCREMENT",
+            'pk' => "PRIMARY KEY",
+            'unsigned' => "UNSIGNED",
+        ];
+    }
+
+    public function databaseName() : string
+    {
+        return $this->database;
+    }
+
+    public function schemaTable(string $databaseName, string $tableName) /* : ? object */
+    {
+        return Table::repository()->where(Table::field('schema'), $databaseName)->loadOneFromField(Table::field('name'), $tableName);
+    }
+
+    public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
+    {
+        $type = $field->type;
+
+        $length = $field->length;
+
+        if ( is_a($type, Entity\Field\Date::class, true) ) {
+            $type = "DATE";
+        }
+        elseif ( is_a($type, Entity\Field\Time::class, true) ) {
+            $type = "TIME";
+        }
+        elseif ( is_a($type, \DateTime::class, true) ) {
+            $type = "DATETIME";
+        }
+
+        switch($type) {
+            case "bool":
+                $type = "TINYINT";
+                $length = 1;
+                break;
+
+            case "array":
+            case "string":
+                if ($length && $length <= 255) {
+                    $type = "VARCHAR";
+                    break;
+                }
+                elseif (! $length || ( $length <= 65535 ) ) {
+                    $type = "TEXT";
+                }
+                elseif ( $length <= 16777215 ) {
+                    $type = "MEDIUMTEXT";
+                }
+                elseif ($length <= 4294967295) {
+                    $type = "LONGTEXT";
+                }
+                else {
+                    throw new \Exception("A column with size bigger than 4GB cannot be created.");
+                }
+
+                # Length is unnecessary on TEXT fields
+                unset($length);
+
+                break;
+
+            case "float":
+                $type = "DOUBLE";
+                break;
+
+            default:
+                $type = strtoupper($type);
+                break;
+        }
+
+        return $typeOnly ? $type : $type . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
+    }
+}
\ No newline at end of file
diff --git a/src/Adapter/MsSQL.php b/src/Adapter/MsSQL.php
index 4c01539..1d410cf 100644
--- a/src/Adapter/MsSQL.php
+++ b/src/Adapter/MsSQL.php
@@ -5,8 +5,13 @@ namespace Ulmus\Adapter;
 use Ulmus\Common\PdoObject;
 
 use Ulmus\Exception\AdapterConfigurationException;
+use Ulmus\Migration\FieldDefinition;
+use Ulmus\{Entity\InformationSchema\Table, Repository, QueryBuilder};
 
 class MsSQL implements AdapterInterface {
+    use DefaultAdapterTrait;
+
+    const DSN_PREFIX = "sqlsrv";
 
     public int $port;
     
@@ -129,7 +134,7 @@ class MsSQL implements AdapterInterface {
             $parts[] = "WSID={$this->wsid}";
         }
         
-        return "sqlsrv:" . implode(';', $parts);
+        return static::DSN_PREFIX . ":" . implode(';', $parts);
     }
     
     public function setup(array $configuration) : void
diff --git a/src/Adapter/MySQL.php b/src/Adapter/MySQL.php
index 8b9113f..1caf641 100644
--- a/src/Adapter/MySQL.php
+++ b/src/Adapter/MySQL.php
@@ -2,11 +2,18 @@
 
 namespace Ulmus\Adapter;
 
+use Ulmus\Entity\InformationSchema\Table;
+use Ulmus\QueryBuilder;
+use Ulmus\Repository;
 use Ulmus\Common\PdoObject;
 
 use Ulmus\Exception\AdapterConfigurationException;
+use Ulmus\Migration\FieldDefinition;
 
 class MySQL implements AdapterInterface {
+    use DefaultAdapterTrait;
+
+    const DSN_PREFIX = "mysql";
 
     public string $hostname;
     
@@ -17,7 +24,7 @@ class MySQL implements AdapterInterface {
     public string $password;
     
     public string $charset = "utf8mb4";
-    
+
     public ? string $socket;
     
     public int $port = 3306;
@@ -68,6 +75,9 @@ class MySQL implements AdapterInterface {
         catch(PDOException $ex){
             throw $ex;
         }
+        finally {
+            $this->password = str_repeat('*', strlen($this->password));
+        }
 
         return $pdo;
     }
@@ -91,7 +101,7 @@ class MySQL implements AdapterInterface {
             $parts[] = "charset={$this->charset}";
         }
 
-        return "mysql:" . implode(';', $parts);
+        return static::DSN_PREFIX . ":" . implode(';', $parts);
     }
     
     public function setup(array $configuration) : void
diff --git a/src/Adapter/SQLite.php b/src/Adapter/SQLite.php
new file mode 100644
index 0000000..dd89b0d
--- /dev/null
+++ b/src/Adapter/SQLite.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Ulmus\Adapter;
+
+use Ulmus\Common\PdoObject;
+
+use Ulmus\Entity\Sqlite\Table;
+use Ulmus\Exception\AdapterConfigurationException;
+use Ulmus\Migration\FieldDefinition;
+use Ulmus\{ Repository, QueryBuilder };
+
+class SQLite implements AdapterInterface {
+    use DefaultAdapterTrait;
+
+    const DSN_PREFIX = "sqlite";
+
+    public string $path;
+
+    public array $pragma;
+
+    public function __construct(
+        ? string $path = null,
+        ? array $pragma = null
+    ) {
+        if ($path !== null) {
+            $this->path = $path;
+        }
+
+        if ($pragma !== null) {
+            $this->pragma = $pragma;
+        }
+    }
+
+    public function connect() : PdoObject
+    {
+        try {
+            $pdo = new PdoObject($this->buildDataSourceName(), null, null);
+            $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+            $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
+            $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
+        }
+        catch(PDOException $ex){
+            throw $ex;
+        }
+
+        return $pdo;
+    }
+    
+    public function buildDataSourceName() : string
+    {
+        $parts[] = $this->path;
+
+        return  static::DSN_PREFIX . ":" . implode(';', $parts);
+    }
+    
+    public function setup(array $configuration) : void
+    {
+        $this->path = $configuration['path'] ?? "";
+        $this->pragma = $configuration['pragma'] ?? [];
+    }
+
+    # https://sqlite.org/lang_keywords.html
+    public function escapeIdentifier(string $segment, int $type) : string 
+    {
+        switch($type) {
+            case static::IDENTIFIER_DATABASE:
+            case static::IDENTIFIER_TABLE:
+            case static::IDENTIFIER_FIELD:
+                return '"' . trim(str_replace('"', '""', $segment), '"') . '"';
+
+            case static::IDENTIFIER_VALUE:
+                return "'$segment'";
+        }
+    }
+
+    public function defaultEngine(): ? string
+    {
+        return null;
+    }
+
+    public function databaseName() : string
+    {
+        $base = basename($this->path);
+
+        return substr($base, 0, strrpos($base, '.') ?: strlen($base));
+    }
+
+    public function schemaTable(string $databaseName, string $tableName) /* : ? object */
+    {
+        return Table::repository()->loadOneFromField(Table::field('tableName'), $tableName);
+    }
+
+    public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
+    {
+        $type = $field->type;
+
+        $length = $field->length;
+
+        if ( is_a($type, Entity\Field\Date::class, true) || is_a($type, Entity\Field\Time::class, true) || is_a($type, \DateTime::class, true) ) {
+            $type = "TEXT";
+            $length = strlen((string) $type);
+        }
+        else {
+            switch($type) {
+                case "bool":
+                    $check = sprintf("CHECK (%s IN (0, 1))", $field->getColumnName());
+
+                case "bigint":
+                case "int":
+                    $type = "INTEGER";
+                    break;
+
+                case "array":
+                case "string":
+                    $type = "TEXT";
+                    $length = null;
+                    break;
+
+                case "float":
+                    $type = "REAL";
+                    break;
+
+                default:
+                    $type = "BLOB";
+                    break;
+            }
+        }
+
+        return $typeOnly ? $type : $type . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
+    }
+
+    public function tableSyntax() : array
+    {
+        return [
+            'ai' => "AUTOINCREMENT",
+            'pk' => "PRIMARY KEY",
+            'unsigned' => "",
+        ];
+    }
+}
diff --git a/src/Common/EntityField.php b/src/Common/EntityField.php
index 4847005..40fc164 100644
--- a/src/Common/EntityField.php
+++ b/src/Common/EntityField.php
@@ -50,9 +50,9 @@ class EntityField implements WhereRawParameter
         return false;
     }
 
-    public static function generateCreateColumn($field) : string
+    public static function generateCreateColumn(AdapterInterface $adapter, $field) : string
     {
-        $definition = new FieldDefinition($field);
+        $definition = new FieldDefinition($adapter, $field);
 
         return implode(" ", [
             $definition->getSqlName(),
diff --git a/src/Common/EntityResolver.php b/src/Common/EntityResolver.php
index b973e5d..2b8923d 100644
--- a/src/Common/EntityResolver.php
+++ b/src/Common/EntityResolver.php
@@ -164,7 +164,7 @@ class EntityResolver {
 
     public function databaseName() : ? string
     {
-        return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->database ?? null;
+        return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->databaseName() ?? null;
     }
 
     public function sqlAdapter() : \Ulmus\ConnectionAdapter
diff --git a/src/ConnectionAdapter.php b/src/ConnectionAdapter.php
index 97d37f5..db6ea72 100644
--- a/src/ConnectionAdapter.php
+++ b/src/ConnectionAdapter.php
@@ -37,6 +37,8 @@ class ConnectionAdapter
         }
         
         $this->adapter->setup($connection);
+
+        unset($this->configuration['connections'][$this->name]);
     }
 
     public function getConfiguration() : array
@@ -77,7 +79,7 @@ class ConnectionAdapter
      */
     protected function instanciateAdapter($name) : AdapterInterface
     {
-        $class = substr($name, 0, 2) === "\\" ? $name : "\\Ulmus\\Adapter\\$name";
+        $class = substr($name, 0, 2) === "\\" ? $name : sprintf("\\%s\\Adapter\\%s", __NAMESPACE__, $name);
         
         return new $class();
     }
diff --git a/src/Entity/Sqlite/Schema.php b/src/Entity/Sqlite/Schema.php
new file mode 100644
index 0000000..ed57e5f
--- /dev/null
+++ b/src/Entity/Sqlite/Schema.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Ulmus\Entity\Sqlite;
+
+use Ulmus\EntityCollection;
+
+/**
+ * @Table('name' => "sqlite_master")
+ */
+class Schema
+{
+    use \Ulmus\EntityTrait;
+
+    /**
+     * @Id
+     */
+    public ? string $name;
+
+    /**
+     * @Field
+     */
+    public ? string $type;
+
+    /**
+     * @Field('name' => 'tbl_name')
+     */
+    public ? string $tableName;
+
+    /**
+     * @Field
+     */
+    public ? int $rootpage;
+
+    /**
+     * @Field
+     */
+    public ? string $sql;
+
+    /**
+     * @Relation('oneToMany', 'key' => 'tableName', 'foreignKey' => 'tableName', 'entity' => Schema::class)
+     */
+    public EntityCollection $columns;
+}
\ No newline at end of file
diff --git a/src/Entity/Sqlite/Table.php b/src/Entity/Sqlite/Table.php
new file mode 100644
index 0000000..43652fd
--- /dev/null
+++ b/src/Entity/Sqlite/Table.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Ulmus\Entity\Sqlite;
+
+use Ulmus\Repository;
+
+class Table extends Schema
+{
+    public static function repository(string $alias = Repository::DEFAULT_ALIAS): Repository
+    {
+        return new class(static::class, $alias) extends Repository\SqliteRepository
+        {
+            public function finalizeQuery(): void
+            {
+                $this->select(Table::field('tableName'))->groupBy(Table::field('tableName'));
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/src/EntityCollection.php b/src/EntityCollection.php
index 0ef38e8..75b9e3f 100644
--- a/src/EntityCollection.php
+++ b/src/EntityCollection.php
@@ -146,7 +146,12 @@ class EntityCollection extends \ArrayObject {
         return $this->filtersCollection(fn($obj) => is_a($obj, $className));
     }
 
-    public function column($field, bool $unique = false) : array
+    public function column($field, bool $uniqueValue = false, $keyField = null) : array
+    {
+        return $this->map($field, $keyField, $uniqueValue);
+    }
+
+    public function map($field, $keyField = null, bool $uniqueValue = false) : array
     {
         $list = [];
 
@@ -158,11 +163,23 @@ class EntityCollection extends \ArrayObject {
                 $value = $item->$field;
             }
 
-            if ($unique && in_array($value, $list, true)) {
+            if ($uniqueValue && in_array($value, $list, true)) {
                 continue;
             }
 
-            $list[] = $value;
+            if ( $keyField !== null ) {
+                if ( is_callable($keyField) ) {
+                    $key = call_user_func_array($keyField, [ $item ]);
+                }
+                else {
+                    $key = $item->$keyField;
+                }
+
+                $list[$key] = $value;
+            }
+            else {
+                $list[] = $value;
+            }
         }
 
         return $list;
diff --git a/src/Migration/FieldDefinition.php b/src/Migration/FieldDefinition.php
index ad35d5d..e5f6459 100644
--- a/src/Migration/FieldDefinition.php
+++ b/src/Migration/FieldDefinition.php
@@ -2,6 +2,7 @@
 
 namespace Ulmus\Migration;
 
+use Ulmus\Adapter\AdapterInterface;
 use Ulmus\Annotation\Property\Field;
 use Ulmus\Entity;
 
@@ -25,8 +26,12 @@ class FieldDefinition {
 
     public ? string $update;
 
-    public function __construct(array $data)
+    public AdapterInterface $adapter;
+
+    public function __construct(AdapterInterface $adapter, array $data)
     {
+        $this->adapter = $adapter;
+
         $this->name = $data['name'];
         $this->builtIn = $data['builtin'];
         $this->tags = $data['tags'];
@@ -46,108 +51,56 @@ class FieldDefinition {
 
     public function getSqlType(bool $typeOnly = false) : string
     {
-        $type = $this->type;
-
-        $length = $this->length;
-
-        if ( is_a($type, Entity\Field\Date::class, true) ) {
-            $type = "DATE";
-        }
-        elseif ( is_a($type, Entity\Field\Time::class, true) ) {
-            $type = "TIME";
-        }
-        elseif ( is_a($type, \DateTime::class, true) ) {
-            $type = "DATETIME";
-        }
-
-        switch($type) {
-            case "bool":
-                $type = "TINYINT";
-                $length = 1;
-                break;
-
-            case "array":
-            case "string":
-                if ($length && $length <= 255) {
-                    $type = "VARCHAR";
-                    break;
-                }
-                elseif (! $length || ( $length <= 65535 ) ) {
-                    $type = "TEXT";
-                }
-                elseif ( $length <= 16777215 ) {
-                    $type = "MEDIUMTEXT";
-                }
-                elseif ($length <= 4294967295) {
-                    $type = "LONGTEXT";
-                }
-                else {
-                    throw new \Exception("A column with size bigger than 4GB cannot be created.");
-                }
-
-                # Length is unnecessary on TEXT fields
-                unset($length);
-
-                break;
-
-            case "float":
-                $type = "DOUBLE";
-                break;
-
-            default:
-                $type = strtoupper($type);
-                break;
-        }
-
-        return $typeOnly ? $type : $type . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
+        return $this->adapter->mapFieldType($this, $typeOnly);
     }
 
     public function getSqlParams() : string
     {
         $default = $this->getDefault();
+        $syntax = $this->adapter->tableSyntax();
 
         return implode(' ', array_filter([
-            $this->isUnsigned() ? "UNSIGNED" : null,
+            $this->isUnsigned() ? $syntax['unsigned'] : null,
             $this->nullable ? "NULL" : "NOT NULL",
             $default ? "DEFAULT $default" : null,
-            $this->isAutoIncrement() ? "AUTO_INCREMENT" : null,
-            $this->isPrimaryKey() ? "PRIMARY KEY" : null,
+            $this->isPrimaryKey() ? $syntax['pk'] : null,
+            $this->isAutoIncrement() ? $syntax['ai'] : null,
         ]));
     }
 
-    protected function getFieldTag() : ? Field
+    public function getFieldTag() : ? Field
     {
         $field = array_filter($this->tags, fn($item) => $item['object'] instanceof Field);
 
         return array_pop($field)['object'];
     }
 
-    protected function getColumnName() : ? string
+    public function getColumnName() : ? string
     {
         return $this->getFieldTag()->name ?? $this->name;
     }
 
-    protected function getDefault() : ? string
+    public function getDefault() : ? string
     {
         return $this->getFieldTag()->attributes['default'] ?? ( $this->nullable ? "NULL" : null ) ;
     }
 
-    protected function isPrimaryKey() : bool
+    public function isPrimaryKey() : bool
     {
         return $this->getFieldTag()->attributes['primary_key'] ?? false;
     }
 
-    protected function isAutoIncrement() : bool
+    public function isAutoIncrement() : bool
     {
         return $this->getFieldTag()->attributes['auto_increment'] ?? false;
     }
 
-    protected function isUnique() : bool
+    public function isUnique() : bool
     {
         return $this->getFieldTag()->attributes['unique'] ?? false;
     }
 
-    protected function isUnsigned() : bool
+    public function isUnsigned() : bool
     {
         return $this->getFieldTag()->attributes['unsigned'] ?? false;
     }
diff --git a/src/Modeler/Schema.php b/src/Modeler/Schema.php
deleted file mode 100644
index 5744811..0000000
--- a/src/Modeler/Schema.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace Ulmus\Modeler;
-
-class Schema {
-
-    public function __construct()
-    {
-        
-    }
-
-    public function compare()
-    {
-
-    }
-
-    public function migrate()
-    {
-
-    }
-}
diff --git a/src/Query/Alter.php b/src/Query/Alter.php
index a2b03dd..8963035 100644
--- a/src/Query/Alter.php
+++ b/src/Query/Alter.php
@@ -2,6 +2,7 @@
 
 namespace Ulmus\Query;
 
+use Ulmus\Adapter\AdapterInterface;
 use Ulmus\Annotation,
     Ulmus\Common\EntityField;
 
@@ -17,7 +18,13 @@ class Alter extends Fragment {
 
     public bool $skipExisting = true;
 
-    public array  $fieldList;
+    public array $fieldList;
+
+    public AdapterInterface $adapter;
+
+    public function __construct(AdapterInterface $adapter) {
+        $this->adapter = $adapter;
+    }
 
     public function render() : string
     {
@@ -29,7 +36,7 @@ class Alter extends Fragment {
     public function renderFields() : string
     {
         return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
-            return "    " . EntityField::generateAlterColumn($field);
+            return "    " . EntityField::generateAlterColumn($this->adapter, $field);
         }, $this->fieldList)) . PHP_EOL . ")";
     }
 }
diff --git a/src/Query/Create.php b/src/Query/Create.php
index b884339..6e95a1d 100644
--- a/src/Query/Create.php
+++ b/src/Query/Create.php
@@ -2,6 +2,7 @@
 
 namespace Ulmus\Query;
 
+use Ulmus\Adapter\AdapterInterface;
 use Ulmus\Annotation,
     Ulmus\Common\EntityField;
 
@@ -19,6 +20,12 @@ class Create extends Fragment {
 
     public array  $fieldList;
 
+    public AdapterInterface $adapter;
+
+    public function __construct(AdapterInterface $adapter) {
+        $this->adapter = $adapter;
+    }
+
     public function render() : string
     {
         return $this->renderSegments([
@@ -29,7 +36,7 @@ class Create extends Fragment {
     public function renderFields() : string
     {
         return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
-            return "    " . EntityField::generateCreateColumn($field);
+            return "    " . EntityField::generateCreateColumn($this->adapter, $field);
         }, $this->fieldList)) . PHP_EOL . ")";
     }
 }
diff --git a/src/Query/Join.php b/src/Query/Join.php
index 77a5e95..f07544d 100644
--- a/src/Query/Join.php
+++ b/src/Query/Join.php
@@ -8,7 +8,7 @@ use Ulmus\Repository\ConditionTrait;
 class Join extends Fragment 
 {
     use ConditionTrait;
-    
+
     const SQL_OUTER = "OUTER";
     const SQL_TOKEN = "JOIN";
 
@@ -39,9 +39,12 @@ class Join extends Fragment
 
     public int $order = 40;
 
+    public int $joinOrder = 0;
+
     public function __construct(QueryBuilderInterface $queryBuilder) 
     {
-        $this->queryBuilder = new QueryBuilder();
+        $cls = get_class($queryBuilder);
+        $this->queryBuilder = new $cls();
         $this->queryBuilder->parent = $queryBuilder;
     }
     
diff --git a/src/Query/Select.php b/src/Query/Select.php
index 4f7c01f..a4efe9f 100644
--- a/src/Query/Select.php
+++ b/src/Query/Select.php
@@ -42,7 +42,6 @@ class Select extends Fragment {
             if ( ! is_numeric($key) ) {
                 $value = sprintf(static::FIELD_AS, $value, $key);
             }
-            
         }
         
         return $this->renderSegments([
diff --git a/src/Query/Sqlite/Pragma.php b/src/Query/Sqlite/Pragma.php
new file mode 100644
index 0000000..9c67f33
--- /dev/null
+++ b/src/Query/Sqlite/Pragma.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Ulmus\Query\Sqlite;
+
+class Pragma extends \Ulmus\Query\Fragment {
+
+    const SQL_TOKEN = "PRAGMA %s%s";
+
+    public int $order = 15;
+
+    public /* object|string */ $pragma;
+
+    public $value;
+
+    public bool $callable;
+
+    public function set(/* object|Stringable */ $pragma, /* ? mixed */ $value = null, bool $callable = false) : self
+    {
+        $this->pragma = $pragma;
+
+        if ($value) {
+            $this->value = $value;
+        }
+
+        $this->callable = $callable;
+
+        return $this;
+    }
+
+    public function render() : string
+    {
+        if ( isset($this->value) ) {
+            $value = sprintf($this->callable ? " (%s)" : " = %s", $this->value);
+        }
+
+        return $this->renderSegments([
+            sprintf(static::SQL_TOKEN, $this->pragma, $value ?? "")
+        ]);
+    }
+}
diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php
index 2b9ada3..3f54269 100644
--- a/src/QueryBuilder.php
+++ b/src/QueryBuilder.php
@@ -305,7 +305,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
         $join->outer = $outer;
         
         $join->alias = $alias;
-        
+
         return $join;
     }
     
@@ -328,7 +328,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
         return $this;
     }
 
-    public function create(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
+    public function create(Adapter\AdapterInterface $adapter, array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
     {
         if ( null === $this->getFragment(Query\Create::class) ) {
             if ( $schema ) {
@@ -339,7 +339,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
                 $table = "$database.$table";
             }
 
-            $create = new Query\Create();
+            $create = new Query\Create($adapter);
             $this->push($create);
 
             $create->fieldList = $fieldlist;
@@ -352,7 +352,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
         return $this;
     }
 
-    public function alter(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
+    public function alter(Adapter\AdapterInterface $adapter, array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
     {
         if ( null === $this->getFragment(Query\Create::class) ) {
             if ( $schema ) {
@@ -363,7 +363,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
                 $table = "$database.$table";
             }
 
-            $alter = new Query\Alter();
+            $alter = new Query\Alter($adapter);
             $this->push($alter);
 
             $alter->fieldList = $fieldlist;
@@ -405,7 +405,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
         $sql = [];
 
         usort($this->queryStack, function($q1, $q2) {
-            return $q1->order <=> $q2->order;
+            return (float) $q1->order <=> (float) $q2->order;
         });
 
         foreach($this->queryStack as $fragment) {
@@ -456,9 +456,9 @@ class QueryBuilder implements Query\QueryBuilderInterface
         }
     }
 
-    public function getFragments() : array
+    public function getFragments(/*? Query\Fragment|array*/ $fragment = null) : array
     {
-        return $this->queryStack;
+        return $fragment === null ? array_filter($this->queryStack, fn($e) => get_class($e) === $fragment) : $this->queryStack;
     }
     
     public function __toString() : string
@@ -485,4 +485,15 @@ class QueryBuilder implements Query\QueryBuilderInterface
     {
         $this->values = $values;
     }
+    
+    protected function nextJoinOrder() : float
+    {
+        $next = 0;
+
+        foreach($this->getFragments(Query\Join::class) as $join) {
+            $next = max($next, $join->joinOrder - Query\Join::ORDER_VALUE);
+        }
+
+        return $next + 1;
+    }
 }
diff --git a/src/QueryBuilder/MssqlQueryBuilder.php b/src/QueryBuilder/MssqlQueryBuilder.php
new file mode 100644
index 0000000..e139517
--- /dev/null
+++ b/src/QueryBuilder/MssqlQueryBuilder.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Ulmus\QueryBuilder;
+
+use Ulmus\QueryBuilder;
+
+use Ulmus\Query;
+
+class MssqlQueryBuilder extends QueryBuilder implements Ulmus\Query\QueryBuilderInterface
+{
+    public function limit(int $value) : self
+    {
+        if ( null === $offset = $this->getFragment(Query\MsSQL\Offset::class) ) {
+            $offset = new Query\MsSQL\Offset();
+            $this->push($offset);
+        }
+
+        $offset->limit = $value;
+
+        return $this;
+    }
+
+    public function offset(int $value) : self
+    {
+        if ( null === $offset = $this->getFragment(Query\MsSQL\Offset::class) ) {
+            $offset = new Query\MsSQL\Offset();
+            $this->push($offset);
+        }
+
+        $offset->offset = $value;
+
+        return $this;
+    }
+}
diff --git a/src/QueryBuilder/SqliteQueryBuilder.php b/src/QueryBuilder/SqliteQueryBuilder.php
new file mode 100644
index 0000000..821df22
--- /dev/null
+++ b/src/QueryBuilder/SqliteQueryBuilder.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Ulmus\QueryBuilder;
+
+use Ulmus\QueryBuilder;
+
+use Ulmus\Query;
+
+class SqliteQueryBuilder extends QueryBuilder implements Query\QueryBuilderInterface
+{
+    public function pragma(/*object|Stringable*/ $name, $value = null, bool $callable = false) : self
+    {
+        if ( null !== ( $pragma = $this->getFragment(Query\Sqlite\Pragma::class) ) ) {
+            $pragma->set($name, $value, $callable);
+        }
+        else {
+            $pragma = new Query\Sqlite\Pragma();
+            $pragma->set($name, $value, $callable);
+            $this->push($pragma);
+        }
+
+        return $this;
+    }
+}
diff --git a/src/Repository.php b/src/Repository.php
index 267efe8..c78bdf9 100644
--- a/src/Repository.php
+++ b/src/Repository.php
@@ -7,7 +7,7 @@ use Ulmus\Common\EntityResolver;
 
 class Repository
 {
-    use EventTrait, Repository\ConditionTrait;
+    use EventTrait, Repository\ConditionTrait, Repository\EscapeTrait;
 
     const DEFAULT_ALIAS = "this";
 
@@ -28,9 +28,9 @@ class Repository
         $this->alias = $alias;
         $this->entityResolver = Ulmus::resolveEntity($entity);
         $this->adapter = $adapter ?? $this->entityResolver->databaseAdapter();
-        $this->queryBuilder = new QueryBuilder();
+        $this->queryBuilder = Ulmus::queryBuilder($entity);
     }
-    
+
     public function __clone()
     {
         #$this->queryBuilder = clone $this->queryBuilder;
@@ -148,9 +148,9 @@ class Repository
             # $dataset = array_filter($dataset, fn($item, $field) => ! ($this->entityResolver->searchFieldAnnotation($field, new Field, false)->readonly ?? false), \ARRAY_FILTER_USE_BOTH);
 
             $statement = $this->insertSqlQuery($fieldsAndValue ?? $dataset, $replace)->runInsertQuery();
-            
-            if ( ( 0 !== $statement->lastInsertId ) && 
-               ( null !== $primaryKeyDefinition )) {
+
+            if ( ( 0 !== $statement->lastInsertId ) &&
+                ( null !== $primaryKeyDefinition )) {
 
                 $pkField = key($primaryKeyDefinition);
                 $dataset[$pkField] = $statement->lastInsertId;
@@ -195,74 +195,20 @@ class Repository
 
     }
 
-    public function loadCollectionRelation(EntityCollection $collection, /*array|string*/ $fields) : void
-    {
-        foreach ((array)$fields as $name) {
-            if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation()))) {
-                $relationType = strtolower(str_replace(['-', '_', ' '], '', $relation->type));
-
-                $order = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\OrderBy());
-                $where = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\Where());
-
-                $baseEntity = $relation->entity ?? $relation->bridge ?? $this->entityResolver->properties[$name]['type'];
-                $baseEntityResolver = $baseEntity::resolveEntity();
-
-                $property = ($baseEntityResolver->field($relation->foreignKey, 01, false) ?: $baseEntityResolver->field($relation->foreignKey, 02))['name'];
-                $entityProperty = ($this->entityResolver->field($relation->key, 01, false) ?: $this->entityResolver->field($relation->key, 02))['name'];
-
-                $repository = $baseEntity::repository();
-
-                foreach ($where as $condition) {
-                    $repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [$this]) : $condition->value, $condition->operator, $condition->condition);
-                }
-
-                foreach ($order as $item) {
-                    $repository->orderBy($item->field, $item->order);
-                }
-
-                $field = $relation->key;
-
-                $values = [];
-
-                $key = is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey);
-
-                foreach ($collection as $item) {
-                    $values[] = is_callable($field) ? $field($item) : $item->$entityProperty;
-                }
-
-                $repository->where($key, $values);
-
-                switch ($relationType) {
-                    case 'onetoone':
-                        $results = call_user_func([$repository, "loadOne"]);
-                        $item->$name = $results ?: new $baseEntity();
-
-                        break;
-
-                    case 'onetomany':
-                        $results = call_user_func([$repository, $relation->function]);
-
-                        foreach ($collection as $item) {
-                            $item->$name = $baseEntity::entityCollection();
-                            $item->$name->mergeWith($results->filtersCollection(fn($e) => $e->$property === $item->$entityProperty));
-                        }
-
-                        break;
-                }
-            }
-        }
-    }
-
     public function replace(/*object|array*/ $entity, ? array $fieldsAndValue = null) : bool
     {
         return $this->save($entity, $fieldsAndValue, true);
     }
 
-    public function replaceAll(/*EntityCollection|array*/ $collection) : void
+    public function replaceAll(/*EntityCollection|array*/ $collection) : int
     {
+        $changed = 0;
+
         foreach($collection as $entity) {
-            $this->replace($entity);
+            $this->replace($entity) && $changed++;
         }
+
+        return $changed;
     }
 
     public function truncate(? string $table = null, ? string $alias = null, ? string $schema = null) : self
@@ -489,10 +435,10 @@ class Repository
     public function randomizeOrder() : self
     {
         $this->queryBuilder->orderBy(Common\Sql::function('RAND', Sql::identifier('CURDATE()+0')));
-        
+
         return $this;
     }
-    
+
     public function orders(array $orderList) : self
     {
         foreach($orderList as $field => $direction) {
@@ -678,6 +624,64 @@ class Repository
         return $this;
     }
 
+    public function loadCollectionRelation(EntityCollection $collection, /*array|string*/ $fields) : void
+    {
+        foreach ((array)$fields as $name) {
+            if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation()))) {
+                $relationType = strtolower(str_replace(['-', '_', ' '], '', $relation->type));
+
+                $order = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\OrderBy());
+                $where = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\Where());
+
+                $baseEntity = $relation->entity ?? $relation->bridge ?? $this->entityResolver->properties[$name]['type'];
+                $baseEntityResolver = $baseEntity::resolveEntity();
+
+                $property = ($baseEntityResolver->field($relation->foreignKey, 01, false) ?: $baseEntityResolver->field($relation->foreignKey, 02))['name'];
+                $entityProperty = ($this->entityResolver->field($relation->key, 01, false) ?: $this->entityResolver->field($relation->key, 02))['name'];
+
+                $repository = $baseEntity::repository();
+
+                foreach ($where as $condition) {
+                    $repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [$this]) : $condition->value, $condition->operator, $condition->condition);
+                }
+
+                foreach ($order as $item) {
+                    $repository->orderBy($item->field, $item->order);
+                }
+
+                $field = $relation->key;
+
+                $values = [];
+
+                $key = is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey);
+
+                foreach ($collection as $item) {
+                    $values[] = is_callable($field) ? $field($item) : $item->$entityProperty;
+                }
+
+                $repository->where($key, $values);
+
+                switch ($relationType) {
+                    case 'onetoone':
+                        $results = call_user_func([$repository, "loadOne"]);
+                        $item->$name = $results ?: new $baseEntity();
+
+                        break;
+
+                    case 'onetomany':
+                        $results = call_user_func([$repository, $relation->function]);
+
+                        foreach ($collection as $item) {
+                            $item->$name = $baseEntity::entityCollection();
+                            $item->$name->mergeWith($results->filtersCollection(fn($e) => $e->$property === $item->$entityProperty));
+                        }
+
+                        break;
+                }
+            }
+        }
+    }
+
     public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest, bool $count = true) : self
     {
         if ($count) {
@@ -819,13 +823,7 @@ class Repository
     public function createSqlQuery() : self
     {
         if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) {
-            $this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
-        }
-
-        if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
-            if ( $engine = $this->entityResolver->tableAnnotation()->engine ?? $this->entityResolver->databaseAdapter()->adapter()->defaultEngine() ) {
-                $this->queryBuilder->engine($engine);
-            }
+            $this->queryBuilder->create($this->adapter->adapter(), $this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
         }
 
         return $this;
@@ -834,7 +832,7 @@ class Repository
     public function alterSqlQuery(array $fields) : self
     {
         if ( null === $this->queryBuilder->getFragment(Query\Alter::class) ) {
-            $this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
+            $this->queryBuilder->create($this->adapter->adapter(), $this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
         }
 
 
@@ -859,7 +857,7 @@ class Repository
 
         return $result;
     }
-    
+
     public function instanciateEntityCollection(...$arguments) : EntityCollection
     {
         return $this->entityClass::entityCollection(...$arguments);
@@ -870,47 +868,6 @@ class Repository
         return new $this->entityClass();
     }
 
-    public function escapeField(string $identifier) : string
-    {
-        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_FIELD);
-    }
-
-    public function escapeFieldList(array $fieldList) : array
-    {
-        foreach($fieldList as &$list) {
-            $list['name'] = $this->escapeField($list['name']);
-
-            $fieldTag = array_filter($list['tags'] ?? [], fn($item) => $item['object'] instanceof Field)[0]['object'] ?? null;
-
-            if ( $fieldTag && isset($fieldTag->name)  ) {
-                $fieldTag->name = $this->escapeField($fieldTag->name);
-            }
-        }
-
-        return $fieldList;
-    }
-
-    public function escapeTable(string $identifier) : string
-    {
-        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_TABLE);
-    }
-
-    public function escapeDatabase(string $identifier) : string
-    {
-        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_DATABASE);
-    }
-
-    public function escapedDatabase() : ? string
-    {
-        $name = $this->entityResolver->tableAnnotation()->database ?? $this->adapter->adapter()->database ?? null;
-
-        return $name ? static::escapeDatabase($name) : null;
-    }
-
-    public function escapeSchema(string $identifier) : string
-    {
-        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_SCHEMA);
-    }
 
     public function hasFilters() : bool
     {
diff --git a/src/Repository/EscapeTrait.php b/src/Repository/EscapeTrait.php
new file mode 100644
index 0000000..eb69ab7
--- /dev/null
+++ b/src/Repository/EscapeTrait.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\{ Query, Adapter };
+use Ulmus\Annotation\Property\Field;
+
+trait EscapeTrait
+{
+    public function escapeField(string $identifier) : string
+    {
+        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_FIELD);
+    }
+
+    public function escapeFieldList(array $fieldList) : array
+    {
+        foreach($fieldList as &$list) {
+            $list['name'] = $this->escapeField($list['name']);
+
+            $fieldTag = array_filter($list['tags'] ?? [], fn($item) => $item['object'] instanceof Field)[0]['object'] ?? null;
+
+            if ( $fieldTag && isset($fieldTag->name)  ) {
+                $fieldTag->name = $this->escapeField($fieldTag->name);
+            }
+        }
+
+        return $fieldList;
+    }
+
+    public function escapeTable(string $identifier) : string
+    {
+        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_TABLE);
+    }
+
+    public function escapeDatabase(string $identifier) : string
+    {
+        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_DATABASE);
+    }
+
+    public function escapedDatabase() : ? string
+    {
+        $name = $this->entityResolver->tableAnnotation()->database ?? $this->adapter->adapter()->database ?? null;
+
+        return $name ? static::escapeDatabase($name) : null;
+    }
+
+    public function escapeSchema(string $identifier) : string
+    {
+        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_SCHEMA);
+    }
+}
\ No newline at end of file
diff --git a/src/Repository/MssqlRepository.php b/src/Repository/MssqlRepository.php
index 590fb47..81ba517 100644
--- a/src/Repository/MssqlRepository.php
+++ b/src/Repository/MssqlRepository.php
@@ -5,7 +5,7 @@ namespace Ulmus\Repository;
 use Ulmus\{ Repository, Query };
 
 class MssqlRepository extends Repository {
-
+/*
     protected function finalizeQuery() : void
     {
         if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) {
@@ -39,5 +39,34 @@ class MssqlRepository extends Repository {
             $this->queryBuilder->removeFragment($limit);
         }
     }
+*/
 
+    protected function finalizeQuery() : void
+    {
+        if ( null !== $offset = $this->queryBuilder->getFragment(Query\MsSQL\Offset::class) ) {
+            # an order by is mandatory for mssql offset/limit
+            if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) {
+                $this->orderBy("(SELECT 0)");
+            }
+
+            if ( empty ($offset->offset ) ) {
+                if ( null !== $select = $this->queryBuilder->getFragment(Query\Select::class) ) {
+                    $select->top = $offset->limit;
+                }
+                elseif ( null !== $delete = $this->queryBuilder->getFragment(Query\Delete::class) ) {
+                    $delete->top = $offset->limit;
+                }
+
+                $this->queryBuilder->removeFragment($offset);
+            }
+            elseif ( empty($offset->limit) ) {
+                throw new \Exception("Your offset query fragment is missing a LIMIT value.");
+            }
+        }
+    }
+
+    protected function serverRequestCountRepository() : Repository
+    {
+        return new static($this->entityClass, $this->alias, $this->adapter);
+    }
 }
diff --git a/src/Repository/MysqlRepository.php b/src/Repository/MysqlRepository.php
new file mode 100644
index 0000000..b12d87d
--- /dev/null
+++ b/src/Repository/MysqlRepository.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\{Common\EntityResolver, ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus};
+
+class MysqlRepository extends Repository {
+
+    public function pragma(/*object|Stringable*/ $pragma, $argument = null, bool $callable = false) : self
+    {
+        $this->queryBuilder->pragma($pragma, $argument, $callable);
+
+        return $this;
+    }
+
+    public function createSqlQuery() : self
+    {
+        if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
+            if ( $engine = $this->entityResolver->tableAnnotation()->engine ?? $this->entityResolver->databaseAdapter()->adapter()->defaultEngine() ) {
+                $this->queryBuilder->engine($engine);
+            }
+        }
+
+        return parent::createSqlQuery();
+    }
+}
diff --git a/src/Repository/SqliteRepository.php b/src/Repository/SqliteRepository.php
new file mode 100644
index 0000000..6392fe1
--- /dev/null
+++ b/src/Repository/SqliteRepository.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\{ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus};
+
+class SqliteRepository extends Repository {
+
+    public function pragma(/*object|Stringable*/ $pragma, $argument = null, bool $callable = false) : self
+    {
+        $this->queryBuilder->pragma($pragma, $argument, $callable);
+
+        return $this;
+    }
+
+    protected function finalizeQuery() : void
+    {
+
+    }
+
+    protected function serverRequestCountRepository() : Repository
+    {
+        return new static($this->entityClass, $this->alias, $this->adapter);
+    }
+}
diff --git a/src/SearchRequest/SearchRequestPaginationTrait.php b/src/SearchRequest/SearchRequestPaginationTrait.php
index 912b862..e93cc72 100644
--- a/src/SearchRequest/SearchRequestPaginationTrait.php
+++ b/src/SearchRequest/SearchRequestPaginationTrait.php
@@ -41,4 +41,10 @@ trait SearchRequestPaginationTrait {
     {
         return $this->pageCount() > 1;
     }
+    public function skipCount(bool $value) : self
+    {
+        $this->skipCount = $value;
+
+        return $this;
+    }
 }
diff --git a/src/Ulmus.php b/src/Ulmus.php
index 07fa13c..258a6a6 100644
--- a/src/Ulmus.php
+++ b/src/Ulmus.php
@@ -102,14 +102,18 @@ abstract class Ulmus
         return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
     }
 
-    public static function repository(...$arguments) : Repository
+    public static function repository(string $entityClass, ...$arguments) : Repository
     {
-        return new static::$repositoryClass(...$arguments);
+        $cls = $entityClass::resolveEntity()->sqlAdapter()->adapter()->repositoryClass();
+
+        return new $cls($entityClass, ...$arguments);
     }
 
-    public static function queryBuilder(...$arguments) : Query\QueryBuilderInterface
+    public static function queryBuilder($entityClass, ...$arguments) : Query\QueryBuilderInterface
     {
-        return new static::$queryBuilderClass(...$arguments);
+        $cls = $entityClass::resolveEntity()->sqlAdapter()->adapter()->queryBuilderClass();
+
+        return new $cls(...$arguments);
     }
     
     public static function instanciateObject(string $type, array $arguments) : object