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

elie29 / oci-driver / 20226421753

15 Dec 2025 09:06AM UTC coverage: 66.304% (-0.6%) from 66.923%
20226421753

push

github

Elie NEHME
🤖 Enhanced OCI driver with error handling, parameter validation, environment management, and added unit tests.

10 of 20 new or added lines in 5 files covered. (50.0%)

1 existing line in 1 file now uncovered.

183 of 276 relevant lines covered (66.3%)

7.08 hits per line

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

0.0
/src/OCI/Driver/Driver.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Elie\OCI\Driver;
6

7
use Elie\OCI\Debugger\DebuggerInterface;
8
use Elie\OCI\Driver\Parameter\Parameter;
9

10
class Driver implements DriverInterface
11
{
12
    /** OPTIONS pour oci_fetch */
13
    public const FETCH_ALL_OPT = OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS;
14
    public const FETCH_ARRAY_OPT = OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS;
15
    public const FETCH_ONE_COL = OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS;
16

17
    /** @var resource */
18
    protected mixed $connection;
19

20
    protected DebuggerInterface $debugger;
21

22
    /** @var int Autocommit by default */
23
    protected int $commitOption = OCI_COMMIT_ON_SUCCESS;
24

25
    /**
26
     * @param resource $connection
27
     */
28
    public function __construct(mixed $connection, DebuggerInterface $debugger)
29
    {
30
        $this->connection = $connection;
×
31
        $this->debugger = $debugger;
×
32
    }
33

34
    public function getConnection(): mixed
35
    {
36
        return $this->connection;
×
37
    }
38

39
    public function beginTransaction(): self
40
    {
41
        $this->commitOption = OCI_NO_AUTO_COMMIT;
×
42
        return $this;
×
43
    }
44

45
    public function commitTransaction(): self
46
    {
47
        if ($this->connection && OCI_NO_AUTO_COMMIT === $this->commitOption) {
×
48
            oci_commit($this->connection);
×
49
        }
50
        $this->commitOption = OCI_COMMIT_ON_SUCCESS;
×
51
        return $this;
×
52
    }
53

54
    public function rollbackTransaction(): self
55
    {
56
        if ($this->connection && OCI_NO_AUTO_COMMIT === $this->commitOption) {
×
57
            oci_rollback($this->connection);
×
58
        }
59
        $this->commitOption = OCI_COMMIT_ON_SUCCESS;
×
60
        return $this;
×
61
    }
62

63
    /**
64
     * @throws DriverException
65
     */
66
    public function executeUpdate(string $sql, ?Parameter $bind = null): int
67
    {
68
        $statement = $this->executeQuery($sql, $bind);
×
69

70
        $count = oci_num_rows($statement);
×
71

72
        oci_free_statement($statement);
×
73

74
        return (int)$count;
×
75
    }
76

77
    /**
78
     * @throws DriverException
79
     */
80
    public function fetchColumns(string $sql, ?Parameter $bind = null): array
81
    {
82
        $statement = $this->executeQuery($sql, $bind);
×
83

84
        $data = [];
×
85

86
        oci_fetch_all($statement, $data, 0, -1, self::FETCH_ONE_COL);
×
87

88
        oci_free_statement($statement);
×
89

90
        return $data ?: [];
×
91
    }
92

93
    /**
94
     * @throws DriverException
95
     */
96
    public function fetchColumn(string $sql, ?Parameter $bind = null): array
97
    {
98
        $data = $this->fetchColumns($sql, $bind);
×
99

100
        return $data[0] ?? [];
×
101
    }
102

103
    /**
104
     * @throws DriverException
105
     */
106
    public function fetchAllAssoc(string $sql, ?Parameter $bind = null): array
107
    {
108
        $statement = $this->executeQuery($sql, $bind);
×
109

110
        $data = [];
×
111

112
        oci_fetch_all($statement, $data, 0, -1, self::FETCH_ALL_OPT);
×
113

114
        oci_free_statement($statement);
×
115

116
        return $data ?: [];
×
117
    }
118

119
    /**
120
     * @throws DriverException
121
     */
122
    public function fetchAssoc(string $sql, ?Parameter $bind = null): array
123
    {
124
        $statement = $this->executeQuery($sql, $bind);
×
125

126
        $data = oci_fetch_array($statement, self::FETCH_ARRAY_OPT);
×
127

128
        oci_free_statement($statement);
×
129

130
        return $data ?: [];
×
131
    }
132

133
    /**
134
     * YOU SHOULD MANUALLY CALL oci_free_statement!
135
     * @throws DriverException
136
     */
137
    public function executeQuery(string $sql, ?Parameter $bind = null): mixed
138
    {
139
        $statement = oci_parse($this->connection, $sql);
×
140

141
        if ($statement === false) {
×
142
            $this->error($sql, $bind, $this->connection); // @codeCoverageIgnore
143
        }
144

145
        $this->ociExecuteAndDebug($statement, $sql, $bind);
×
146

147
        return $statement;
×
148
    }
149

150
    /**
151
     * @param resource $statement
152
     * @param string $sql
153
     * @param Parameter|null $bind
154
     * @throws DriverException
155
     */
156
    private function ociExecuteAndDebug($statement, string $sql, Parameter $bind = null): void
157
    {
158
        $this->debugger->start();
×
159

160
        $attributes = $bind ? $bind->getAttributes() : [];
×
161

162
        foreach ($attributes as $column => $params) {
×
NEW
163
            oci_bind_by_name($statement, $column, $params->variable, $params->maxlength, $params->type);
×
164
        }
165

166
        if (!@oci_execute($statement, $this->commitOption)) {
×
167
            $this->error($sql, $bind, $statement);
×
168
        }
169

170
        $this->debugger->end($sql, $attributes);
×
171
    }
172

173
    /**
174
     * @param string $sql
175
     * @param Parameter|null $bind
176
     * @param resource|null $resource
177
     * @throws DriverException
178
     */
179
    private function error(string $sql, Parameter $bind = null, $resource = null): void
180
    {
181
        $ociError = oci_error($resource) ?: ['message' => 'OCI Driver unknown error'];
×
182
        $attributes = $bind ? $bind->getAttributes() : [];
×
183

184
        $message = sprintf(
×
185
            'SQL error: %s, SQL: %s, BIND: %s',
×
186
            $ociError['message'],
×
187
            $sql,
×
188
            json_encode($attributes)
×
189
        );
×
190

191
        $this->rollbackTransaction();
×
192

193
        throw new DriverException($message);
×
194
    }
195
}
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