Browse Source

Simplify array flattening

microsub
J. King 5 years ago
parent
commit
c706a76057
  1. 45
      lib/Db/AbstractStatement.php
  2. 11
      lib/Misc/ValueInfo.php
  3. 6
      tests/cases/Misc/TestValueInfo.php

45
lib/Db/AbstractStatement.php

@ -46,23 +46,14 @@ abstract class AbstractStatement implements Statement {
return $query; return $query;
} }
public function retypeArray(array $bindings, bool $append = false): bool { public function retypeArray(array $bindings): bool {
if (!$append) { $this->types = [];
$this->types = []; foreach (ValueInfo::flatten($bindings) as $binding) { // recursively flatten any arrays, which may be provided for SET or IN() clauses
} $bindId = self::TYPES[trim(strtolower($binding))] ?? 0;
foreach ($bindings as $binding) { assert($bindId, new Exception("paramTypeInvalid", $binding));
if (is_array($binding)) { $this->types[] = $bindId;
// recursively flatten any arrays, which may be provided for SET or IN() clauses
$this->retypeArray($binding, true);
} else {
$bindId = self::TYPES[trim(strtolower($binding))] ?? 0;
assert($bindId, new Exception("paramTypeInvalid", $binding));
$this->types[] = $bindId;
}
}
if (!$append) {
$this->prepare(static::mungeQuery($this->query, $this->types));
} }
$this->prepare(static::mungeQuery($this->query, $this->types));
return true; return true;
} }
@ -79,26 +70,22 @@ abstract class AbstractStatement implements Statement {
} }
} }
protected function bindValues(array $values, int $offset = null): int { protected function bindValues(array $values): bool {
$a = (int) $offset; // recursively flatten any arrays, which may be provided for SET or IN() clauses
foreach ($values as $value) { $values = ValueInfo::flatten($values);
if (is_array($value)) { foreach ($values as $a => $value) {
// recursively flatten any arrays, which may be provided for SET or IN() clauses if (array_key_exists($a, $this->types)) {
$a += $this->bindValues($value, $a);
} elseif (array_key_exists($a, $this->types)) {
$value = $this->cast($value, $this->types[$a]); $value = $this->cast($value, $this->types[$a]);
$this->bindValue($value, $this->types[$a] % self::T_NOT_NULL, ++$a); $this->bindValue($value, $this->types[$a] % self::T_NOT_NULL, ++$a);
} else { } else {
throw new Exception("paramTypeMissing", $a+1); throw new Exception("paramTypeMissing", $a+1);
} }
} }
// once the last value is bound, check that all parameters have been supplied values and bind null for any missing ones // once all values are bound, check that all parameters have been supplied values and bind null for any missing ones
// SQLite will happily substitute null for a missing value, but other engines (viz. PostgreSQL) produce an error // SQLite will happily substitute null for a missing value, but other engines (viz. PostgreSQL) produce an error
if (is_null($offset)) { for ($a = sizeof($values); $a < sizeof($this->types); $a++) {
while ($a < sizeof($this->types)) { $this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, $a + 1);
$this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, ++$a);
}
} }
return $a - $offset; return true;
} }
} }

11
lib/Misc/ValueInfo.php

@ -397,6 +397,17 @@ class ValueInfo {
} }
} }
public static function flatten(array $arr): array {
$arr = array_values($arr);
for ($a = 0; $a < sizeof($arr); $a++) {
if (is_array($arr[$a])) {
array_splice($arr, $a, 1, $arr[$a]);
$a--;
}
}
return $arr;
}
public static function int($value): int { public static function int($value): int {
$out = 0; $out = 0;
if (is_null($value)) { if (is_null($value)) {

6
tests/cases/Misc/TestValueInfo.php

@ -639,4 +639,10 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest {
$out->f = $msec; $out->f = $msec;
return $out; return $out;
} }
public function testFlattenArray() {
$arr = [1, [2, 3, [4, 5]], 6, [[7, 8], 9, 10]];
$exp = range(1,10);
$this->assertSame($exp, I::flatten($arr));
}
} }

Loading…
Cancel
Save