419 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			419 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @author Daniel J. Summers <daniel@bitbadger.solutions>
 | |
|  * @license MIT
 | |
|  */
 | |
| 
 | |
| declare(strict_types=1);
 | |
| 
 | |
| use BitBadger\PDODocument\{Configuration, Field, Mode, Op};
 | |
| 
 | |
| pest()->group('unit');
 | |
| 
 | |
| describe('->appendParameter()', function () {
 | |
|     afterEach(function () { Configuration::overrideMode(null); });
 | |
|     test('appends no parameter for exists', function () {
 | |
|         expect(Field::exists('exists')->appendParameter([]))->toBeEmpty();
 | |
|     });
 | |
|     test('appends no parameter for notExists', function () {
 | |
|         expect(Field::notExists('absent')->appendParameter([]))->toBeEmpty();
 | |
|     });
 | |
|     test('appends two parameters for between', function () {
 | |
|         expect(Field::between('exists', 5, 9, '@num')->appendParameter([]))
 | |
|             ->toHaveLength(2)
 | |
|             ->toEqual(['@nummin' => 5, '@nummax' => 9]);
 | |
|     });
 | |
|     test('appends a parameter for each value for in', function () {
 | |
|         expect(Field::in('it', ['test', 'unit', 'great'], ':val')->appendParameter([]))
 | |
|             ->toHaveLength(3)
 | |
|             ->toEqual([':val_0' => 'test', ':val_1' => 'unit', ':val_2' => 'great']);
 | |
|     });
 | |
|     test('appends a parameter for each value for inArray [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]))
 | |
|             ->toHaveLength(3)
 | |
|             ->toEqual([':bit_0' => '2', ':bit_1' => '8', ':bit_2' => '64']);
 | |
|     })->group('postgresql');
 | |
|     test('appends a parameter for each value for inArray [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]))
 | |
|             ->toHaveLength(3)
 | |
|             ->toEqual([':bit_0' => 2, ':bit_1' => 8, ':bit_2' => 64]);
 | |
|     })->group('sqlite');
 | |
|     test('appends a parameter for other operators', function () {
 | |
|         expect(Field::equal('the_field', 33, ':test')->appendParameter([]))
 | |
|             ->toHaveLength(1)
 | |
|             ->toEqual([':test' => 33]);
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('->path()', function () {
 | |
|     afterEach(function () { Configuration::overrideMode(null); });
 | |
|     test('returns simple SQL path [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::equal('it', 'that'))->path()->toBe("data->>'it'");
 | |
|     })->group('postgresql');
 | |
|     test('returns simple SQL path [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::equal('top', 'that'))->path()->toBe("data->>'top'");
 | |
|     })->group('sqlite');
 | |
|     test('returns nested SQL path [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::equal('parts.to.the.path', ''))->path()->toBe("data#>>'{parts,to,the,path}'");
 | |
|     })->group('postgresql');
 | |
|     test('returns nested SQL path [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::equal('one.two.three', ''))->path()->toBe("data->'one'->'two'->>'three'");
 | |
|     })->group('sqlite');
 | |
|     test('returns simple JSON path [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::equal('it', 'that'))->path(true)->toBe("data->'it'");
 | |
|     })->group('postgresql');
 | |
|     test('returns simple JSON path [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::equal('top', 'that'))->path(true)->toBe("data->'top'");
 | |
|     })->group('sqlite');
 | |
|     test('returns nested JSON path [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::equal('parts.to.the.path', ''))->path(true)->toBe("data#>'{parts,to,the,path}'");
 | |
|     })->group('postgresql');
 | |
|     test('returns nested JSON path [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::equal('one.two.three', ''))->path(true)->toBe("data->'one'->'two'->'three'");
 | |
|     })->group('sqlite');
 | |
| });
 | |
| 
 | |
| describe('->toWhere()', function () {
 | |
|     afterEach(function () { Configuration::overrideMode(null); });
 | |
|     test('generates IS NOT NULL for exists w/o qualifier [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL");
 | |
|     })->group('postgresql');
 | |
|     test('generates IS NOT NULL for exists w/o qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL");
 | |
|     })->group('sqlite');
 | |
|     test('generates IS NULL for notExists w/o qualifier [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL");
 | |
|     })->group('postgresql');
 | |
|     test('generates IS NULL for notExists w/o qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL");
 | |
|     })->group('sqlite');
 | |
|     test('generates BETWEEN for between w/o qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::between('age', 13, 17, '@age'))->toWhere()->toBe("data->>'age' BETWEEN @agemin AND @agemax");
 | |
|     })->group('sqlite');
 | |
|     test('generates BETWEEN for between w/o qualifier, numeric range [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::between('age', 13, 17, '@age'))->toWhere()
 | |
|             ->toBe("(data->>'age')::numeric BETWEEN @agemin AND @agemax");
 | |
|     })->group('postgresql');
 | |
|     test('generates BETWEEN for between w/o qualifier, non-numeric range [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::between('city', 'Atlanta', 'Chicago', ':city'))->toWhere()
 | |
|             ->toBe("data->>'city' BETWEEN :citymin AND :citymax");
 | |
|     })->group('postgresql');
 | |
|     test('generates BETWEEN for between w/ qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         $field = Field::between('age', 13, 17, '@age');
 | |
|         $field->qualifier = 'me';
 | |
|         expect($field)->toWhere()->toBe("me.data->>'age' BETWEEN @agemin AND @agemax");
 | |
|     })->group('sqlite');
 | |
|     test('generates BETWEEN for between w/ qualifier, numeric range [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         $field = Field::between('age', 13, 17, '@age');
 | |
|         $field->qualifier = 'me';
 | |
|         expect($field)->toWhere()->toBe("(me.data->>'age')::numeric BETWEEN @agemin AND @agemax");
 | |
|     })->group('postgresql');
 | |
|     test('generates BETWEEN for between w/ qualifier, non-numeric range [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         $field = Field::between('city', 'Atlanta', 'Chicago', ':city');
 | |
|         $field->qualifier = 'me';
 | |
|         expect($field)->toWhere()->toBe("me.data->>'city' BETWEEN :citymin AND :citymax");
 | |
|     })->group('postgresql');
 | |
|     test('generates IN for in, non-numeric values [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere()
 | |
|             ->toBe("data->>'test' IN (:city_0, :city_1)");
 | |
|     })->group('postgresql');
 | |
|     test('generates IN for in, numeric values [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::in('even', [2, 4, 6], ':nbr'))->toWhere()
 | |
|             ->toBe("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)");
 | |
|     })->group('postgresql');
 | |
|     test('generates IN for in [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere()
 | |
|             ->toBe("data->>'test' IN (:city_0, :city_1)");
 | |
|     })->group('sqlite');
 | |
|     test('generates clause for inArray [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::inArray('even', 'tbl', [2, 4, 6, 8], ':it'))->toWhere()
 | |
|             ->toBe("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]");
 | |
|     })->group('postgresql');
 | |
|     test('generates clause for inArray [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::inArray('test', 'tbl', ['Atlanta', 'Chicago'], ':city'))->toWhere()
 | |
|             ->toBe("EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))");
 | |
|     })->group('sqlite');
 | |
|     test('generates clause for other operators w/o qualifier [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value");
 | |
|     })->group('postgresql');
 | |
|     test('generates clause for other operators w/o qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value");
 | |
|     })->group('sqlite');
 | |
|     test('generates no-parameter clause w/ qualifier [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         $field = Field::exists('no_field');
 | |
|         $field->qualifier = 'test';
 | |
|         expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL");
 | |
|     })->group('postgresql');
 | |
|     test('generates no-parameter clause w/ qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         $field = Field::exists('no_field');
 | |
|         $field->qualifier = 'test';
 | |
|         expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL");
 | |
|     })->group('sqlite');
 | |
|     test('generates parameter clause w/ qualifier [PostgreSQL]', function () {
 | |
|         Configuration::overrideMode(Mode::PgSQL);
 | |
|         $field = Field::lessOrEqual('le_field', 18, ':it');
 | |
|         $field->qualifier = 'q';
 | |
|         expect($field)->toWhere()->toBe("(q.data->>'le_field')::numeric <= :it");
 | |
|     })->group('postgresql');
 | |
|     test('generates parameter clause w/ qualifier [SQLite]', function () {
 | |
|         Configuration::overrideMode(Mode::SQLite);
 | |
|         $field = Field::lessOrEqual('le_field', 18, ':it');
 | |
|         $field->qualifier = 'q';
 | |
|         expect($field)->toWhere()->toBe("q.data->>'le_field' <= :it");
 | |
|     })->group('sqlite');
 | |
| });
 | |
| 
 | |
