Changes for beta10 #5
|
@ -46,12 +46,48 @@ class Field
|
|||
$existing["{$this->paramName}min"] = $this->value[0];
|
||||
$existing["{$this->paramName}max"] = $this->value[1];
|
||||
break;
|
||||
case Op::In:
|
||||
for ($idx = 0; $idx < count($this->value); $idx++) {
|
||||
$existing["{$this->paramName}_$idx"] = $this->value[$idx];
|
||||
}
|
||||
break;
|
||||
case Op::InArray:
|
||||
$mkString = Configuration::mode("Append parameters for InArray condition") === Mode::PgSQL;
|
||||
$values = $this->value['values'];
|
||||
for ($idx = 0; $idx < count($values); $idx++) {
|
||||
$existing["{$this->paramName}_$idx"] = $mkString ? "$values[$idx]" : $values[$idx];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$existing[$this->paramName] = $this->value;
|
||||
}
|
||||
return $existing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the path for this field
|
||||
*
|
||||
* @param bool $asJSON Whether the field should be treated as JSON in the query (optional, default false)
|
||||
* @return string The path for this field
|
||||
* @throws Exception If the database mode has not been set
|
||||
*/
|
||||
public function path(bool $asJSON = false): string
|
||||
{
|
||||
$extra = $asJSON ? '' : '>';
|
||||
if (str_contains($this->fieldName, '.')) {
|
||||
$mode = Configuration::mode('determine field path');
|
||||
if ($mode === Mode::PgSQL) {
|
||||
return "data#>$extra'{" . implode(',', explode('.', $this->fieldName)) . "}'";
|
||||
}
|
||||
if ($mode === Mode::SQLite) {
|
||||
$parts = explode('.', $this->fieldName);
|
||||
$last = array_pop($parts);
|
||||
return "data->'" . implode("'->'", $parts) . "'->$extra'$last'";
|
||||
}
|
||||
}
|
||||
return "data->$extra'$this->fieldName'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WHERE clause fragment for this parameter
|
||||
*
|
||||
|
@ -60,27 +96,41 @@ class Field
|
|||
*/
|
||||
public function toWhere(): string
|
||||
{
|
||||
$mode = Configuration::mode('make field WHERE clause');
|
||||
$fieldName = (empty($this->qualifier) ? '' : "$this->qualifier.") . 'data' . match (true) {
|
||||
!str_contains($this->fieldName, '.') => "->>'$this->fieldName'",
|
||||
$mode === Mode::PgSQL => "#>>'{" . implode(',', explode('.', $this->fieldName)) . "}'",
|
||||
$mode === Mode::SQLite => "->>'" . implode("'->>'", explode('.', $this->fieldName)) . "'",
|
||||
};
|
||||
$fieldPath = match ($mode) {
|
||||
$mode = Configuration::mode('make field WHERE clause');
|
||||
$fieldName = (empty($this->qualifier) ? '' : "$this->qualifier.") . $this->path($this->op === Op::InArray);
|
||||
$fieldPath = match ($mode) {
|
||||
Mode::PgSQL => match (true) {
|
||||
$this->op === Op::Between => is_numeric($this->value[0]) ? "($fieldName)::numeric" : $fieldName,
|
||||
$this->op === Op::Between,
|
||||
$this->op === Op::In => is_numeric($this->value[0]) ? "($fieldName)::numeric" : $fieldName,
|
||||
is_numeric($this->value) => "($fieldName)::numeric",
|
||||
default => $fieldName,
|
||||
},
|
||||
default => $fieldName,
|
||||
};
|
||||
$criteria = match ($this->op) {
|
||||
Op::Exists, Op::NotExists => '',
|
||||
Op::Between => " {$this->paramName}min AND {$this->paramName}max",
|
||||
Op::In => "TODO",
|
||||
default => " $this->paramName",
|
||||
Op::Exists,
|
||||
Op::NotExists => '',
|
||||
Op::Between => " {$this->paramName}min AND {$this->paramName}max",
|
||||
Op::In => ' (' . $this->inParameterNames() . ')',
|
||||
Op::InArray => $mode === Mode::PgSQL ? ' ARRAY[' . $this->inParameterNames() . ']' : '',
|
||||
default => " $this->paramName",
|
||||
};
|
||||
return $fieldPath . ' ' . $this->op->toSQL() . $criteria;
|
||||
return $mode === Mode::SQLite && $this->op === Op::InArray
|
||||
? "EXISTS (SELECT 1 FROM json_each({$this->value['table']}.data, '\$.$this->fieldName') WHERE value IN ("
|
||||
. $this->inParameterNames() . '))'
|
||||
: $fieldPath . ' ' . $this->op->toSQL() . $criteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create parameter names for an IN clause
|
||||
*
|
||||
* @return string A comma-delimited string of parameter names
|
||||
*/
|
||||
private function inParameterNames(): string
|
||||
{
|
||||
$values = $this->op === Op::In ? $this->value : $this->value['values'];
|
||||
return implode(', ',
|
||||
array_map(fn($value, $key) => "{$this->paramName}_$key", $values, range(0, count($values) - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,13 +334,14 @@ class Field
|
|||
* Create an IN ARRAY field criterion
|
||||
*
|
||||
* @param string $fieldName The name of the field against which the values will be compared
|
||||
* @param string $tableName The table name where this field is located
|
||||
* @param mixed[] $values The potential matching values for the field
|
||||
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
|
||||
* @return self The field with the requested criterion
|
||||
*/
|
||||
public static function inArray(string $fieldName, array $values, string $paramName = ''): self
|
||||
public static function inArray(string $fieldName, string $tableName, array $values, string $paramName = ''): self
|
||||
{
|
||||
return new self($fieldName, Op::InArray, $values, $paramName);
|
||||
return new self($fieldName, Op::InArray, ['table' => $tableName, 'values' => $values], $paramName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,13 +18,13 @@ use PHPUnit\Framework\TestCase;
|
|||
#[TestDox('Configuration (Unit tests)')]
|
||||
class ConfigurationTest extends TestCase
|
||||
{
|
||||
#[TestDox('ID field default succeeds')]
|
||||
#[TestDox('id default succeeds')]
|
||||
public function testIdFieldDefaultSucceeds(): void
|
||||
{
|
||||
$this->assertEquals('id', Configuration::$idField, 'Default ID field should be "id"');
|
||||
}
|
||||
|
||||
#[TestDox('ID field change succeeds')]
|
||||
#[TestDox('id change succeeds')]
|
||||
public function testIdFieldChangeSucceeds(): void
|
||||
{
|
||||
try {
|
||||
|
@ -36,19 +36,19 @@ class ConfigurationTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('Auto ID default succeeds')]
|
||||
#[TestDox('autoId default succeeds')]
|
||||
public function testAutoIdDefaultSucceeds(): void
|
||||
{
|
||||
$this->assertEquals(AutoId::None, Configuration::$autoId, 'Auto ID should default to None');
|
||||
}
|
||||
|
||||
#[TestDox('ID string length default succeeds')]
|
||||
#[TestDox('idStringLength default succeeds')]
|
||||
public function testIdStringLengthDefaultSucceeds(): void
|
||||
{
|
||||
$this->assertEquals(16, Configuration::$idStringLength, 'ID string length should default to 16');
|
||||
}
|
||||
|
||||
#[TestDox("Db conn fails when no DSN specified")]
|
||||
#[TestDox("dbConn() fails when no DSN specified")]
|
||||
public function testDbConnFailsWhenNoDSNSpecified(): void
|
||||
{
|
||||
$this->expectException(DocumentException::class);
|
||||
|
|
|
@ -38,6 +38,7 @@ class DocumentExceptionTest extends TestCase
|
|||
$this->assertNull($ex->getPrevious(), 'Prior exception should have been null');
|
||||
}
|
||||
|
||||
#[TestDox('toString() succeeds without code')]
|
||||
public function testToStringSucceedsWithoutCode(): void
|
||||
{
|
||||
$ex = new DocumentException('Test failure');
|
||||
|
@ -45,6 +46,7 @@ class DocumentExceptionTest extends TestCase
|
|||
'toString not generated correctly');
|
||||
}
|
||||
|
||||
#[TestDox('toString() succeeds with code')]
|
||||
public function testToStringSucceedsWithCode(): void
|
||||
{
|
||||
$ex = new DocumentException('Oof', -6);
|
||||
|
|
|
@ -18,13 +18,13 @@ use PHPUnit\Framework\TestCase;
|
|||
#[TestDox('Field Match (Unit tests)')]
|
||||
class FieldMatchTest extends TestCase
|
||||
{
|
||||
#[TestDox('To SQL succeeds for all')]
|
||||
#[TestDox('toSQL() succeeds for All')]
|
||||
public function testToSQLSucceedsForAll(): void
|
||||
{
|
||||
$this->assertEquals('AND', FieldMatch::All->toSQL(), 'All should have returned AND');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for any')]
|
||||
#[TestDox('toSQL() succeeds for Any')]
|
||||
public function testToSQLSucceedsForAny(): void
|
||||
{
|
||||
$this->assertEquals('OR', FieldMatch::Any->toSQL(), 'Any should have returned OR');
|
||||
|
|
|
@ -18,33 +18,166 @@ use PHPUnit\Framework\TestCase;
|
|||
#[TestDox('Field (Unit tests)')]
|
||||
class FieldTest extends TestCase
|
||||
{
|
||||
#[TestDox('appendParameter() succeeds for exists')]
|
||||
public function testAppendParameterSucceedsForExists(): void
|
||||
{
|
||||
$this->assertEquals([], Field::exists('exists')->appendParameter([]),
|
||||
'exists should not have appended a parameter');
|
||||
}
|
||||
|
||||
#[TestDox('Append parameter succeeds for notExists')]
|
||||
#[TestDox('appendParameter() succeeds for notExists')]
|
||||
public function testAppendParameterSucceedsForNotExists(): void
|
||||
{
|
||||
$this->assertEquals([], Field::notExists('absent')->appendParameter([]),
|
||||
'notExists should not have appended a parameter');
|
||||
}
|
||||
|
||||
#[TestDox('appendParameter() succeeds for between')]
|
||||
public function testAppendParameterSucceedsForBetween(): void
|
||||
{
|
||||
$this->assertEquals(['@nummin' => 5, '@nummax' => 9],
|
||||
Field::between('exists', 5, 9, '@num')->appendParameter([]),
|
||||
'BT should have appended min and max parameters');
|
||||
'Between should have appended min and max parameters');
|
||||
}
|
||||
|
||||
#[TestDox('appendParameter() succeeds for in')]
|
||||
public function testAppendParameterSucceedsForIn(): void
|
||||
{
|
||||
$this->assertEquals([':val_0' => 'test', ':val_1' => 'unit', ':val_2' => 'great'],
|
||||
Field::in('it', ['test', 'unit', 'great'], ':val')->appendParameter([]),
|
||||
'In should have appended 3 parameters for the input values');
|
||||
}
|
||||
|
||||
#[TestDox('appendParameter() succeeds for inArray for PostgreSQL')]
|
||||
public function testAppendParameterSucceedsForInArrayForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$this->assertEquals([':bit_0' => '2', ':bit_1' => '8', ':bit_2' => '64'],
|
||||
Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]),
|
||||
'InArray should have appended 3 string parameters for the input values');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('appendParameter() succeeds for inArray for SQLite')]
|
||||
public function testAppendParameterSucceedsForInArrayForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$this->assertEquals([':bit_0' => 2, ':bit_1' => 8, ':bit_2' => 64],
|
||||
Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]),
|
||||
'InArray should have appended 3 parameters for the input values');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('appendParameter() succeeds for others')]
|
||||
public function testAppendParameterSucceedsForOthers(): void
|
||||
{
|
||||
$this->assertEquals(['@test' => 33], Field::equal('the_field', 33, '@test')->appendParameter([]),
|
||||
'Field parameter not returned correctly');
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for exists without qualifier for PostgreSQL')]
|
||||
#[TestDox('path() succeeds for simple SQL path for PostgreSQL')]
|
||||
public function testPathSucceedsForSimpleSqlPathForPostgreSQL()
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$this->assertEquals("data->>'it'", Field::equal('it', 'that')->path(),
|
||||
'SQL value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for simple SQL path for SQLite')]
|
||||
public function testPathSucceedsForSimpleSqlPathForSQLite()
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$this->assertEquals("data->>'top'", Field::equal('top', 'that')->path(),
|
||||
'SQL value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for nested SQL path for PostgreSQL')]
|
||||
public function testPathSucceedsForNestedSqlPathForPostgreSQL()
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$this->assertEquals("data#>>'{parts,to,the,path}'", Field::equal('parts.to.the.path', '')->path(),
|
||||
'SQL value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for nested SQL path for SQLite')]
|
||||
public function testPathSucceedsForNestedSqlPathForSQLite()
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$this->assertEquals("data->'one'->'two'->>'three'", Field::equal('one.two.three', '')->path(),
|
||||
'SQL value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for simple JSON path for PostgreSQL')]
|
||||
public function testPathSucceedsForSimpleJsonPathForPostgreSQL()
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$this->assertEquals("data->'it'", Field::equal('it', 'that')->path(true),
|
||||
'JSON value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for simple JSON path for SQLite')]
|
||||
public function testPathSucceedsForSimpleJsonPathForSQLite()
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$this->assertEquals("data->'top'", Field::equal('top', 'that')->path(true),
|
||||
'JSON value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for nested JSON path for PostgreSQL')]
|
||||
public function testPathSucceedsForNestedJsonPathForPostgreSQL()
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$this->assertEquals("data#>'{parts,to,the,path}'", Field::equal('parts.to.the.path', '')->path(true),
|
||||
'JSON value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('path() succeeds for nested JSON path for SQLite')]
|
||||
public function testPathSucceedsForNestedJsonPathForSQLite()
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$this->assertEquals("data->'one'->'two'->'three'", Field::equal('one.two.three', '')->path(true),
|
||||
'SQL value path not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for exists without qualifier for PostgreSQL')]
|
||||
public function testToWhereSucceedsForExistsWithoutQualifierForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -56,7 +189,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for exists without qualifier for SQLite')]
|
||||
#[TestDox('toWhere() succeeds for exists without qualifier for SQLite')]
|
||||
public function testToWhereSucceedsForExistsWithoutQualifierForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -68,7 +201,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for notExists without qualifier for PostgreSQL')]
|
||||
#[TestDox('toWhere() succeeds for notExists without qualifier for PostgreSQL')]
|
||||
public function testToWhereSucceedsForNotExistsWithoutQualifierForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -80,7 +213,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for notExists without qualifier for SQLite')]
|
||||
#[TestDox('toWhere() succeeds for notExists without qualifier for SQLite')]
|
||||
public function testToWhereSucceedsForNotExistsWithoutQualifierForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -92,7 +225,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between without qualifier for SQLite')]
|
||||
#[TestDox('toWhere() succeeds for between without qualifier for SQLite')]
|
||||
public function testToWhereSucceedsForBetweenWithoutQualifierForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -104,7 +237,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between without qualifier for PostgreSQL with numeric range')]
|
||||
#[TestDox('toWhere() succeeds for between without qualifier for PostgreSQL with numeric range')]
|
||||
public function testToWhereSucceedsForBetweenWithoutQualifierForPostgreSQLWithNumericRange(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -116,7 +249,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between without qualifier for PostgreSQL with non-numeric range')]
|
||||
#[TestDox('toWhere() succeeds for between without qualifier for PostgreSQL with non-numeric range')]
|
||||
public function testToWhereSucceedsForBetweenWithoutQualifierForPostgreSQLWithNonNumericRange(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -129,7 +262,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between with qualifier for SQLite')]
|
||||
#[TestDox('toWhere() succeeds for between with qualifier for SQLite')]
|
||||
public function testToWhereSucceedsForBetweenWithQualifierForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -143,7 +276,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between with qualifier for PostgreSQL with numeric range')]
|
||||
#[TestDox('toWhere() succeeds for between with qualifier for PostgreSQL with numeric range')]
|
||||
public function testToWhereSucceedsForBetweenWithQualifierForPostgreSQLWithNumericRange(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -157,7 +290,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for between with qualifier for PostgreSQL with non-numeric range')]
|
||||
#[TestDox('toWhere() succeeds for between with qualifier for PostgreSQL with non-numeric range')]
|
||||
public function testToWhereSucceedsForBetweenWithQualifierForPostgreSQLWithNonNumericRange(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -171,7 +304,73 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for others without qualifier for PostgreSQL')]
|
||||
#[TestDox('toWhere() succeeds for in for PostgreSQL with non-numeric values')]
|
||||
public function testToWhereSucceedsForInForPostgreSQLWithNonNumericValues(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$field = Field::in('test', ['Atlanta', 'Chicago'], ':city');
|
||||
$this->assertEquals("data->>'test' IN (:city_0, :city_1)", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for in for PostgreSQL with numeric values')]
|
||||
public function testToWhereSucceedsForInForPostgreSQLWithNumericValues(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$field = Field::in('even', [2, 4, 6], ':nbr');
|
||||
$this->assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for in for SQLite')]
|
||||
public function testToWhereSucceedsForInForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$field = Field::in('test', ['Atlanta', 'Chicago'], ':city');
|
||||
$this->assertEquals("data->>'test' IN (:city_0, :city_1)", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for inArray for PostgreSQL')]
|
||||
public function testToWhereSucceedsForInArrayForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$field = Field::inArray('even', 'tbl', [2, 4, 6, 8], ':it');
|
||||
$this->assertEquals("data->'even' ?| ARRAY[:it_0, :it_1, :it_2, :it_3]", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for inArray for SQLite')]
|
||||
public function testToWhereSucceedsForInArrayForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$field = Field::inArray('test', 'tbl', ['Atlanta', 'Chicago'], ':city');
|
||||
$this->assertEquals(
|
||||
"EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))",
|
||||
$field->toWhere(), 'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('toWhere() succeeds for others without qualifier for PostgreSQL')]
|
||||
public function testToWhereSucceedsForOthersWithoutQualifierForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -183,7 +382,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds for others without qualifier for SQLite')]
|
||||
#[TestDox('toWhere() succeeds for others without qualifier for SQLite')]
|
||||
public function testToWhereSucceedsForOthersWithoutQualifierForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -195,7 +394,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with qualifier no parameter for PostgreSQL')]
|
||||
#[TestDox('toWhere() succeeds with qualifier no parameter for PostgreSQL')]
|
||||
public function testToWhereSucceedsWithQualifierNoParameterForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -209,7 +408,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with qualifier no parameter for SQLite')]
|
||||
#[TestDox('toWhere() succeeds with qualifier no parameter for SQLite')]
|
||||
public function testToWhereSucceedsWithQualifierNoParameterForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -223,7 +422,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with qualifier and parameter for PostgreSQL')]
|
||||
#[TestDox('toWhere() succeeds with qualifier and parameter for PostgreSQL')]
|
||||
public function testToWhereSucceedsWithQualifierAndParameterForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -237,7 +436,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with qualifier and parameter for SQLite')]
|
||||
#[TestDox('toWhere() succeeds with qualifier and parameter for SQLite')]
|
||||
public function testToWhereSucceedsWithQualifierAndParameterForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
|
@ -251,33 +450,7 @@ class FieldTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with sub-document for PostgreSQL')]
|
||||
public function testToWhereSucceedsWithSubDocumentForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
try {
|
||||
$field = Field::equal('sub.foo.bar', 22, '@it');
|
||||
$this->assertEquals("(data#>>'{sub,foo,bar}')::numeric = @it", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('To where succeeds with sub-document for SQLite')]
|
||||
public function testToWhereSucceedsWithSubDocumentForSQLite(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
try {
|
||||
$field = Field::equal('sub.foo.bar', 22, '@it');
|
||||
$this->assertEquals("data->>'sub'->>'foo'->>'bar' = @it", $field->toWhere(),
|
||||
'WHERE fragment not generated correctly');
|
||||
} finally {
|
||||
Configuration::overrideMode(null);
|
||||
}
|
||||
}
|
||||
|
||||
#[TestDox('equal succeeds without parameter')]
|
||||
#[TestDox('equal() succeeds without parameter')]
|
||||
public function testEqualSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::equal('my_test', 9);
|
||||
|
@ -288,7 +461,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('equal succeeds with parameter')]
|
||||
#[TestDox('equal() succeeds with parameter')]
|
||||
public function testEqualSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::equal('another_test', 'turkey', '@test');
|
||||
|
@ -299,7 +472,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@test', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('greater succeeds without parameter')]
|
||||
#[TestDox('greater() succeeds without parameter')]
|
||||
public function testGreaterSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::greater('your_test', 4);
|
||||
|
@ -310,7 +483,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('greater succeeds with parameter')]
|
||||
#[TestDox('greater() succeeds with parameter')]
|
||||
public function testGreaterSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::greater('more_test', 'chicken', '@value');
|
||||
|
@ -321,7 +494,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@value', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('greaterOrEqual succeeds without parameter')]
|
||||
#[TestDox('greaterOrEqual() succeeds without parameter')]
|
||||
public function testGreaterOrEqualSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::greaterOrEqual('their_test', 6);
|
||||
|
@ -332,7 +505,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('greaterOrEqual succeeds with parameter')]
|
||||
#[TestDox('greaterOrEqual() succeeds with parameter')]
|
||||
public function testGreaterOrEqualSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::greaterOrEqual('greater_test', 'poultry', '@cluck');
|
||||
|
@ -343,7 +516,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@cluck', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('less succeeds without parameter')]
|
||||
#[TestDox('less() succeeds without parameter')]
|
||||
public function testLessSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::less('z', 32);
|
||||
|
@ -354,7 +527,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('less succeeds with parameter')]
|
||||
#[TestDox('less() succeeds with parameter')]
|
||||
public function testLessSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::less('additional_test', 'fowl', '@boo');
|
||||
|
@ -365,7 +538,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@boo', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('lessOrEqual succeeds without parameter')]
|
||||
#[TestDox('lessOrEqual() succeeds without parameter')]
|
||||
public function testLessOrEqualSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::lessOrEqual('g', 87);
|
||||
|
@ -376,7 +549,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('lessOrEqual succeeds with parameter')]
|
||||
#[TestDox('lessOrEqual() succeeds with parameter')]
|
||||
public function testLessOrEqualSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::lessOrEqual('lesser_test', 'hen', '@woo');
|
||||
|
@ -387,7 +560,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@woo', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('notEqual succeeds without parameter')]
|
||||
#[TestDox('notEqual() succeeds without parameter')]
|
||||
public function testNotEqualSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::notEqual('j', 65);
|
||||
|
@ -398,7 +571,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('notEqual succeeds with parameter')]
|
||||
#[TestDox('notEqual() succeeds with parameter')]
|
||||
public function testNotEqualSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::notEqual('unequal_test', 'egg', '@zoo');
|
||||
|
@ -409,7 +582,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@zoo', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('between succeeds without parameter')]
|
||||
#[TestDox('between() succeeds without parameter')]
|
||||
public function testBetweenSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::between('k', 'alpha', 'zed');
|
||||
|
@ -420,7 +593,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('between succeeds with parameter')]
|
||||
#[TestDox('between() succeeds with parameter')]
|
||||
public function testBetweenSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::between('between_test', 18, 49, '@count');
|
||||
|
@ -431,7 +604,51 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('@count', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('exists succeeds')]
|
||||
#[TestDox('in() succeeds without parameter')]
|
||||
public function testInSucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::in('test', [1, 2, 3]);
|
||||
$this->assertNotNull($field, 'The field should not have been null');
|
||||
$this->assertEquals('test', $field->fieldName, 'Field name not filled correctly');
|
||||
$this->assertEquals(Op::In, $field->op, 'Operation not filled correctly');
|
||||
$this->assertEquals([1, 2, 3], $field->value, 'Value not filled correctly');
|
||||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('in() succeeds with parameter')]
|
||||
public function testInSucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::in('unit', ['a', 'b'], '@inParam');
|
||||
$this->assertNotNull($field, 'The field should not have been null');
|
||||
$this->assertEquals('unit', $field->fieldName, 'Field name not filled correctly');
|
||||
$this->assertEquals(Op::In, $field->op, 'Operation not filled correctly');
|
||||
$this->assertEquals(['a', 'b'], $field->value, 'Value not filled correctly');
|
||||
$this->assertEquals('@inParam', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('inArray() succeeds without parameter')]
|
||||
public function testInArraySucceedsWithoutParameter(): void
|
||||
{
|
||||
$field = Field::inArray('test', 'tbl', [1, 2, 3]);
|
||||
$this->assertNotNull($field, 'The field should not have been null');
|
||||
$this->assertEquals('test', $field->fieldName, 'Field name not filled correctly');
|
||||
$this->assertEquals(Op::InArray, $field->op, 'Operation not filled correctly');
|
||||
$this->assertEquals(['table' => 'tbl', 'values' => [1, 2, 3]], $field->value, 'Value not filled correctly');
|
||||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('inArray() succeeds with parameter')]
|
||||
public function testInArraySucceedsWithParameter(): void
|
||||
{
|
||||
$field = Field::inArray('unit', 'tab', ['a', 'b'], '@inAParam');
|
||||
$this->assertNotNull($field, 'The field should not have been null');
|
||||
$this->assertEquals('unit', $field->fieldName, 'Field name not filled correctly');
|
||||
$this->assertEquals(Op::InArray, $field->op, 'Operation not filled correctly');
|
||||
$this->assertEquals(['table' => 'tab', 'values' => ['a', 'b']], $field->value, 'Value not filled correctly');
|
||||
$this->assertEquals('@inAParam', $field->paramName, 'Parameter name not filled correctly');
|
||||
}
|
||||
|
||||
#[TestDox('exists() succeeds')]
|
||||
public function testExistsSucceeds(): void
|
||||
{
|
||||
$field = Field::exists('be_there');
|
||||
|
@ -442,7 +659,7 @@ class FieldTest extends TestCase
|
|||
$this->assertEquals('', $field->paramName, 'Parameter name should have been blank');
|
||||
}
|
||||
|
||||
#[TestDox('notExists succeeds')]
|
||||
#[TestDox('notExists() succeeds')]
|
||||
public function testNotExistsSucceeds(): void
|
||||
{
|
||||
$field = Field::notExists('be_absent');
|
||||
|
|
|
@ -18,19 +18,19 @@ use PHPUnit\Framework\TestCase;
|
|||
#[TestDox('Mode (Unit tests)')]
|
||||
class ModeTest extends TestCase
|
||||
{
|
||||
#[TestDox('Derive from DSN succeeds for PostgreSQL')]
|
||||
#[TestDox('deriveFromDSN() succeeds for PostgreSQL')]
|
||||
public function testDeriveFromDSNSucceedsForPostgreSQL(): void
|
||||
{
|
||||
$this->assertEquals(Mode::PgSQL, Mode::deriveFromDSN('pgsql:Host=localhost'), 'PostgreSQL mode incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('Derive from DSN succeeds for SQLite')]
|
||||
#[TestDox('deriveFromDSN() succeeds for SQLite')]
|
||||
public function testDeriveFromDSNSucceedsForSQLite(): void
|
||||
{
|
||||
$this->assertEquals(Mode::SQLite, Mode::deriveFromDSN('sqlite:data.db'), 'SQLite mode incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('Derive from DSN fails for MySQL')]
|
||||
#[TestDox('deriveFromDSN() fails for MySQL')]
|
||||
public function testDeriveFromDSNFailsForMySQL(): void
|
||||
{
|
||||
$this->expectException(DocumentException::class);
|
||||
|
|
|
@ -18,67 +18,67 @@ use PHPUnit\Framework\TestCase;
|
|||
#[TestDox('Op (Unit tests)')]
|
||||
class OpTest extends TestCase
|
||||
{
|
||||
#[TestDox('To SQL succeeds for Equal')]
|
||||
#[TestDox('toSQL() succeeds for Equal')]
|
||||
public function testToSQLSucceedsForEqual(): void
|
||||
{
|
||||
$this->assertEquals('=', Op::Equal->toSQL(), 'Equal SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for Greater')]
|
||||
#[TestDox('toSQL() succeeds for Greater')]
|
||||
public function testToSQLSucceedsForGreater(): void
|
||||
{
|
||||
$this->assertEquals('>', Op::Greater->toSQL(), 'Greater SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for GreaterOrEqual')]
|
||||
#[TestDox('toSQL() succeeds for GreaterOrEqual')]
|
||||
public function testToSQLSucceedsForGreaterOrEqual(): void
|
||||
{
|
||||
$this->assertEquals('>=', Op::GreaterOrEqual->toSQL(), 'GreaterOrEqual SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for Less')]
|
||||
#[TestDox('toSQL() succeeds for Less')]
|
||||
public function testToSQLSucceedsForLess(): void
|
||||
{
|
||||
$this->assertEquals('<', Op::Less->toSQL(), 'Less SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for LessOrEqual')]
|
||||
#[TestDox('toSQL() succeeds for LessOrEqual')]
|
||||
public function testToSQLSucceedsForLessOrEqual(): void
|
||||
{
|
||||
$this->assertEquals('<=', Op::LessOrEqual->toSQL(), 'LessOrEqual SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for NotEqual')]
|
||||
#[TestDox('toSQL() succeeds for NotEqual')]
|
||||
public function testToSQLSucceedsForNotEqual(): void
|
||||
{
|
||||
$this->assertEquals('<>', Op::NotEqual->toSQL(), 'NotEqual SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for Between')]
|
||||
#[TestDox('toSQL() succeeds for Between')]
|
||||
public function testToSQLSucceedsForBetween(): void
|
||||
{
|
||||
$this->assertEquals('BETWEEN', Op::Between->toSQL(), 'Between SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for In')]
|
||||
#[TestDox('toSQL() succeeds for In')]
|
||||
public function testToSQLSucceedsForIn(): void
|
||||
{
|
||||
$this->assertEquals('IN', Op::In->toSQL(), 'In SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for InArray')]
|
||||
#[TestDox('toSQL() succeeds for InArray')]
|
||||
public function testToSQLSucceedsForInArray(): void
|
||||
{
|
||||
$this->assertEquals('?|', Op::InArray->toSQL(), 'InArray SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for Exists')]
|
||||
#[TestDox('toSQL() succeeds for Exists')]
|
||||
public function testToSQLSucceedsForExists(): void
|
||||
{
|
||||
$this->assertEquals('IS NOT NULL', Op::Exists->toSQL(), 'Exists SQL operator incorrect');
|
||||
}
|
||||
|
||||
#[TestDox('To SQL succeeds for NotExists')]
|
||||
#[TestDox('toSQL() succeeds for NotExists')]
|
||||
public function testToSQLSucceedsForNEX(): void
|
||||
{
|
||||
$this->assertEquals('IS NULL', Op::NotExists->toSQL(), 'NotExists SQL operator incorrect');
|
||||
|
|
|
@ -20,18 +20,19 @@ use Test\{PjsonDocument, PjsonId};
|
|||
#[TestDox('Parameters (Unit tests)')]
|
||||
class ParametersTest extends TestCase
|
||||
{
|
||||
#[TestDox('ID succeeds with string')]
|
||||
#[TestDox('id() succeeds with string')]
|
||||
public function testIdSucceedsWithString(): void
|
||||
{
|
||||
$this->assertEquals([':id' => 'key'], Parameters::id('key'), 'ID parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('ID succeeds with non string')]
|
||||
#[TestDox('id() succeeds with non string')]
|
||||
public function testIdSucceedsWithNonString(): void
|
||||
{
|
||||
$this->assertEquals([':id' => '7'], Parameters::id(7), 'ID parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json() succeeds for array')]
|
||||
public function testJsonSucceedsForArray(): void
|
||||
{
|
||||
$this->assertEquals([':it' => '{"id":18,"url":"https://www.unittest.com"}'],
|
||||
|
@ -39,20 +40,21 @@ class ParametersTest extends TestCase
|
|||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json() succeeds for array with empty array parameter')]
|
||||
public function testJsonSucceedsForArrayWithEmptyArrayParameter(): void
|
||||
{
|
||||
$this->assertEquals([':it' => '{"id":18,"urls":[]}'], Parameters::json(':it', ['id' => 18, 'urls' => []]),
|
||||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json succeeds for 1D array with empty array parameter')]
|
||||
#[TestDox('json() succeeds for 1D array with empty array parameter')]
|
||||
public function testJsonSucceedsFor1DArrayWithEmptyArrayParameter(): void
|
||||
{
|
||||
$this->assertEquals([':it' => '{"urls":[]}'], Parameters::json(':it', ['urls' => []]),
|
||||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json succeeds for stdClass')]
|
||||
#[TestDox('json() succeeds for stdClass')]
|
||||
public function testJsonSucceedsForStdClass(): void
|
||||
{
|
||||
$obj = new stdClass();
|
||||
|
@ -62,6 +64,7 @@ class ParametersTest extends TestCase
|
|||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json() succeeds for Pjson class')]
|
||||
public function testJsonSucceedsForPjsonClass(): void
|
||||
{
|
||||
$this->assertEquals([':it' => '{"id":"999","name":"a test","num_value":98}'],
|
||||
|
@ -69,6 +72,7 @@ class ParametersTest extends TestCase
|
|||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('json() succeeds for array of Pjson class')]
|
||||
public function testJsonSucceedsForArrayOfPjsonClass(): void
|
||||
{
|
||||
$this->assertEquals([':it' => '{"pjson":[{"id":"997","name":"another test","num_value":94}]}'],
|
||||
|
@ -77,6 +81,7 @@ class ParametersTest extends TestCase
|
|||
'JSON parameter not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('nameFields() succeeds')]
|
||||
public function testNameFieldsSucceeds(): void
|
||||
{
|
||||
$named = Parameters::nameFields(
|
||||
|
@ -87,6 +92,7 @@ class ParametersTest extends TestCase
|
|||
$this->assertEquals(':field2', $named[2]->paramName, 'Parameter 3 not named correctly');
|
||||
}
|
||||
|
||||
#[TestDox('addFields() succeeds')]
|
||||
public function testAddFieldsSucceeds(): void
|
||||
{
|
||||
$this->assertEquals([':a' => 1, ':b' => 'two', ':z' => 18],
|
||||
|
@ -94,7 +100,7 @@ class ParametersTest extends TestCase
|
|||
'Field parameters not added correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Field names succeeds for PostgreSQL')]
|
||||
#[TestDox('fieldNames() succeeds for PostgreSQL')]
|
||||
public function testFieldNamesSucceedsForPostgreSQL(): void
|
||||
{
|
||||
try {
|
||||
|
@ -106,7 +112,7 @@ class ParametersTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('Field names succeeds for SQLite')]
|
||||
#[TestDox('fieldNames() succeeds for SQLite')]
|
||||
public function testFieldNamesSucceedsForSQLite(): void
|
||||
{
|
||||
try {
|
||||
|
@ -118,6 +124,7 @@ class ParametersTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('fieldNames() fails when mode not set')]
|
||||
public function testFieldNamesFailsWhenModeNotSet(): void
|
||||
{
|
||||
$this->expectException(DocumentException::class);
|
||||
|
|
|
@ -28,12 +28,14 @@ class QueryTest extends TestCase
|
|||
Configuration::overrideMode(null);
|
||||
}
|
||||
|
||||
#[TestDox('selectFromTable() succeeds')]
|
||||
public function testSelectFromTableSucceeds(): void
|
||||
{
|
||||
$this->assertEquals('SELECT data FROM testing', Query::selectFromTable('testing'),
|
||||
'Query not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('whereByFields() succeeds for single field')]
|
||||
public function testWhereByFieldsSucceedsForSingleField(): void
|
||||
{
|
||||
$this->assertEquals("data->>'test_field' <= :it",
|
||||
|
@ -41,6 +43,7 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('whereByFields() succeeds for multiple fields All')]
|
||||
public function testWhereByFieldsSucceedsForMultipleFieldsAll(): void
|
||||
{
|
||||
$this->assertEquals("data->>'test_field' <= :it AND data->>'other_field' = :other",
|
||||
|
@ -49,6 +52,7 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('whereByFields() succeeds for multiple fields Any')]
|
||||
public function testWhereByFieldsSucceedsForMultipleFieldsAny(): void
|
||||
{
|
||||
$this->assertEquals("data->>'test_field' <= :it OR data->>'other_field' = :other",
|
||||
|
@ -58,18 +62,19 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Where by ID succeeds with default parameter')]
|
||||
#[TestDox('whereById() succeeds with default parameter')]
|
||||
public function testWhereByIdSucceedsWithDefaultParameter(): void
|
||||
{
|
||||
$this->assertEquals("data->>'id' = :id", Query::whereById(), 'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Where by ID succeeds with specific parameter')]
|
||||
#[TestDox('whereById() succeeds with specific parameter')]
|
||||
public function testWhereByIdSucceedsWithSpecificParameter(): void
|
||||
{
|
||||
$this->assertEquals("data->>'id' = :di", Query::whereById(':di'), 'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('whereDataContains() succeeds with default parameter')]
|
||||
public function testWhereDataContainsSucceedsWithDefaultParameter(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -77,13 +82,14 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('whereDataContains() succeeds with specific parameter')]
|
||||
public function testWhereDataContainsSucceedsWithSpecifiedParameter(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$this->assertEquals('data @> :it', Query::whereDataContains(':it'), 'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Where data contains fails if not PostgreSQL')]
|
||||
#[TestDox('whereDataContains() fails if not PostgreSQL')]
|
||||
public function testWhereDataContainsFailsIfNotPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(null);
|
||||
|
@ -91,7 +97,7 @@ class QueryTest extends TestCase
|
|||
Query::whereDataContains();
|
||||
}
|
||||
|
||||
#[TestDox('Where JSON Path matches succeeds with default parameter')]
|
||||
#[TestDox('whereJsonPathMatches() succeeds with default parameter')]
|
||||
public function testWhereJsonPathMatchesSucceedsWithDefaultParameter(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -99,7 +105,7 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Where JSON Path matches succeeds with specified parameter')]
|
||||
#[TestDox('whereJsonPathMatches() succeeds with specified parameter')]
|
||||
public function testWhereJsonPathMatchesSucceedsWithSpecifiedParameter(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -107,7 +113,7 @@ class QueryTest extends TestCase
|
|||
'WHERE fragment not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Where JSON Path matches fails if not PostgreSQL')]
|
||||
#[TestDox('whereJsonPathMatches() fails if not PostgreSQL')]
|
||||
public function testWhereJsonPathMatchesFailsIfNotPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(null);
|
||||
|
@ -115,7 +121,7 @@ class QueryTest extends TestCase
|
|||
Query::whereJsonPathMatches();
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with no auto-ID for PostgreSQL')]
|
||||
#[TestDox('insert() succeeds with no auto-ID for PostgreSQL')]
|
||||
public function testInsertSucceedsWithNoAutoIdForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -123,14 +129,14 @@ class QueryTest extends TestCase
|
|||
'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with no auto-ID for SQLite')]
|
||||
#[TestDox('insert() succeeds with no auto-ID for SQLite')]
|
||||
public function testInsertSucceedsWithNoAutoIdForSQLite(): void
|
||||
{
|
||||
$this->assertEquals('INSERT INTO test_tbl VALUES (:data)', Query::insert('test_tbl'),
|
||||
'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto numeric ID for PostgreSQL')]
|
||||
#[TestDox('insert() succeeds with auto numeric ID for PostgreSQL')]
|
||||
public function testInsertSucceedsWithAutoNumericIdForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -140,7 +146,7 @@ class QueryTest extends TestCase
|
|||
Query::insert('test_tbl', AutoId::Number), 'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto numeric ID for SQLite')]
|
||||
#[TestDox('insert() succeeds with auto numeric ID for SQLite')]
|
||||
public function testInsertSucceedsWithAutoNumericIdForSQLite(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
|
@ -149,7 +155,7 @@ class QueryTest extends TestCase
|
|||
Query::insert('test_tbl', AutoId::Number), 'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto UUID for PostgreSQL')]
|
||||
#[TestDox('insert() succeeds with auto UUID for PostgreSQL')]
|
||||
public function testInsertSucceedsWithAutoUuidForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -159,7 +165,7 @@ class QueryTest extends TestCase
|
|||
$this->assertStringEndsWith("\"}')", $query, 'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto UUID for SQLite')]
|
||||
#[TestDox('insert() succeeds with auto UUID for SQLite')]
|
||||
public function testInsertSucceedsWithAutoUuidForSQLite(): void
|
||||
{
|
||||
$query = Query::insert('test_tbl', AutoId::UUID);
|
||||
|
@ -168,7 +174,7 @@ class QueryTest extends TestCase
|
|||
$this->assertStringEndsWith("'))", $query, 'INSERT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto random string for PostgreSQL')]
|
||||
#[TestDox('insert() succeeds with auto random string for PostgreSQL')]
|
||||
public function testInsertSucceedsWithAutoRandomStringForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
|
@ -185,7 +191,7 @@ class QueryTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
#[TestDox('Insert succeeds with auto random string for SQLite')]
|
||||
#[TestDox('insert() succeeds with auto random string for SQLite')]
|
||||
public function testInsertSucceedsWithAutoRandomStringForSQLite(): void
|
||||
{
|
||||
$query = Query::insert('test_tbl', AutoId::RandomString);
|
||||
|
@ -196,6 +202,7 @@ class QueryTest extends TestCase
|
|||
$this->assertEquals(16, strlen($id), "Generated ID [$id] should have been 16 characters long");
|
||||
}
|
||||
|
||||
#[TestDox('insert() fails when mode not set')]
|
||||
public function testInsertFailsWhenModeNotSet(): void
|
||||
{
|
||||
$this->expectException(DocumentException::class);
|
||||
|
@ -203,6 +210,7 @@ class QueryTest extends TestCase
|
|||
Query::insert('kaboom');
|
||||
}
|
||||
|
||||
#[TestDox('save() succeeds')]
|
||||
public function testSaveSucceeds(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
|
@ -210,6 +218,7 @@ class QueryTest extends TestCase
|
|||
Query::save('test_tbl'), 'INSERT ON CONFLICT statement not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('update() succeeds')]
|
||||
public function testUpdateSucceeds(): void
|
||||
{
|
||||
$this->assertEquals("UPDATE testing SET data = :data WHERE data->>'id' = :id", Query::update('testing'),
|
||||
|
|
Loading…
Reference in New Issue
Block a user