depage-xmldb v2.3.1
XML documents in a relational database
Loading...
Searching...
No Matches
NodeBatch.php
Go to the documentation of this file.
1<?php
2
12
13namespace Depage\XmlDb\Helpers;
14
15use Depage\XmlDb\Exceptions\XmlDbException;
16
33{
34 use IdentifierChecker;
35
39 public const DEFAULT_SIZE = 200;
40
41 protected $pdo;
42
46 protected $entries = [];
47
56 public function __construct(
57 $pdo,
58 protected string $table,
59 protected int $docId,
60 protected int $size = self::DEFAULT_SIZE
61 ) {
62 $this->pdo = $pdo;
63
64 $this->checkIdentifier($table, 'table');
65 }
66
67 public function isEmpty(): bool
68 {
69 return count($this->entries) == 0;
70 }
71
76 public function isFull(): bool
77 {
78 return count($this->entries) >= $this->size;
79 }
80
94 public function add($key, $id, $parentId, $pos, $name, $value, $type): void
95 {
96 $this->entries[$key] = [
97 'id' => $id,
98 'parent_id' => $parentId,
99 'pos' => $pos,
100 'name' => $name,
101 'value' => $value,
102 'type' => $type,
103 ];
104 }
105
113 public function write(): array
114 {
115 if ($this->isEmpty()) {
116 return [];
117 }
118
120 $this->entries = [];
121
122 $this->insert($entries);
123
124 $ids = $this->readAutoIncrementIds($entries);
125
126 foreach ($entries as $key => $entry) {
127 if (!is_null($entry['id'])) {
128 $ids[$key] = $entry['id'];
129 }
130 }
131 ksort($ids);
132
133 return $ids;
134 }
135
141 protected function insert(array $entries): void
142 {
143 $values = [];
144 $params = [];
145
146 foreach ($entries as $entry) {
147 $values[] = '(?, ?, ?, ?, ?, ?, ?)';
148 array_push(
149 $params,
150 $entry['id'],
151 $entry['parent_id'],
152 $this->docId,
153 $entry['pos'],
154 $entry['name'],
155 $entry['value'],
156 $entry['type']
157 );
158 }
159
160 $query = $this->pdo->prepare(
161 "INSERT {$this->table}
162 (id, id_parent, id_doc, pos, name, value, type)
163 VALUES
164 " . implode(", ", $values) . "
165 ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)"
166 );
167 $query->execute($params);
168 }
169
180 protected function readAutoIncrementIds(array $entries): array
181 {
182 $wanted = [];
183 $parents = [];
184 $positions = [];
185
186 foreach ($entries as $key => $entry) {
187 if (!is_null($entry['id'])) {
188 continue;
189 }
190
191 $wanted[$entry['parent_id'] . ':' . $entry['pos']] = $key;
192 $parents[] = (int) $entry['parent_id'];
193 $positions[] = (int) $entry['pos'];
194 }
195
196 if (count($wanted) == 0) {
197 return [];
198 }
199
200 $parents = array_values(array_unique($parents));
201 $positions = array_values(array_unique($positions));
202
203 $query = $this->pdo->prepare(
204 "SELECT id, id_parent, pos
205 FROM {$this->table}
206 WHERE id_doc = ?
207 AND id_parent IN (" . implode(", ", array_fill(0, count($parents), '?')) . ")
208 AND pos IN (" . implode(", ", array_fill(0, count($positions), '?')) . ")"
209 );
210 $query->execute(array_merge(
211 [$this->docId],
212 $parents,
213 $positions
214 ));
215 $rows = $query->fetchAll(\PDO::FETCH_OBJ);
216 $query->closeCursor();
217
218 $ids = [];
219 foreach ($rows as $row) {
220 $sibling = $row->id_parent . ':' . $row->pos;
221
222 if (isset($wanted[$sibling])) {
223 $ids[$wanted[$sibling]] = (int) $row->id;
224 unset($wanted[$sibling]);
225 }
226 }
227
228 if (count($wanted) > 0) {
229 throw new XmlDbException("Inserted node could not be found again after batch insert.");
230 }
231
232 return $ids;
233 }
234}
235
236/* vim:set ft=php sw=4 sts=4 fdm=marker et : */
isFull()
whether the batch holds as many nodes as a single statement writes; a caller that needs the ids of a ...
Definition NodeBatch.php:76
readAutoIncrementIds(array $entries)
finds the ids the auto increment handed out for the nodes of the batch that did not carry one; the un...
add($key, $id, $parentId, $pos, $name, $value, $type)
collects one node of the batch
Definition NodeBatch.php:94
write()
inserts the collected nodes with one statement and empties the batch
__construct( $pdo, protected string $table, protected int $docId, protected int $size=self::DEFAULT_SIZE)
Definition NodeBatch.php:56
insert(array $entries)
writes the rows of one batch; nodes that carry an id are inserted with it, a node whose id is already...
const DEFAULT_SIZE
number of nodes written with a single insert statement
Definition NodeBatch.php:39
$entries
rows of the batch, keyed by the key the caller passed to add()
Definition NodeBatch.php:46