Skip to content

Commit 474af7f

Browse files
committed
test: add leaf db tests
1 parent 004d42d commit 474af7f

14 files changed

Lines changed: 508 additions & 367 deletions

File tree

‎.github/workflows/lint.yml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Lint code
2+
3+
on: ["push","pull_request"]
4+
5+
jobs:
6+
lint:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- name: Checkout code
11+
uses: actions/checkout@v4
12+
with:
13+
ref: ${{ github.head_ref }}
14+
15+
- name: Setup PHP
16+
uses: shivammathur/setup-php@v2
17+
with:
18+
php-version: '8.2'
19+
extensions: json, zip, pdo, pdo_sqlite
20+
tools: composer:v2
21+
coverage: none
22+
23+
- name: Install PHP dependencies
24+
run: composer update --no-interaction --no-progress
25+
26+
- name: Run Linter
27+
run: composer run lint -- --check

‎.github/workflows/tests.yml‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Run Tests
2+
3+
on: ["push","pull_request"]
4+
5+
jobs:
6+
tests:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
fail-fast: true
10+
matrix:
11+
os: ["macos-latest","ubuntu-latest","windows-latest"]
12+
php: ["8.4","8.3","8.2"]
13+
14+
name: PHP ${{ matrix.php }} - ${{ matrix.os }}
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Setup PHP
21+
uses: shivammathur/setup-php@v2
22+
with:
23+
php-version: ${{ matrix.php }}
24+
extensions: json, zip, pdo, pdo_sqlite
25+
tools: composer:v2
26+
coverage: xdebug
27+
28+
- name: Install PHP dependencies
29+
run: composer update --no-interaction --no-progress
30+
31+
- name: Run Tests
32+
run: composer run test -- --flags=coverage

‎alchemy.yml‎

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,57 @@ app:
33

44
tests:
55
engine: pest
6-
parallel: true
6+
parallel: false
77
paths:
88
- tests
99
files:
1010
- '*.test.php'
1111
coverage:
12-
local: false
13-
actions: true
12+
processUncoveredFiles: true
1413

1514
lint:
1615
preset: PSR12
1716
rules:
17+
single_quote: true
18+
phpdoc_scalar: true
1819
no_unused_imports: true
20+
unary_operator_spaces: true
21+
binary_operator_spaces: true
22+
phpdoc_var_without_name: true
23+
trailing_comma_in_multiline: true
24+
phpdoc_single_line_var_spacing: true
25+
single_trait_insert_per_statement: true
1926
not_operator_with_successor_space: false
20-
single_quote: true
27+
array_syntax:
28+
syntax: short
29+
ordered_imports:
30+
sort_algorithm: alpha
31+
method_argument_space:
32+
on_multiline: ensure_fully_multiline
33+
keep_multiple_spaces_after_comma: true
34+
blank_line_before_statement:
35+
statements:
36+
- try
37+
- break
38+
- throw
39+
- return
40+
- declare
41+
- continue
2142

2243
actions:
2344
run:
2445
- lint
2546
- tests
2647
os:
48+
- macos-latest
2749
- ubuntu-latest
50+
- windows-latest
2851
php:
29-
extensions: json, zip, dom, curl, libxml, mbstring, pdo
30-
versions:
52+
extensions: json, zip, pdo, pdo_sqlite
53+
versions: # library supports ^7.4|^8.0, but pest 3 needs 8.2+
54+
- '8.4'
3155
- '8.3'
3256
- '8.2'
33-
- '8.1'
34-
- '8.0'
35-
- '7.4'
3657
events:
3758
- push
3859
- pull_request

‎composer.json‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,17 @@
3030
"minimum-stability": "dev",
3131
"prefer-stable": true,
3232
"require-dev": {
33-
"pestphp/pest": "^1.21",
33+
"pestphp/pest": "*",
3434
"friendsofphp/php-cs-fixer": "^3.14",
35-
"leafs/alchemy": "^2.2"
35+
"leafs/alchemy": "v5.x-dev"
3636
},
3737
"scripts": {
3838
"format": "vendor/bin/php-cs-fixer fix --config=.php_cs.dist.php --allow-risky=yes",
39-
"test": "./vendor/bin/alchemy setup --test",
39+
"test": "./vendor/bin/alchemy test",
4040
"alchemy": "./vendor/bin/alchemy setup",
41-
"lint": "./vendor/bin/alchemy setup --lint",
42-
"actions": "./vendor/bin/alchemy setup --actions"
41+
"lint": "./vendor/bin/alchemy lint",
42+
"fmt": "./vendor/bin/alchemy fmt",
43+
"ci": "./vendor/bin/alchemy ci"
4344
},
4445
"config": {
4546
"allow-plugins": {

‎src/Db.php‎

Lines changed: 17 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,27 @@ public function tableExists(string $table)
5353
switch ($this->config['dbtype']) {
5454
case 'sqlite':
5555
$schema = $this->select('sqlite_master')->where(['type' => 'table', 'name' => $table])->all();
56+
5657
break;
5758

5859
case 'mysql':
5960
$schema = $this->select('INFORMATION_SCHEMA.TABLES')->where(['TABLE_SCHEMA' => $this->config['dbname'], 'TABLE_NAME' => $table])->all();
61+
6062
break;
6163

6264
case 'pgsql':
6365
$schema = $this->select('pg_catalog.pg_tables')->where(['schemaname' => 'public', 'tablename' => $table])->all();
66+
6467
break;
6568

6669
case 'sqlsrv':
6770
$schema = $this->select('information_schema.tables')->where(['table_schema' => 'dbo', 'table_name' => $table])->all();
71+
6872
break;
6973

7074
default:
7175
$schema = $this->select('INFORMATION_SCHEMA.SCHEMATA')->where('SCHEMA_NAME', $table)->all();
76+
7277
break;
7378
}
7479

@@ -132,7 +137,7 @@ public function dropTable(string $table)
132137
public function backup(string $dbName, string $destination, bool $withDifferential = false)
133138
{
134139
return $this->query("BACKUP DATABASE $dbName TO DISK = '$destination' " .
135-
$withDifferential ? 'WITH DIFFERENTIAL' : '')->execute();
140+
($withDifferential ? 'WITH DIFFERENTIAL' : ''))->execute();
136141
}
137142

138143
/**
@@ -355,6 +360,8 @@ public function orWhere($condition, $comparator = null, $value = null): self
355360
return $this;
356361
}
357362

363+
/**
364+
* Add a JSON where clause to the query
358365
*
359366
* @param string $column The JSON column
360367
* @param string $jsonKey The key within the JSON structure
@@ -363,9 +370,8 @@ public function orWhere($condition, $comparator = null, $value = null): self
363370
*/
364371
public function whereJson(string $column, string $jsonKey, $value, string $comparator = '='): self
365372
{
366-
// Check if the value is an integer, and cast the JSON value to an integer
373+
// cast the extracted value to a number when comparing against one
367374
$jsonExpression = is_int($value)
368-
# just incase: ? "CAST(JSON_EXTRACT($column, '$.$jsonKey') AS UNSIGNED)";
369375
? "JSON_EXTRACT($column, '$.$jsonKey') + 0"
370376
: "JSON_EXTRACT($column, '$.$jsonKey')";
371377

@@ -442,95 +448,9 @@ public function orWhereJsonContains(string $column, $value, ?string $jsonKey = n
442448
/**
443449
* Fetch current query with all related data
444450
*
445-
* @param string $column The JSON column
446-
* @param string $jsonKey The key within the JSON structure
447-
* @param mixed $value The value to compare against
448-
* @param string $comparator The comparison operator (default '=')
449-
*/
450-
public function whereJson(string $column, string $jsonKey, $value, string $comparator = '='): self
451-
{
452-
// Check if the value is an integer, and cast the JSON value to an integer
453-
$jsonExpression = is_int($value)
454-
? "JSON_EXTRACT($column, '$.$jsonKey') + 0" # just incase: ? "CAST(JSON_EXTRACT($column, '$.$jsonKey') AS UNSIGNED)";
455-
: "JSON_EXTRACT($column, '$.$jsonKey')";
456-
457-
$this->query = Builder::where($this->query, $jsonExpression, $value, $comparator);
458-
$this->bind(...(Builder::$bindings));
459-
460-
return $this;
461-
}
462-
463-
/**
464-
* Add a JSON where clause with OR comparator to the query
465-
*
466-
* @param string $column The JSON column
467-
* @param string $jsonKey The key within the JSON structure
468-
* @param mixed $value The value to compare against
469-
* @param string $comparator The comparison operator (default '=')
470-
*/
471-
public function orWhereJson(string $column, string $jsonKey, $value, string $comparator = '='): self
472-
{
473-
$jsonExpression = is_int($value)
474-
? "JSON_EXTRACT($column, '$.$jsonKey') + 0"
475-
: "JSON_EXTRACT($column, '$.$jsonKey')";
476-
477-
$this->query = Builder::where($this->query, $jsonExpression, $value, $comparator, 'OR');
478-
$this->bind(...(Builder::$bindings));
479-
480-
return $this;
481-
}
482-
483-
/**
484-
* Add a JSON contains clause to the query
485-
*
486-
* @param string $column The JSON column
487-
* @param mixed $value The value to check for
488-
* @param string|null $jsonKey The key within the JSON structure (optional)
489-
*/
490-
public function whereJsonContains(string $column, $value, ?string $jsonKey = null): self
491-
{
492-
$jsonValue = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
493-
494-
$jsonExpression = $jsonKey
495-
? "JSON_CONTAINS($column, ?, '$.$jsonKey')"
496-
: "JSON_CONTAINS($column, ?)";
497-
498-
499-
Builder::$bindings[] = $jsonValue;
500-
$this->query = Builder::where($this->query, $jsonExpression, 1, '=');
501-
$this->bind(...(Builder::$bindings));
502-
503-
return $this;
504-
}
505-
506-
/**
507-
* Add a JSON contains clause with OR comparator to the query
508-
*
509-
* @param string $column The JSON column
510-
* @param mixed $value The value to check for
511-
* @param string|null $jsonKey The key within the JSON structure (optional)
512-
*/
513-
public function orWhereJsonContains(string $column, $value, ?string $jsonKey = null): self
514-
{
515-
$jsonValue = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
516-
517-
$jsonExpression = $jsonKey
518-
? "JSON_CONTAINS($column, ?, '$.$jsonKey')"
519-
: "JSON_CONTAINS($column, ?)";
520-
521-
Builder::$bindings[] = $jsonValue;
522-
$this->query = Builder::where($this->query, $jsonExpression, 1, '=', 'OR');
523-
$this->bind(...(Builder::$bindings));
524-
525-
return $this;
526-
}
527-
528-
/**
529-
* Fetch current query with all related data
530-
*
531451
* @param string $table The table to join
532452
* @param string $foreignKey The foreign key to use
533-
*
453+
*
534454
* @return self
535455
*/
536456
public function with(string $table, ?string $foreignKey = null)
@@ -539,7 +459,7 @@ public function with(string $table, ?string $foreignKey = null)
539459

540460
$this->eager[] = [
541461
'table' => $table,
542-
'foreignKey' => $foreignKey
462+
'foreignKey' => $foreignKey,
543463
];
544464

545465
return $this;
@@ -605,8 +525,9 @@ public function search(string $row, string $value, ?array $hidden = []): ?array
605525
*/
606526
public function beginTransaction(): self
607527
{
608-
$this->query('START TRANSACTION');
609-
$this->execute();
528+
// PDO's own transaction handling works across mysql, sqlite,
529+
// postgres and sqlsrv — raw START TRANSACTION is mysql-only
530+
$this->connection($this->currentConnection)->beginTransaction();
610531

611532
return $this;
612533
}
@@ -618,8 +539,7 @@ public function beginTransaction(): self
618539
*/
619540
public function commit(): self
620541
{
621-
$this->query('COMMIT');
622-
$this->execute();
542+
$this->connection($this->currentConnection)->commit();
623543

624544
return $this;
625545
}
@@ -631,8 +551,7 @@ public function commit(): self
631551
*/
632552
public function rollback(): self
633553
{
634-
$this->query('ROLLBACK');
635-
$this->execute();
554+
$this->connection($this->currentConnection)->rollBack();
636555

637556
return $this;
638557
}
@@ -654,7 +573,7 @@ public function transaction($callback): bool
654573
return true;
655574
} catch (\Exception $e) {
656575
$this->rollback();
657-
$this->errorsArray = $e;
576+
$this->errors['transaction'] = $e->getMessage();
658577

659578
return false;
660579
}

‎src/Db/Builder.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,17 +166,19 @@ public static function whereAdvanced(
166166
case 'in':
167167
$placeholders = implode(', ', array_fill(0, count($values), '?'));
168168
$query .= "$column IN ($placeholders)";
169+
169170
break;
170171

171172
case 'notin':
172173
case 'not in':
173174
$placeholders = implode(', ', array_fill(0, count($values), '?'));
174175
$query .= "$column NOT IN ($placeholders)";
176+
175177
break;
176178

177179
case 'between':
178180
if (count($values) !== 2) {
179-
throw new \InvalidArgumentException("BETWEEN requires exactly 2 values.");
181+
throw new \InvalidArgumentException('BETWEEN requires exactly 2 values.');
180182
}
181183

182184
$query .= "$column BETWEEN ? AND ?";
@@ -188,6 +190,7 @@ public static function whereAdvanced(
188190
}
189191

190192
static::$bindings = array_merge(static::$bindings, $values);
193+
191194
return $query;
192195
}
193196

0 commit comments

Comments
 (0)