-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
function pg_parse_array(string $arraystring, bool $reset=true): array
{
if ($arraystring === '') {
throw new SQLException('['.__FUNCTION__.']: Empty string is not a Postgres array literal');
}
static $i = 0;
if ($reset) {
$i = 0;
}
$matches = [];
// $indexer = 1; // by default sql arrays start at 1
$indexer = 0;
// handle [2:4]= cases
if (preg_match('/^\[(?P<index_start>\d+):(?P<index_end>\d+)]=/', substr($arraystring, $i), $matches)) {
$indexer = (int)$matches['index_start'];
$pos = strpos($arraystring, '{');
if ($pos === false) {
throw new SQLException('['.__FUNCTION__.']: Unexpected input (no "{")');
}
$i = $pos;
}
if (!isset($arraystring[$i]) || $arraystring[$i] !== '{') {
throw new SQLException('['.__FUNCTION__.']: Unexpected input');
}
$i++;
$work = [];
$curr = '';
$length = strlen($arraystring);
$quoted = false;
while ($i < $length) {
switch ($arraystring[$i]) {
case '{':
$sub = pg_parse_array($arraystring, false);
$work[$indexer++] = $sub; // keep empty sub-arrays too
break;
case '}':
$i++;
if ($quoted || strlen($curr) > 0) {
if (!$quoted && strtoupper($curr) === 'NULL') {
$curr = null;
}
$work[$indexer++] = $curr; // will correctly add '' for {""}
}
return $work;
case '\\':
$i++;
$curr .= $arraystring[$i];
$i++;
break;
case '"':
$quoted = true;
$openq = $i;
do {
$closeq = strpos($arraystring, '"' , $i + 1);
if ($closeq === false) {
throw new SQLException('['.__FUNCTION__.']: Unterminated quote');
}
$escaped = $closeq > $openq
&& preg_match('/(\\\\+)$/', substr($arraystring, $openq + 1, $closeq - ($openq + 1)), $matches)
&& (strlen($matches[1]) % 2);
if ($escaped) {
$i = $closeq;
} else {
break;
}
} while(true);
if ($closeq <= $openq) {
throw new SQLException('['.__FUNCTION__.']: Unexpected condition');
}
$chunk = substr($arraystring, $openq + 1, $closeq - ($openq + 1));
// Unescape Postgres array output escapes inside quoted elements:
// \" -> " and \\ -> \
$chunk = str_replace('\\\\', '\\', $chunk);
$chunk = str_replace('\\"', '"', $chunk);
$curr .= $chunk;
$i = $closeq + 1;
break;
case ',':
if ($quoted || strlen($curr) > 0) {
if (!$quoted && strtoupper($curr) === 'NULL') {
$curr = null;
}
$work[$indexer++] = $curr;
}
$curr = '';
$quoted = false;
$i++;
break;
default:
$curr .= $arraystring[$i];
$i++;
}
}
throw new SQLException('['.__FUNCTION__.']: Unexpected line end');
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels