Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance and test support for PostgreSQL #189

Merged
merged 35 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b36deff
wip
luisdalmolin Sep 29, 2024
67d1ad3
wip
luisdalmolin Sep 29, 2024
82cbf73
Merge branch 'master' into postgres-support
danharrin Oct 1, 2024
a3be0c4
Update OrderByTest.php
danharrin Oct 1, 2024
9559bf0
Fixed hasOneOfMany for MySQL and Postgres
luisdalmolin Oct 1, 2024
353d46d
Removed readme
luisdalmolin Oct 1, 2024
2880e1b
Handling left joins in one of many
luisdalmolin Oct 2, 2024
c9be3ca
Add phpunit.xml to gitignore
danharrin Oct 2, 2024
51579ef
Remove support for unsupported PHP/Laravel versions
danharrin Oct 2, 2024
c3394b6
Remove DB setup in test case
danharrin Oct 2, 2024
4b8e419
Add CI jobs for testing the package across multiple DBs
danharrin Oct 2, 2024
b4fb186
Update DB connection credentials
danharrin Oct 2, 2024
fc27b7e
Update ci.yaml
danharrin Oct 2, 2024
114a480
Ensure correct DB name across Laravel versions
danharrin Oct 2, 2024
dc3e0d5
Set DB var in action instead
danharrin Oct 2, 2024
7b67d3c
Preparing to run tests on all dbs
luisdalmolin Oct 2, 2024
66dd83e
Fixed test
luisdalmolin Oct 2, 2024
61236d0
Update JoinRelationshipTest.php
danharrin Oct 2, 2024
b7b98b0
Merge branch 'postgres-support' of https://github.com/kirschbaum-deve…
danharrin Oct 2, 2024
ee42518
Added additional test
luisdalmolin Oct 2, 2024
344ec29
Fixed powerJoinHas with hasOneOfMany
luisdalmolin Oct 2, 2024
b685652
Fixed concat checks
luisdalmolin Oct 2, 2024
b4b44c4
Fix join instance counting on MySQL
danharrin Oct 2, 2024
b2e4376
Update TestCase.php
danharrin Oct 2, 2024
6bb68b2
Fixed OrderByTest::test_order_by_relationship_min_and_max in MySQL
luisdalmolin Oct 2, 2024
2dd3e0f
Update TestCase.php
danharrin Oct 2, 2024
efd396b
Merge branch 'postgres-support' of https://github.com/kirschbaum-deve…
danharrin Oct 2, 2024
d57c663
Update RelationshipsExtraMethods.php
danharrin Oct 2, 2024
8425878
Fix Postgres tests again
danharrin Oct 2, 2024
f904961
Added custom one of many logic for MySQL
luisdalmolin Oct 2, 2024
3374a61
Removed old Postgres check
luisdalmolin Oct 2, 2024
d475c64
Update JoinRelationshipTest.php
danharrin Oct 2, 2024
c109c90
Update 2020_03_16_000000_create_tables.php
danharrin Oct 2, 2024
ca35e32
Dropped PowerJoins trait
luisdalmolin Oct 2, 2024
424095e
Removed PowerJoins traits
luisdalmolin Oct 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 130 additions & 26 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,151 @@ on:
pull_request:

jobs:
tests:
runs-on: ubuntu-latest
mysql_8:
runs-on: ubuntu-24.04
timeout-minutes: 5

services:
mysql:
image: mysql:8
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: laravel
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

strategy:
fail-fast: true
matrix:
php: [8.0, 8.1, 8.2, 8.3]
laravel: [8.*, 9.*, 10.*, 11.*]
php: [ 8.1, 8.2, 8.3 ]
laravel: [ 10.*, 11.* ]
include:
- laravel: 11.*
testbench: 9.*-dev
- laravel: 10.*
testbench: 8.*
- laravel: 9.*
testbench: 7.*
- laravel: 8.*
testbench: 6.*
exclude:
- laravel: 11.*
php: 8.0
- laravel: 11.*
php: 8.1

name: MySQL 8 - PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr
tools: composer:v2
coverage: none

- name: Set Framework version
run: composer config version "11.x-dev"

- name: Install dependencies
uses: nick-fields/retry@v3
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress

- name: Execute tests
run: vendor/bin/phpunit
env:
DB_CONNECTION: mysql

pgsql_15:
runs-on: ubuntu-24.04
timeout-minutes: 5

