• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

brick / geo / 14083804946

26 Mar 2025 12:54PM UTC coverage: 63.411%. Remained the same
14083804946

push

github

BenMorel
Move docker compose to postgis image

1922 of 3031 relevant lines covered (63.41%)

1910.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.47
/src/Engine/Database/Driver/PgsqlDriver.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo\Engine\Database\Driver;
6

7
use Brick\Geo\Engine\Database\Query\BinaryValue;
8
use Brick\Geo\Engine\Database\Query\ScalarValue;
9
use Brick\Geo\Engine\Database\Result\Row;
10
use Brick\Geo\Exception\GeometryEngineException;
11
use Override;
12
use PgSql\Connection;
13

14
/**
15
 * Database driver using the pgsql extension for PostgreSQL.
16
 */
17
final class PgsqlDriver implements DatabaseDriver
18
{
19
    public function __construct(
20
        private readonly Connection $connection,
21
    ) {
22
    }
×
23

24
    #[Override]
25
    public function executeQuery(string|BinaryValue|ScalarValue ...$query) : Row
26
    {
27
        $position = 1;
300✔
28

29
        $queryString = '';
300✔
30
        $queryParams = [];
300✔
31

32
        foreach ($query as $queryPart) {
300✔
33
            if ($queryPart instanceof BinaryValue) {
300✔
34
                $queryString .= '$' . $position++ . '::bytea';
300✔
35
                /** @var string */
36
                $queryParams[] = pg_escape_bytea($this->connection, $queryPart->value);
300✔
37
            } elseif ($queryPart instanceof ScalarValue) {
300✔
38
                $queryString .= '$' . $position++;
80✔
39

40
                if (is_int($queryPart->value)) {
80✔
41
                    $queryString .= '::int';
7✔
42
                    $queryParams[] = $queryPart->value;
7✔
43
                } elseif (is_float($queryPart->value)) {
73✔
44
                    $queryString .= '::float';
69✔
45
                    $queryParams[] = $queryPart->value;
69✔
46
                } elseif (is_bool($queryPart->value)) {
9✔
47
                    $queryString .= '::bool';
5✔
48
                    $queryParams[] = $queryPart->value ? 't' : 'f';
5✔
49
                } else {
50
                    $queryParams[] = $queryPart->value;
4✔
51
                }
52
            } else {
53
                $queryString .= $queryPart;
300✔
54
            }
55
        }
56

57
        // Mute warnings and back up the current error reporting level.
58
        $errorReportingLevel = error_reporting(0);
300✔
59

60
        try {
61
            $value = pg_prepare($this->connection, '', $queryString);
300✔
62

63
            if ($value === false) {
300✔
64
                $this->throwLastError();
×
65
            }
66

67
            $result = pg_execute($this->connection, '', $queryParams);
300✔
68

69
            if ($result === false) {
300✔
70
                $this->throwLastError();
×
71
            }
72

73
            /** @var list<list<mixed>>|false $rows */
74
            $rows = pg_fetch_all($result, PGSQL_NUM);
300✔
75

76
            if ($rows === false) {
300✔
77
                $this->throwLastError();
×
78
            }
79

80
            if (count($rows) !== 1) {
300✔
81
                throw new GeometryEngineException(sprintf('Expected exactly one row, got %d.', count($rows)));
×
82
            }
83
        } finally {
84
            // Restore the error reporting level.
85
            error_reporting($errorReportingLevel);
300✔
86
        }
87

88
        return new Row($this, $rows[0]);
300✔
89
    }
90

91
    /**
92
     * @throws GeometryEngineException
93
     */
94
    private function throwLastError() : never
95
    {
96
        throw new GeometryEngineException('The engine return an error: ' . pg_last_error($this->connection));
×
97
    }
98

99
    #[Override]
100
    public function convertBinaryResult(mixed $value) : string
101
    {
102
        if (is_string($value)) {
123✔
103
            return pg_unescape_bytea($value);
123✔
104
        }
105

106
        throw GeometryEngineException::unexpectedDatabaseReturnType('string', $value);
×
107
    }
108

109
    #[Override]
110
    public function convertStringResult(mixed $value) : string
111
    {
112
        if (is_string($value)) {
×
113
            return $value;
×
114
        }
115

116
        throw GeometryEngineException::unexpectedDatabaseReturnType('string', $value);
×
117
    }
118

119
    #[Override]
120
    public function convertIntResult(mixed $value) : int
121
    {
122
        // TODO check that actually returned as int;
123
        //      maybe checks for all types sent & received for each driver?
124

125
        if (is_int($value)) {
×
126
            return $value;
×
127
        }
128

129
        throw GeometryEngineException::unexpectedDatabaseReturnType('int', $value);
×
130
    }
131

132
    #[Override]
133
    public function convertFloatResult(mixed $value) : float
134
    {
135
        if (is_numeric($value)) {
41✔
136
            return (float) $value;
40✔
137
        }
138

139
        throw GeometryEngineException::unexpectedDatabaseReturnType('number or numeric string', $value);
1✔
140
    }
141

142
    #[Override]
143
    public function convertBoolResult(mixed $value) : bool
144
    {
145
        return match ($value) {
161✔
146
            't' => true,
89✔
147
            'f' => false,
78✔
148
            default => throw GeometryEngineException::unexpectedDatabaseReturnType('t or f', $value),
161✔
149
        };
161✔
150
    }
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc