Initial SQLite development (#1)
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
35
src/Query/Count.php
Normal file
35
src/Query/Count.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Field, Query};
|
||||
|
||||
/**
|
||||
* Queries for counting documents
|
||||
*/
|
||||
class Count
|
||||
{
|
||||
/**
|
||||
* Query to count all documents in a table
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be counted
|
||||
* @return string The query to count all documents in a table
|
||||
*/
|
||||
public static function all(string $tableName): string
|
||||
{
|
||||
return "SELECT COUNT(*) FROM $tableName";
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to count matching documents using a text comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be counted
|
||||
* @param Field[] $fields The field comparison to match
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The query to count documents using a field comparison
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): string
|
||||
{
|
||||
return self::all($tableName) . ' WHERE ' . Query::whereByFields($fields, $conjunction);
|
||||
}
|
||||
}
|
||||
71
src/Query/Definition.php
Normal file
71
src/Query/Definition.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, DocumentException, Mode};
|
||||
|
||||
/**
|
||||
* Queries to define tables and indexes
|
||||
*/
|
||||
class Definition
|
||||
{
|
||||
/**
|
||||
* SQL statement to create a document table
|
||||
*
|
||||
* @param string $name The name of the table (including schema, if applicable)
|
||||
* @return string The CREATE TABLE statement for the document table
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function ensureTable(string $name): string
|
||||
{
|
||||
$dataType = match (Configuration::$mode) {
|
||||
Mode::PgSQL => 'JSONB',
|
||||
Mode::SQLite => 'TEXT',
|
||||
default => throw new DocumentException('Database mode not set; cannot make create table statement')
|
||||
};
|
||||
return "CREATE TABLE IF NOT EXISTS $name (data $dataType NOT NULL)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a schema and table name
|
||||
*
|
||||
* @param string $tableName The name of the table, possibly including the schema
|
||||
* @return array|string[] An array with the schema at index 0 and the table name at index 1
|
||||
*/
|
||||
private static function splitSchemaAndTable(string $tableName): array
|
||||
{
|
||||
$parts = explode('.', $tableName);
|
||||
return sizeof($parts) == 1 ? ["", $tableName] : [$parts[0], $parts[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL statement to create an index on one or more fields in a JSON document
|
||||
*
|
||||
* @param string $tableName The name of the table which should be indexed
|
||||
* @param string $indexName The name of the index to create
|
||||
* @param array $fields An array of fields to be indexed; may contain direction (ex. 'salary DESC')
|
||||
* @return string The CREATE INDEX statement to ensure the index exists
|
||||
*/
|
||||
public static function ensureIndexOn(string $tableName, string $indexName, array $fields): string
|
||||
{
|
||||
[, $tbl] = self::splitSchemaAndTable($tableName);
|
||||
$jsonFields = implode(', ', array_map(function (string $field) {
|
||||
$parts = explode(' ', $field);
|
||||
$fieldName = sizeof($parts) == 1 ? $field : $parts[0];
|
||||
$direction = sizeof($parts) < 2 ? "" : " $parts[1]";
|
||||
return "(data->>'$fieldName')$direction";
|
||||
}, $fields));
|
||||
return "CREATE INDEX IF NOT EXISTS idx_{$tbl}_$indexName ON $tableName ($jsonFields)";
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL statement to create a key index for a document table
|
||||
*
|
||||
* @param string $tableName The name of the table whose key should be ensured
|
||||
* @return string The CREATE INDEX statement to ensure the key index exists
|
||||
*/
|
||||
public static function ensureKey(string $tableName): string
|
||||
{
|
||||
return str_replace('INDEX', 'UNIQUE INDEX', self::ensureIndexOn($tableName, 'key', [Configuration::$idField]));
|
||||
}
|
||||
}
|
||||
35
src/Query/Delete.php
Normal file
35
src/Query/Delete.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Field, Query};
|
||||
|
||||
/**
|
||||
* Queries to delete documents
|
||||
*/
|
||||
class Delete
|
||||
{
|
||||
/**
|
||||
* Query to delete a document by its ID
|
||||
*
|
||||
* @param string $tableName The name of the table from which a document should be deleted
|
||||
* @return string The DELETE statement to delete a document by its ID
|
||||
*/
|
||||
public static function byId(string $tableName): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE " . Query::whereById();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to delete documents using a comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The name of the table from which documents should be deleted
|
||||
* @param Field[] $fields The field comparison to match
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The DELETE statement to delete documents via field comparison
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE " . Query::whereByFields($fields, $conjunction);
|
||||
}
|
||||
}
|
||||
47
src/Query/Exists.php
Normal file
47
src/Query/Exists.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Field, Query};
|
||||
|
||||
/**
|
||||
* Queries to determine document existence
|
||||
*/
|
||||
class Exists
|
||||
{
|
||||
/**
|
||||
* The shell of a query for an existence check
|
||||
*
|
||||
* @param string $tableName The name of the table in which existence should be checked
|
||||
* @param string $whereClause The conditions for which existence should be checked
|
||||
* @return string The query to determine existence of documents
|
||||
*/
|
||||
public static function query(string $tableName, string $whereClause): string
|
||||
{
|
||||
return "SELECT EXISTS (SELECT 1 FROM $tableName WHERE $whereClause)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to determine if a document exists for the given ID
|
||||
*
|
||||
* @param string $tableName The name of the table in which document existence should be checked
|
||||
* @return string The query to determine document existence by ID
|
||||
*/
|
||||
public static function byId(string $tableName): string
|
||||
{
|
||||
return self::query($tableName, Query::whereById());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to determine if documents exist using a comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The name of the table in which document existence should be checked
|
||||
* @param Field[] $fields The field comparison to match
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The query to determine document existence by field comparison
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): string
|
||||
{
|
||||
return self::query($tableName, Query::whereByFields($fields, $conjunction));
|
||||
}
|
||||
}
|
||||
35
src/Query/Find.php
Normal file
35
src/Query/Find.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Field, Query};
|
||||
|
||||
/**
|
||||
* Queries for retrieving documents
|
||||
*/
|
||||
class Find
|
||||
{
|
||||
/**
|
||||
* Query to retrieve a document by its ID
|
||||
*
|
||||
* @param string $tableName The name of the table from which a document should be retrieved
|
||||
* @return string The SELECT statement to retrieve a document by its ID
|
||||
*/
|
||||
public static function byId(string $tableName): string
|
||||
{
|
||||
return Query::selectFromTable($tableName) . ' WHERE ' . Query::whereById();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to retrieve documents using a comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The name of the table from which documents should be retrieved
|
||||
* @param Field[] $fields The field comparison to match
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The SELECT statement to retrieve documents by field comparison
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): string
|
||||
{
|
||||
return Query::selectFromTable($tableName) . ' WHERE ' . Query::whereByFields($fields, $conjunction);
|
||||
}
|
||||
}
|
||||
55
src/Query/Patch.php
Normal file
55
src/Query/Patch.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Query};
|
||||
|
||||
/**
|
||||
* Queries to perform partial updates on documents
|
||||
*/
|
||||
class Patch
|
||||
{
|
||||
/**
|
||||
* Create an UPDATE statement to patch documents
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be patched
|
||||
* @param string $whereClause The body of the WHERE clause to use in the UPDATE statement
|
||||
* @return string The UPDATE statement to perform the patch
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function update(string $tableName, string $whereClause): string
|
||||
{
|
||||
$setValue = match (Configuration::$mode) {
|
||||
Mode::PgSQL => 'data || :data',
|
||||
Mode::SQLite => 'json_patch(data, json(:data))',
|
||||
default => throw new DocumentException('Database mode not set; cannot make patch statement')
|
||||
};
|
||||
return "UPDATE $tableName SET data = $setValue WHERE $whereClause";
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to patch (partially update) a document by its ID
|
||||
*
|
||||
* @param string $tableName The name of the table in which a document should be patched
|
||||
* @return string The query to patch a document by its ID
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byId(string $tableName): string
|
||||
{
|
||||
return self::update($tableName, Query::whereById());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to patch (partially update) a document via a comparison on a JSON field
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be patched
|
||||
* @param array|Field[] $field The field comparison to match
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The query to patch documents via field comparison
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byFields(string $tableName, array $field, string $conjunction = 'AND'): string
|
||||
{
|
||||
return self::update($tableName, Query::whereByFields($field, $conjunction));
|
||||
}
|
||||
}
|
||||
66
src/Query/RemoveFields.php
Normal file
66
src/Query/RemoveFields.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Query};
|
||||
|
||||
/**
|
||||
* Queries to remove fields from documents
|
||||
*
|
||||
* _NOTE: When using these queries to build custom functions, be aware that different databases use significantly
|
||||
* different syntax. The `$parameters` passed to these functions should be run through `Parameters::fieldNames`
|
||||
* function to generate them appropriately for the database currently being targeted._
|
||||
*/
|
||||
class RemoveFields
|
||||
{
|
||||
/**
|
||||
* Create an UPDATE statement to remove fields from a JSON document
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be manipulated
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @param string $whereClause The body of the WHERE clause for the update
|
||||
* @return string The UPDATE statement to remove fields from a JSON document
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function update(string $tableName, array $parameters, string $whereClause): string
|
||||
{
|
||||
switch (Configuration::$mode) {
|
||||
case Mode::PgSQL:
|
||||
return "UPDATE $tableName SET data = data - " . array_keys($parameters)[0] . " WHERE $whereClause";
|
||||
case Mode::SQLite:
|
||||
$paramNames = implode(', ', array_keys($parameters));
|
||||
return "UPDATE $tableName SET data = json_remove(data, $paramNames) WHERE $whereClause";
|
||||
default:
|
||||
throw new DocumentException('Database mode not set; cannot generate field removal query');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to remove fields from a document by the document's ID
|
||||
*
|
||||
* @param string $tableName The name of the table in which the document should be manipulated
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @return string The UPDATE statement to remove fields from a document by its ID
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byId(string $tableName, array $parameters): string
|
||||
{
|
||||
return self::update($tableName, $parameters, Query::whereById());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to remove fields from documents via a comparison on JSON fields within the document
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be manipulated
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The UPDATE statement to remove fields from documents via field comparison
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, array $parameters,
|
||||
string $conjunction = 'AND'): string
|
||||
{
|
||||
return self::update($tableName, $parameters, Query::whereByFields($fields, $conjunction));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user