add column unique numbering scheme, more efficient selects
This commit is contained in:
@@ -128,14 +128,13 @@ abstract class BaseExporter
|
||||
|
||||
$start = 0;
|
||||
while ($start < $count) {
|
||||
$rows = $revision->rows()->offset($start)->limit($chunkSize)->get();
|
||||
// TODO raw query to allow selecting aggregates, column subsets, etc
|
||||
$rows = $revision->rowsData($this->columns, false)
|
||||
->offset($start)->limit($chunkSize)->get()->toArray();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$data = $row->data;
|
||||
|
||||
// column renaming, value formatting...
|
||||
|
||||
yield $data;
|
||||
unset($row['_row_pivot']);
|
||||
yield $row;
|
||||
}
|
||||
|
||||
$start += $chunkSize;
|
||||
|
||||
@@ -99,20 +99,7 @@ class CStructArrayExporter extends BaseExporter
|
||||
echo ",";
|
||||
}
|
||||
|
||||
$val = 0;
|
||||
switch ($field->type) {
|
||||
case 'string':
|
||||
$val = "";
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
$val = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($row->{$field->name})) {
|
||||
$val = $row->{$field->name};
|
||||
}
|
||||
$val = $row[$field->name];
|
||||
|
||||
// export to C format
|
||||
switch ($field->type) {
|
||||
|
||||
+32
-15
@@ -11,9 +11,10 @@ use MightyPork\Utils\Utils;
|
||||
/**
|
||||
* Helper class representing one column in a data table.
|
||||
*
|
||||
* @property-read string $id
|
||||
* @property-read string $type
|
||||
* @property-read string $name
|
||||
* @property-read string $title
|
||||
* @property-read string $type
|
||||
*/
|
||||
class Column implements JsonSerializable
|
||||
{
|
||||
@@ -21,9 +22,10 @@ class Column implements JsonSerializable
|
||||
'int', 'bool', 'float', 'string'
|
||||
];
|
||||
|
||||
private $id;
|
||||
private $type;
|
||||
private $name;
|
||||
private $title;
|
||||
private $type;
|
||||
|
||||
public static function columnsFromJson($columns)
|
||||
{
|
||||
@@ -36,13 +38,13 @@ class Column implements JsonSerializable
|
||||
}, $columns);
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
/**
|
||||
* Set column ID
|
||||
* @param string $id - GCID
|
||||
*/
|
||||
public function setID($id)
|
||||
{
|
||||
if (property_exists($this, $name)) {
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
throw new NotApplicableException("No such column property");
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,18 +54,32 @@ class Column implements JsonSerializable
|
||||
*/
|
||||
public function __construct($obj)
|
||||
{
|
||||
$b = new \objBag($obj);
|
||||
$b = objBag($obj);
|
||||
|
||||
if (!$b->has('name')) throw new NotApplicableException('Missing name in column');
|
||||
if (!$b->has('type')) throw new NotApplicableException('Missing type in column');
|
||||
|
||||
if ($b->name[0] == '_') { // global row ID
|
||||
throw new NotApplicableException("Column name can't start with underscore.");
|
||||
}
|
||||
|
||||
if (!in_array($b->type, self::colTypes)) {
|
||||
throw new NotApplicableException("\"$b->type\" is not a valid column type.");
|
||||
}
|
||||
|
||||
$this->id = $b->get('id', null);
|
||||
$this->name = $b->name;
|
||||
$this->title = $b->title;
|
||||
$this->type = $b->type;
|
||||
$this->title = $b->title ?: $b->name;
|
||||
}
|
||||
|
||||
if ($this->name == '_grid') { // global row ID
|
||||
throw new NotApplicableException("_grid is a reserved column name.");
|
||||
public function __get($name)
|
||||
{
|
||||
if (property_exists($this, $name)) {
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
if (!in_array($this->type, self::colTypes)) {
|
||||
throw new NotApplicableException("\"$this->type\" is not a valid column type.");
|
||||
}
|
||||
throw new NotApplicableException("No such column property: $name");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +88,7 @@ class Column implements JsonSerializable
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'title' => $this->title,
|
||||
'type' => $this->type,
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Tables;
|
||||
|
||||
use App\Models\Row;
|
||||
use MightyPork\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Generates a sequence of string codes for internal naming of columns
|
||||
*
|
||||
* Produces database-unique lowercase identifiers for created or proposed columns.
|
||||
* Column identifiers are used in row objects to uniquely identify data even if the
|
||||
* revision header (columns object) is modified, such as reordering, changing name,
|
||||
* adding new column in concurrent proposals, etc.
|
||||
*
|
||||
* Thanks to this uniqueness, it could even be possible to compare or merge forks
|
||||
* of the same table.
|
||||
*/
|
||||
class ColumnNumerator
|
||||
{
|
||||
const ALPHABET = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
|
||||
|
||||
/** @var int */
|
||||
private $next;
|
||||
/** @var int */
|
||||
private $last;
|
||||
|
||||
/**
|
||||
* Create numerator for the given number of columns
|
||||
*/
|
||||
public function __construct($capacity)
|
||||
{
|
||||
list($this->next, $this->last) = Row::allocateColIDs($capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next column name, incrementing the internal state
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if ($this->next > $this->last)
|
||||
throw new \OutOfBoundsException("Column numerator has run out of allocated GCID slots");
|
||||
|
||||
$key = Utils::alphabetEncode($this->next, self::ALPHABET);
|
||||
$this->next++;
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
@@ -44,15 +44,7 @@ class CsvExporter extends BaseExporter
|
||||
fputcsv($handle, $columnNames, $this->delimiter);
|
||||
|
||||
foreach ($this->iterateRows() as $row) {
|
||||
$items = [];
|
||||
foreach ($this->columns as $column) {
|
||||
if (isset($row->{$column->name})) {
|
||||
$items[] = $row->{$column->name};
|
||||
} else {
|
||||
$items[] = null;
|
||||
}
|
||||
}
|
||||
fputcsv($handle, $items, $this->delimiter);
|
||||
fputcsv($handle, array_values($row), $this->delimiter);
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
@@ -53,7 +53,7 @@ class PhpExporter extends BaseExporter
|
||||
|
||||
var_export($column->name);
|
||||
echo ' => ';
|
||||
var_export($row->{$column->name});
|
||||
var_export($row[$column->name]);
|
||||
}
|
||||
|
||||
echo ']';
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Tables;
|
||||
|
||||
use App\Models\Row;
|
||||
|
||||
class RowNumerator
|
||||
{
|
||||
/** @var int */
|
||||
private $next;
|
||||
/** @var int */
|
||||
private $last;
|
||||
|
||||
/**
|
||||
* Create a numerator for the given number of rows.
|
||||
*
|
||||
* @param int $capacity
|
||||
*/
|
||||
public function __construct($capacity)
|
||||
{
|
||||
list($this->next, $this->last) = Row::allocateRowIDs($capacity);
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
if ($this->next > $this->last)
|
||||
throw new \OutOfBoundsException("Row numerator has run out of allocated GRID slots");
|
||||
|
||||
return $this->next++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user