| describe('::equal()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::equal('my_test', 9);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('my_test')
 | |
|             ->op->toBe(Op::Equal)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(9);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::equal('another_test', 'turkey', ':test');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('another_test')
 | |
|             ->op->toBe(Op::Equal)
 | |
|             ->paramName->toBe(':test')
 | |
|             ->and($field->value)->toBe('turkey');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::greater()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::greater('your_test', 4);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('your_test')
 | |
|             ->op->toBe(Op::Greater)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(4);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::greater('more_test', 'chicken', ':value');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('more_test')
 | |
|             ->op->toBe(Op::Greater)
 | |
|             ->paramName->toBe(':value')
 | |
|             ->and($field->value)->toBe('chicken');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::greaterOrEqual()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::greaterOrEqual('their_test', 6);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('their_test')
 | |
|             ->op->toBe(Op::GreaterOrEqual)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(6);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::greaterOrEqual('greater_test', 'poultry', ':cluck');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('greater_test')
 | |
|             ->op->toBe(Op::GreaterOrEqual)
 | |
|             ->paramName->toBe(':cluck')
 | |
|             ->and($field->value)->toBe('poultry');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::less()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::less('z', 32);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('z')
 | |
|             ->op->toBe(Op::Less)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(32);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::less('additional_test', 'fowl', ':boo');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('additional_test')
 | |
|             ->op->toBe(Op::Less)
 | |
|             ->paramName->toBe(':boo')
 | |
|             ->and($field->value)->toBe('fowl');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::lessOrEqual()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::lessOrEqual('g', 87);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('g')
 | |
|             ->op->toBe(Op::LessOrEqual)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(87);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::lessOrEqual('lesser_test', 'hen', ':woo');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('lesser_test')
 | |
|             ->op->toBe(Op::LessOrEqual)
 | |
|             ->paramName->toBe(':woo')
 | |
|             ->and($field->value)->toBe('hen');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::notEqual()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::notEqual('j', 65);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('j')
 | |
|             ->op->toBe(Op::NotEqual)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBe(65);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::notEqual('unequal_test', 'egg', ':zoo');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('unequal_test')
 | |
|             ->op->toBe(Op::NotEqual)
 | |
|             ->paramName->toBe(':zoo')
 | |
|             ->and($field->value)->toBe('egg');
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::between()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::between('k', 'alpha', 'zed');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('k')
 | |
|             ->op->toBe(Op::Between)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toEqual(['alpha', 'zed']);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::between('between_test', 18, 49, ':count');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('between_test')
 | |
|             ->op->toBe(Op::Between)
 | |
|             ->paramName->toBe(':count')
 | |
|             ->and($field->value)->toEqual([18, 49]);
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::in()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::in('test', [1, 2, 3]);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('test')
 | |
|             ->op->toBe(Op::In)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toEqual([1, 2, 3]);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::in('unit', ['a', 'b'], ':inParam');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('unit')
 | |
|             ->op->toBe(Op::In)
 | |
|             ->paramName->toBe(':inParam')
 | |
|             ->and($field->value)->toEqual(['a', 'b']);
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::inArray()', function () {
 | |
|     test('creates Field w/o parameter', function () {
 | |
|         $field = Field::inArray('test', 'tbl', [1, 2, 3]);
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('test')
 | |
|             ->op->toBe(Op::InArray)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toEqual(['table' => 'tbl', 'values' => [1, 2, 3]]);
 | |
|     });
 | |
|     test('creates Field w/ parameter', function () {
 | |
|         $field = Field::inArray('unit', 'tab', ['a', 'b'], ':inAParam');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('unit')
 | |
|             ->op->toBe(Op::InArray)
 | |
|             ->paramName->toBe(':inAParam')
 | |
|             ->and($field->value)->toEqual(['table' => 'tab', 'values' => ['a', 'b']]);
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::exists()', function () {
 | |
|     test('creates Field', function () {
 | |
|         $field = Field::exists('be_there');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('be_there')
 | |
|             ->op->toBe(Op::Exists)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBeEmpty();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::notExists()', function () {
 | |
|     test('creates Field', function () {
 | |
|         $field = Field::notExists('be_absent');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('be_absent')
 | |
|             ->op->toBe(Op::NotExists)
 | |
|             ->paramName->toBeEmpty()
 | |
|             ->and($field->value)->toBeEmpty();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe('::named()', function () {
 | |
|     test('creates Field', function () {
 | |
|         $field = Field::named('the_field');
 | |
|         expect($field)
 | |
|             ->not->toBeNull()
 | |
|             ->fieldName->toBe('the_field')
 | |
|             ->op->toBe(Op::Equal)
 | |
|             ->value->toBeEmpty()
 | |
|             ->and($field->value)->toBeEmpty();
 | |
|     });
 | |
| });
 |