services:
postgresql:
image: postgres:15
env:
POSTGRES_DB: laravel
POSTGRES_USER: laravel
POSTGRES_PASSWORD: password
ports:
- 5432:5432
options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3

strategy:
fail-fast: true
matrix:
php: [ 8.1, 8.2, 8.3 ]
laravel: [ 10.*, 11.* ]
include:
- laravel: 11.*
testbench: 9.*-dev
- laravel: 10.*
php: 8.0
- laravel: 8.*
testbench: 8.*
exclude:
- laravel: 11.*
php: 8.1
- laravel: 8.*
php: 8.2
- laravel: 9.*
php: 8.2
- laravel: 8.*
php: 8.3
- laravel: 9.*
php: 8.3


name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
name: PostgreSQL 15 - PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}

steps:
- name: Checkout code
uses: actions/checkout@v1
uses: actions/checkout@v4

- name: Install SQLite 3
- name: Cache dependencies
uses: actions/cache@v1
with:
path: ~/.composer/cache/files
key: dependencies-pw-v2-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: curl, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, iconv
coverage: none
tools: composer:v2

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install sqlite3
composer --version
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer require "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update --dev
composer update --prefer-dist --no-interaction --no-suggest --dev
composer dump

- name: Execute tests
run: vendor/bin/phpunit
env:
DB_CONNECTION: pgsql
DB_DATABASE: laravel
DB_USERNAME: laravel
DB_PASSWORD: password

sqlite:
runs-on: ubuntu-24.04
timeout-minutes: 5

strategy:
fail-fast: true
matrix:
php: [ 8.1, 8.2, 8.3 ]
laravel: [ 10.*, 11.* ]
include:
- laravel: 11.*
testbench: 9.*-dev
- laravel: 10.*
testbench: 8.*
exclude:
- laravel: 11.*
php: 8.1

name: SQLite - PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Cache dependencies
uses: actions/cache@v1
Expand All @@ -74,5 +173,10 @@ jobs:
composer update --prefer-dist --no-interaction --no-suggest --dev
composer dump

- name: Setup SQLite Database
run: php vendor/bin/testbench package:create-sqlite-db

- name: Execute tests
run: vendor/bin/phpunit
env:
DB_CONNECTION: sqlite
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
build
composer.lock
docs
phpunit.xml
vendor
coverage
.phpunit.result.cache
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,3 @@ Development of this package is sponsored by Kirschbaum Development Group, a deve
## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

## Laravel Package Boilerplate

This package was generated using the [Laravel Package Boilerplate](https://laravelpackageboilerplate.com).
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
}
],
"require": {
"php": "^8.0",
"illuminate/support": "^8.0|^9.0|^10.0|^11.0",
"illuminate/database": "^8.0|^9.0|^10.0|^11.0"
"php": "^8.1",
"illuminate/support": "^10.0|^11.0",
"illuminate/database": "^10.0|^11.0"
},
"require-dev": {
"laravel/legacy-factories": "^1.0@dev",
"orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0",
"phpunit/phpunit": "^8.0|^9.0|^10.0"
"orchestra/testbench": "^8.0|^9.0",
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
Expand Down
4 changes: 3 additions & 1 deletion src/Mixins/JoinRelationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,10 @@ public function powerJoinHas(): Closure

$relation = $this->getRelationWithoutConstraintsProxy($relation);
}
$relation->performJoinForEloquentPowerJoins($this, 'leftPowerJoin', $callback, morphable: $morphable);

$relation->performJoinForEloquentPowerJoins($this, 'leftPowerJoin', $callback, morphable: $morphable, hasCheck: true);
$relation->performHavingForEloquentPowerJoins($this, $operator, $count, morphable: $morphable);

return $this;
};
}
Expand Down
53 changes: 43 additions & 10 deletions src/Mixins/RelationshipsExtraMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Kirschbaum\PowerJoins\Mixins;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\PostgresConnection;
use Stringable;
use Illuminate\Support\Str;
use Kirschbaum\PowerJoins\StaticCache;
Expand All @@ -19,6 +20,7 @@
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Database\MySqlConnection;

