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

brick / geo / 14085820119

26 Mar 2025 02:27PM UTC coverage: 63.783%. Remained the same
14085820119

push

github

BenMorel
Test pdo_pgsql with emulate prepares ON/OFF

1939 of 3040 relevant lines covered (63.78%)

2122.25 hits per line

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

83.02
/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\Driver\Internal\TypeConverter;
8
use Brick\Geo\Engine\Database\Query\BinaryValue;
9
use Brick\Geo\Engine\Database\Query\ScalarValue;
10
use Brick\Geo\Engine\Database\Result\Row;
11
use Brick\Geo\Exception\GeometryEngineException;
12
use Override;
13
use PgSql\Connection;
14

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

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

30
        $queryString = '';
326✔
31
        $queryParams = [];
326✔
32

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

120
    #[Override]
121
    public function convertIntResult(mixed $value) : int
122
    {
123
        if (is_string($value)) {
7✔
124
            return TypeConverter::convertStringToInt($value);
7✔
125
        }
126

127
        throw GeometryEngineException::unexpectedDatabaseReturnType('integer string', $value);
×
128
    }
129

130
    #[Override]
131
    public function convertFloatResult(mixed $value) : float
132
    {
133
        if (is_string($value) && is_numeric($value)) {
46✔
134
            return (float) $value;
45✔
135
        }
136

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

140
    #[Override]
141
    public function convertBoolResult(mixed $value) : bool
142
    {
143
        return match ($value) {
163✔
144
            't' => true,
90✔
145
            'f' => false,
79✔
146
            default => throw GeometryEngineException::unexpectedDatabaseReturnType('t or f', $value),
163✔
147
        };
163✔
148
    }
149
}
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