Add Map expression

Signed-off-by: davidarendsen <davidarendsen@hey.com>
This commit is contained in:
davidarendsen 2022-10-25 17:55:35 +00:00
commit d52f3e9d74
10 changed files with 140 additions and 12 deletions

View file

@ -16,6 +16,8 @@ composer require arendsen/fluxquerybuilder
use Arendsen\FluxQueryBuilder\QueryBuilder;
use Arendsen\FluxQueryBuilder\Expression\KeyFilter;
use Arendsen\FluxQueryBuilder\Expression\Map;
use Arendsen\FluxQueryBuilder\Expression\Selection;
$queryBuilder = new QueryBuilder();
$queryBuilder->fromBucket('test_bucket')
@ -26,7 +28,13 @@ $queryBuilder->fromBucket('test_bucket')
KeyFilter::setEqualTo('_field', 'username')
->orEqualTo('_field', 'email')
)
->addMap('r with name: r.user')
->addMap(Map::with('name', 'user'))
->addMap(Map::columns([
'time' => '_time',
'source' => 'tag',
'alert' => Selection::if('r._value > 10')->then(true)->else(false),
'test' => Selection::if('r._value > 10')->then('yes')->else('no'),
]))
->addGroup(['_field', 'ip']);
echo $queryBuilder->build();

View file

@ -204,4 +204,4 @@ class KeyFilter extends Base
throw new Exception('Operator "' . $operator . '" is not supported!');
}
}
}
}

View file

@ -207,4 +207,4 @@ class KeyValue extends Base
throw new Exception('Operator "' . $operator . '" is not supported!');
}
}
}
}

27
src/Expression/Map.php Normal file
View file

@ -0,0 +1,27 @@
<?php
namespace Arendsen\FluxQueryBuilder\Expression;
use Arendsen\FluxQueryBuilder\Type\FieldRecordType;
class Map extends Base
{
private static $string;
public static function with(string $name, string $content): Map
{
self::$string = 'r with ' . $name . ': ' . $content;
return new self();
}
public static function columns(array $columns)
{
self::$string = new FieldRecordType($columns);
return new self();
}
public function __toString()
{
return self::$string;
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace Arendsen\FluxQueryBuilder\Expression;
use Arendsen\FluxQueryBuilder\Type;
class Selection extends Base
{
private $string;
private function __construct(string $string)
{
$this->string = $string;
}
public static function if(string $value): Selection
{
return new self('if ' . $value);
}
public function then($then): Selection
{
$this->string .= ' then ' . new Type($then);
return $this;
}
public function else($else): Selection
{
$this->string .= ' else ' . new Type($else);
return $this;
}
public function __toString()
{
return $this->string;
}
}

View file

@ -2,14 +2,16 @@
namespace Arendsen\FluxQueryBuilder\Functions;
use Arendsen\FluxQueryBuilder\Expression\Map as MapExpression;
class Map extends Base
{
/**
* @var array $query
* @var mixed $query
*/
private $query;
public function __construct(string $query)
public function __construct($query)
{
$this->query = $query;
}

View file

@ -158,7 +158,7 @@ class QueryBuilder
return $this;
}
public function addMap(string $query): QueryBuilder
public function addMap($query): QueryBuilder
{
$this->addToQuery(
self::FLUX_PART_MAP,

View file

@ -0,0 +1,27 @@
<?php
namespace Arendsen\FluxQueryBuilder\Type;
use Arendsen\FluxQueryBuilder\Settings;
use Arendsen\FluxQueryBuilder\Type;
class FieldRecordType implements TypeInterface
{
public const SETTING_IS_RECORD = 'isRecord';
public function __construct(array $value)
{
$this->value = $value;
}
public function __toString(): string
{
array_walk($this->value, function (&$value, $key) {
if (is_string($key)) {
$value = $key . ': ' . $value;
}
});
return '{' . implode(', ', $this->value) . '}';
}
}

View file

@ -5,30 +5,30 @@ declare(strict_types=1);
namespace Tests\Expression;
use Exception;
use Arendsen\FluxQueryBuilder\Expression\KeyValue;
use Arendsen\FluxQueryBuilder\Expression\KeyFilter;
use PHPUnit\Framework\TestCase;
final class KeyValueExpressionTest extends TestCase
final class KeyFilterExpressionTest extends TestCase
{
public function testSimpleKeyvalue()
{
$keyvalue = KeyValue::setEqualTo('_measurement', 'test_measurement')
$keyFilter = KeyFilter::setEqualTo('_measurement', 'test_measurement')
->andEqualTo('_field', 'user')
->or('count', '>=', '1')
->and('user', KeyValue::EQUAL_TO, 'my_username')
->and('user', KeyFilter::EQUAL_TO, 'my_username')
->orNotEqualTo('test', 'world');
$query = 'r._measurement == "test_measurement" and r._field == "user" or ' .
'r.count >= "1" and r.user == "my_username" or r.test != "world"';
$this->assertEquals($keyvalue->__toString(), $query);
$this->assertEquals($keyFilter->__toString(), $query);
}
public function testInvalidOperator()
{
$this->expectException(Exception::class);
KeyValue::set('_measurement', '9dkda9e', 'test_measurement')
KeyFilter::set('_measurement', '9dkda9e', 'test_measurement')
->andEqualTo('_field', 'user')
->or('_field', '==', 'field2')
->andEqualTo('user', 'my_username');

View file

@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Tests\Functions;
use Arendsen\FluxQueryBuilder\Functions\Map;
use Arendsen\FluxQueryBuilder\Expression\Map as MapExpression;
use Arendsen\FluxQueryBuilder\Expression\Selection as SelectionExpression;
use PHPUnit\Framework\TestCase;
final class MapFunctionTest extends TestCase
@ -17,4 +19,29 @@ final class MapFunctionTest extends TestCase
$this->assertEquals($query, $expression->__toString());
}
public function testWithMapObject()
{
$expression = new Map(MapExpression::with('name', 'r.user'));
$query = '|> map(fn: (r) => ({ r with name: r.user })) ';
$this->assertEquals($query, $expression->__toString());
}
public function testRecordMapObject()
{
$expression = new Map(MapExpression::columns([
'time' => 'r._time',
'source' => 'r.tag',
'alert' => SelectionExpression::if('r._value > 10')->then(true)->else(false),
'test' => SelectionExpression::if('r._value > 10')->then('yes')->else('no')
]));
$query = '|> map(fn: (r) => ({ {time: r._time, source: r.tag, ' .
'alert: if r._value > 10 then true else false, ' .
'test: if r._value > 10 then "yes" else "no"} })) ';
$this->assertEquals($query, $expression->__toString());
}
}