/**
* @method \Illuminate\Database\Eloquent\Model getModel()
Expand Down Expand Up @@ -56,12 +58,12 @@ class RelationshipsExtraMethods
*/
public function performJoinForEloquentPowerJoins()
{
return function ($builder, $joinType = 'leftJoin', $callback = null, $alias = null, bool $disableExtraConditions = false, string $morphable = null) {
return function ($builder, $joinType = 'leftJoin', $callback = null, $alias = null, bool $disableExtraConditions = false, string $morphable = null, bool $hasCheck = false) {
return match (true) {
$this instanceof MorphToMany => $this->performJoinForEloquentPowerJoinsForMorphToMany($builder, $joinType, $callback, $alias, $disableExtraConditions),
$this instanceof BelongsToMany => $this->performJoinForEloquentPowerJoinsForBelongsToMany($builder, $joinType, $callback, $alias, $disableExtraConditions),
$this instanceof MorphOneOrMany => $this->performJoinForEloquentPowerJoinsForMorph($builder, $joinType, $callback, $alias, $disableExtraConditions),
$this instanceof HasMany || $this instanceof HasOne => $this->performJoinForEloquentPowerJoinsForHasMany($builder, $joinType, $callback, $alias, $disableExtraConditions),
$this instanceof HasMany || $this instanceof HasOne => $this->performJoinForEloquentPowerJoinsForHasMany($builder, $joinType, $callback, $alias, $disableExtraConditions, $hasCheck),
$this instanceof HasManyThrough || $this instanceof HasOneThrough => $this->performJoinForEloquentPowerJoinsForHasManyThrough($builder, $joinType, $callback, $alias, $disableExtraConditions),
$this instanceof MorphTo => $this->performJoinForEloquentPowerJoinsForMorphTo($builder, $joinType, $callback, $alias, $disableExtraConditions, $morphable),
default => $this->performJoinForEloquentPowerJoinsForBelongsTo($builder, $joinType, $callback, $alias, $disableExtraConditions),
Expand Down Expand Up @@ -284,17 +286,48 @@ protected function performJoinForEloquentPowerJoinsForMorphTo()
*/
protected function performJoinForEloquentPowerJoinsForHasMany()
{
return function ($builder, $joinType, $callback = null, $alias = null, bool $disableExtraConditions = false) {
$joinedTable = $alias ?: $this->query->getModel()->getTable();
return function ($builder, $joinType, $callback = null, $alias = null, bool $disableExtraConditions = false, bool $hasCheck = false) {
$joinedModel = $this->query->getModel();
$joinedTable = $alias ?: $joinedModel->getTable();
$parentTable = StaticCache::getTableOrAliasForModel($this->parent);
$isOneOfMany = method_exists($this, 'isOneOfMany') ? $this->isOneOfMany() : false;

if ($isOneOfMany) {
foreach ($this->getOneOfManySubQuery()->getQuery()->columns as $column) {
$builder->addSelect($column);
}

$builder->take(1);
if ($isOneOfMany && ! $hasCheck) {
$column = $this->getOneOfManySubQuery()->getQuery()->columns[0];
$fkColumn = $this->getOneOfManySubQuery()->getQuery()->columns[1];

$builder->where(function ($query) use ($column, $joinType, $joinedModel, $builder, $fkColumn) {
$query->whereIn($joinedModel->getQualifiedKeyName(), function ($query) use ($column, $joinedModel, $builder, $fkColumn) {
$columnValue = $column->getValue($builder->getGrammar());
$direction = Str::contains($columnValue, 'min(') ? 'asc' : 'desc';

$columnName = Str::of($columnValue)->after('(')->before(')')->__toString();
$columnName = Str::replace(['"', "'", '`'], '', $columnName);

if ($builder->getConnection() instanceof MySqlConnection) {
$query->select('*')->from(function ($query) use ($joinedModel, $columnName, $fkColumn, $direction, $builder) {
$query
->select($joinedModel->getQualifiedKeyName())
->from($joinedModel->getTable())
->whereColumn($fkColumn, $builder->getModel()->getQualifiedKeyName())
->orderBy($columnName, $direction)
->take(1);
});
} else {
$query
->select($joinedModel->getQualifiedKeyName())
->distinct($columnName)
->from($joinedModel->getTable())
->whereColumn($fkColumn, $builder->getModel()->getQualifiedKeyName())
->orderBy($columnName, $direction)
->take(1);
}
});

if ($joinType === 'leftPowerJoin') {
$query->orWhereRaw('1 = 1');
}
});
}

$builder->{$joinType}($this->query->getModel()->getTable(), function ($join) use ($callback, $joinedTable, $parentTable, $alias, $disableExtraConditions) {
Expand Down
9 changes: 0 additions & 9 deletions src/PowerJoins.php

This file was deleted.

Loading
Loading