Remove ID col from doc table
This commit is contained in:
parent
9af41447b7
commit
1e6d984d95
@ -98,7 +98,7 @@ class Data
|
||||
Query::whereJsonPathMatches('$2'));
|
||||
$params = [
|
||||
Query::jsonbDocParam([ 'userId' => $userId ]),
|
||||
sprintf("$.history[0].status ? (@ $op \"%s\")", RequestAction::Answered->name)
|
||||
sprintf('$.history[0].status ? (@ %s "%s")', $op, RequestAction::Answered->name)
|
||||
];
|
||||
return self::mapToJournalRequest(
|
||||
Document::customList($sql, $params, Request::class, Document::mapFromJson(...)), true);
|
||||
|
@ -11,7 +11,7 @@ use PgSql\Connection;
|
||||
class Configuration
|
||||
{
|
||||
/** @var string $connectionString The connection string to use when establishing a database connection */
|
||||
public static string $connectionString = "";
|
||||
public static string $connectionString = '';
|
||||
|
||||
/** @var ?Connection $pgConn The active connection */
|
||||
private static ?Connection $pgConn = null;
|
||||
@ -19,6 +19,9 @@ class Configuration
|
||||
/** @var ?string $startUp The name of a function to run on first connection to the database */
|
||||
public static ?string $startUp = null;
|
||||
|
||||
/** @var string $keyName The key name for document IDs (default "id") */
|
||||
public static string $keyName = 'id';
|
||||
|
||||
/**
|
||||
* Ensure that the connection string is set, either explicitly, by environment variables, or with defaults
|
||||
*/
|
||||
|
@ -18,7 +18,19 @@ class Definition
|
||||
*/
|
||||
public static function createTable(string $name): string
|
||||
{
|
||||
return "CREATE TABLE IF NOT EXISTS $name (id TEXT NOT NULL PRIMARY KEY, data JSONB NOT NULL)";
|
||||
return "CREATE TABLE IF NOT EXISTS $name (data JSONB NOT NULL)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a statement to create a key for a document table
|
||||
*
|
||||
* @param string $tableName The table (or schema/table) for which a key should be created
|
||||
* @return string A `CREATE INDEX` statement for a unique key for the document table
|
||||
*/
|
||||
public static function createKey(string $tableName): string
|
||||
{
|
||||
return sprintf('CREATE UNIQUE INDEX IF NOT EXISTS idx_%s_key ON %s ((data -> \'%s\'))',
|
||||
self::extractTable($tableName), $tableName, Configuration::$keyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,21 +42,21 @@ class Definition
|
||||
*/
|
||||
public static function createIndex(string $name, DocumentIndex $type): string
|
||||
{
|
||||
$extraOps = $type == DocumentIndex::Full ? '' : ' jsonb_path_ops';
|
||||
$schemaAndTable = explode('.', $name);
|
||||
$tableName = end($schemaAndTable);
|
||||
return "CREATE INDEX IF NOT EXISTS idx_$tableName ON $name USING GIN (data$extraOps)";
|
||||
return sprintf('CREATE INDEX IF NOT EXISTS idx_%s ON %s USING GIN (data%s)',
|
||||
self::extractTable($name), $name, $type == DocumentIndex::Full ? '' : ' jsonb_path_ops');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the given document table exists
|
||||
*
|
||||
* @param string $name The name of the table
|
||||
* @param string $tableName The name of the table
|
||||
*/
|
||||
public static function ensureTable(string $name): void
|
||||
public static function ensureTable(string $tableName): void
|
||||
{
|
||||
/** @var Result|bool $result */
|
||||
$result = pg_query(pg_conn(), self::createTable($name));
|
||||
$result = pg_query(pg_conn(), self::createTable($tableName));
|
||||
if ($result) pg_free_result($result);
|
||||
$result = pg_query(pg_conn(), self::createKey($tableName));
|
||||
if ($result) pg_free_result($result);
|
||||
}
|
||||
|
||||
@ -60,4 +72,16 @@ class Definition
|
||||
$result = pg_query(pg_conn(), self::createIndex($name, $type));
|
||||
if ($result) pg_free_result($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract just the table name from a possible `schema.table` name
|
||||
*
|
||||
* @param string $name The name of the table, possibly including the schema
|
||||
* @return string The table name
|
||||
*/
|
||||
private static function extractTable(string $name): string
|
||||
{
|
||||
$schemaAndTable = explode('.', $name);
|
||||
return end($schemaAndTable);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PgDocuments;
|
||||
|
||||
use Exception;
|
||||
use JsonMapper;
|
||||
use PgSql\Result;
|
||||
|
||||
@ -45,13 +46,17 @@ class Document
|
||||
|
||||
/**
|
||||
* Execute a document-focused statement that does not return results
|
||||
*
|
||||
*
|
||||
* @param string $query The query to be executed
|
||||
* @param string $docId The ID of the document on which action should be taken
|
||||
* @param array|object $document The array or object representing the document
|
||||
* @throws Exception If the document's ID is null
|
||||
*/
|
||||
private static function executeNonQuery(string $query, string $docId, array|object $document): void
|
||||
private static function executeNonQuery(string $query, array|object $document): void
|
||||
{
|
||||
$docId = is_array($document)
|
||||
? $document[Configuration::$keyName]
|
||||
: get_object_vars($document)[Configuration::$keyName];
|
||||
if (is_null($docId)) throw new Exception('PgDocument: ID cannot be NULL');
|
||||
/** @var Result|bool $result */
|
||||
$result = pg_query_params(pg_conn(), $query, [ $docId, Query::jsonbDocParam($document) ]);
|
||||
if ($result) pg_free_result($result);
|
||||
@ -61,24 +66,22 @@ class Document
|
||||
* Insert a document
|
||||
*
|
||||
* @param string $tableName The name of the table into which a document should be inserted
|
||||
* @param string $docId The ID of the document to be inserted
|
||||
* @param array|object $document The array or object representing the document
|
||||
*/
|
||||
public static function insert(string $tableName, string $docId, array|object $document): void
|
||||
public static function insert(string $tableName, array|object $document): void
|
||||
{
|
||||
self::executeNonQuery(Query::insert($tableName), $docId, $document);
|
||||
self::executeNonQuery(Query::insert($tableName), $document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save (upsert) a document
|
||||
*
|
||||
* @param string $tableName The name of the table into which a document should be inserted
|
||||
* @param string $docId The ID of the document to be inserted
|
||||
* @param array|object $document The array or object representing the document
|
||||
*/
|
||||
public static function save(string $tableName, string $docId, array|object $document): void
|
||||
public static function save(string $tableName, array|object $document): void
|
||||
{
|
||||
self::executeNonQuery(Query::save($tableName), $docId, $document);
|
||||
self::executeNonQuery(Query::save($tableName), $document);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,24 +294,22 @@ class Document
|
||||
* Update a full document
|
||||
*
|
||||
* @param string $tableName The table in which the document should be updated
|
||||
* @param string $docId The ID of the document to be updated
|
||||
* @param array|object $document The document to be updated
|
||||
*/
|
||||
public static function updateFull(string $tableName, string $docId, array|object $document): void
|
||||
public static function updateFull(string $tableName, array|object $document): void
|
||||
{
|
||||
self::executeNonQuery(Query::updateFull($tableName), $docId, $document);
|
||||
self::executeNonQuery(Query::updateFull($tableName), $document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a partial document by its ID
|
||||
*
|
||||
* @param string $tableName The table in which the document should be updated
|
||||
* @param string $docId The ID of the document to be updated
|
||||
* @param array|object $document The partial document to be updated
|
||||
*/
|
||||
public static function updatePartialById(string $tableName, string $docId, array|object $document): void
|
||||
public static function updatePartialById(string $tableName, array|object $document): void
|
||||
{
|
||||
self::executeNonQuery(Query::updatePartialById($tableName), $docId, $document);
|
||||
self::executeNonQuery(Query::updatePartialById($tableName), $document);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,7 +319,8 @@ class Document
|
||||
* @param array|object $criteria The JSON containment criteria
|
||||
* @param array|object $document The document to be updated
|
||||
*/
|
||||
public static function updatePartialByContains(string $tableName, array|object $criteria, array|object $document): void
|
||||
public static function updatePartialByContains(string $tableName, array|object $criteria,
|
||||
array|object $document): void
|
||||
{
|
||||
/** @var Result|bool $result */
|
||||
$result = pg_query_params(pg_conn(), Query::updatePartialByContains($tableName),
|
||||
@ -336,7 +338,7 @@ class Document
|
||||
public static function updatePartialByJsonPath(string $tableName, string $jsonPath, array|object $document): void
|
||||
{
|
||||
/** @var Result|bool $result */
|
||||
$result = pg_query_params(pg_conn(), Query::updatePartialByContains($tableName),
|
||||
$result = pg_query_params(pg_conn(), Query::updatePartialByJsonPath($tableName),
|
||||
[ $jsonPath, Query::jsonbDocParam($document) ]);
|
||||
if ($result) pg_free_result($result);
|
||||
}
|
||||
@ -349,7 +351,7 @@ class Document
|
||||
*/
|
||||
public static function deleteById(string $tableName, string $docId): void
|
||||
{
|
||||
self::executeNonQuery(Query::deleteById($tableName), $docId, []);
|
||||
self::executeNonQuery(Query::deleteById($tableName), [ Configuration::$keyName => $docId ]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,18 @@ class Query
|
||||
{
|
||||
return "SELECT data FROM $tableName";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a `WHERE` clause fragment to implement a key check condition
|
||||
*
|
||||
* @param string $paramName The name of the parameter to be replaced when the query is executed
|
||||
* @return string A `WHERE` clause fragment with the named key and parameter
|
||||
*/
|
||||
public static function whereById(string $paramName): string
|
||||
{
|
||||
return sprintf("data -> '%s' = %s", Configuration::$keyName, $paramName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `WHERE` clause fragment to implement a @> (JSON contains) condition
|
||||
*
|
||||
@ -50,33 +61,41 @@ class Query
|
||||
return json_encode($it);
|
||||
}
|
||||
|
||||
/// Create ID and data parameters for a query
|
||||
/* let docParameters<'T> docId (doc : 'T) =
|
||||
[ "@id", Sql.string docId; "@data", jsonbDocParam doc ]
|
||||
*/
|
||||
/**
|
||||
* Query to insert a document
|
||||
*
|
||||
* @param string $tableName The name of the table into which the document will be inserted
|
||||
* @return string The `INSERT` statement (with `@id` and `@data` parameters defined)
|
||||
* @return string The `INSERT` statement (with `$1` parameter defined for the document)
|
||||
*/
|
||||
public static function insert(string $tableName): string
|
||||
{
|
||||
return "INSERT INTO $tableName (id, data) VALUES ($1, $2)";
|
||||
return sprintf('INSERT INTO %s (data) VALUES ($1)', $tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
*
|
||||
* @param string $tableName The name of the table into which the document will be saved
|
||||
* @return string The `INSERT`/`ON CONFLICT DO UPDATE` statement (with `@id` and `@data` parameters defined)
|
||||
* @return string The `INSERT`/`ON CONFLICT DO UPDATE` statement (with `$1` parameter defined for the document)
|
||||
*/
|
||||
public static function save(string $tableName): string
|
||||
{
|
||||
return "INSERT INTO $tableName (id, data) VALUES ($1, $2)
|
||||
ON CONFLICT (id) DO UPDATE SET data = EXCLUDED.data";
|
||||
return sprintf('INSERT INTO %s (data) VALUES ($1) ON CONFLICT (data) DO UPDATE SET data = EXCLUDED.data',
|
||||
$tableName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query to count documents in a table
|
||||
*
|
||||
* @param string $tableName The name of the table for which documents should be counted
|
||||
* @param string $where The condition for which documents should be counted
|
||||
* @return string A `SELECT` statement to obtain the count of documents for the given table
|
||||
*/
|
||||
private static function countQuery(string $tableName, string $where): string
|
||||
{
|
||||
return "SELECT COUNT(*) AS it FROM $tableName WHERE $where";
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to count all documents in a table
|
||||
*
|
||||
@ -85,7 +104,7 @@ class Query
|
||||
*/
|
||||
public static function countAll(string $tableName): string
|
||||
{
|
||||
return "SELECT COUNT(id) AS it FROM $tableName";
|
||||
return self::countQuery($tableName, '1 = 1');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +115,7 @@ class Query
|
||||
*/
|
||||
public static function countByContains(string $tableName): string
|
||||
{
|
||||
return "SELECT COUNT(id) AS it FROM $tableName WHERE " . self::whereDataContains('$1');
|
||||
return self::countQuery($tableName, self::whereDataContains('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,9 +126,20 @@ class Query
|
||||
*/
|
||||
public static function countByJsonPath(string $tableName): string
|
||||
{
|
||||
return "SELECT COUNT(id) AS it FROM $tableName WHERE " . self::whereJsonPathMatches('$1');
|
||||
return self::countQuery($tableName, self::whereJsonPathMatches('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to check document existence
|
||||
*
|
||||
* @param string $tableName The name of the table in which document existence should be checked
|
||||
* @param string $where The criteria for which document existence should be checked
|
||||
* @return string A `SELECT` statement to check document existence for the given criteria
|
||||
*/
|
||||
private static function existsQuery(string $tableName, string $where): string
|
||||
{
|
||||
return "SELECT EXISTS (SELECT 1 FROM $tableName WHERE $where) AS it";
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to determine if a document exists for the given ID
|
||||
*
|
||||
@ -118,7 +148,7 @@ class Query
|
||||
*/
|
||||
public static function existsById(string $tableName): string
|
||||
{
|
||||
return "SELECT EXISTS (SELECT 1 FROM $tableName WHERE id = $1) AS it";
|
||||
return self::existsQuery($tableName, self::whereById('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +159,7 @@ class Query
|
||||
*/
|
||||
public static function existsByContains(string $tableName): string
|
||||
{
|
||||
return "SELECT EXISTS (SELECT 1 FROM $tableName WHERE " . self::whereDataContains('$1') . ' AS it';
|
||||
return self::existsQuery($tableName, self::whereDataContains('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,7 +170,7 @@ class Query
|
||||
*/
|
||||
public static function existsByJsonPath(string $tableName): string
|
||||
{
|
||||
return "SELECT EXISTS (SELECT 1 FROM $tableName WHERE " . self::whereJsonPathMatches('$1') . ' AS it';
|
||||
return self::existsQuery($tableName, self::whereJsonPathMatches('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +181,7 @@ class Query
|
||||
*/
|
||||
public static function findById(string $tableName): string
|
||||
{
|
||||
return self::selectFromTable($tableName) . ' WHERE id = $1';
|
||||
return sprintf('%s WHERE %s', self::selectFromTable($tableName), self::whereById('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,7 +192,7 @@ class Query
|
||||
*/
|
||||
public static function findByContains(string $tableName): string
|
||||
{
|
||||
return self::selectFromTable($tableName) . ' WHERE ' . self::whereDataContains('$1');
|
||||
return sprintf('%s WHERE %s', self::selectFromTable($tableName), self::whereDataContains('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,7 +203,7 @@ class Query
|
||||
*/
|
||||
public static function findByJsonPath(string $tableName): string
|
||||
{
|
||||
return self::selectFromTable($tableName) . ' WHERE ' . self::whereJsonPathMatches('$1');
|
||||
return sprintf('%s WHERE %s', self::selectFromTable($tableName), self::whereJsonPathMatches('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,7 +214,19 @@ class Query
|
||||
*/
|
||||
public static function updateFull(string $tableName): string
|
||||
{
|
||||
return "UPDATE $tableName SET data = $2 WHERE id = $1";
|
||||
return sprintf('UPDATE %s SET data = $2 WHERE %s', $tableName, self::whereById('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to apply a partial update to a document
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be updated
|
||||
* @param string $where The `WHERE` clause specifying which documents should be updated
|
||||
* @return string An `UPDATE` statement to update a partial document ($1 is ID, $2 is document)
|
||||
*/
|
||||
private static function updatePartial(string $tableName, string $where): string
|
||||
{
|
||||
return sprintf('UPDATE %s SET data = data || $2 WHERE %s', $tableName, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,7 +237,7 @@ class Query
|
||||
*/
|
||||
public static function updatePartialById(string $tableName): string
|
||||
{
|
||||
return "UPDATE $tableName SET data = data || $2 WHERE id = $1";
|
||||
return self::updatePartial($tableName, self::whereById('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,7 +248,7 @@ class Query
|
||||
*/
|
||||
public static function updatePartialByContains(string $tableName): string
|
||||
{
|
||||
return "UPDATE $tableName SET data = data || $2 WHERE " . self::whereDataContains('$1');
|
||||
return self::updatePartial($tableName, self::whereDataContains('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,7 +259,19 @@ class Query
|
||||
*/
|
||||
public static function updatePartialByJsonPath(string $tableName): string
|
||||
{
|
||||
return "UPDATE $tableName SET data = data || $2 WHERE " . self::whereJsonPathMatches('$1');
|
||||
return self::updatePartial($tableName, self::whereJsonPathMatches('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to delete documents
|
||||
*
|
||||
* @param string $tableName The name of the table from which documents should be deleted
|
||||
* @param string $where The criteria by which documents should be deleted
|
||||
* @return string A `DELETE` statement to delete documents in the specified table
|
||||
*/
|
||||
private static function deleteQuery(string $tableName, string $where): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE $where";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,7 +282,7 @@ class Query
|
||||
*/
|
||||
public static function deleteById(string $tableName): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE id = $1";
|
||||
return self::deleteQuery($tableName, self::whereById('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +293,7 @@ class Query
|
||||
*/
|
||||
public static function deleteByContains(string $tableName): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE " . self::whereDataContains('$1');
|
||||
return self::deleteQuery($tableName, self::whereDataContains('$1'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,6 +304,6 @@ class Query
|
||||
*/
|
||||
public static function deleteByJsonPath(string $tableName): string
|
||||
{
|
||||
return "DELETE FROM $tableName WHERE " . self::whereJsonPathMatches('$1');
|
||||
return self::deleteQuery($tableName, self::whereJsonPathMatches('$1'));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user