Skip to content

Commit

Permalink
Added more (failing - commented) tests & logic
Browse files Browse the repository at this point in the history
Updated Travis config.
  • Loading branch information
phptek committed Jun 12, 2016
1 parent 4cc8d7d commit 01120a2
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 39 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ php:
- 7.0

env:
- DB=MYSQL
- DB=MYSQL CORE_RELEASE=3.2

matrix:
include:
- php: 5.6
env: DB=MYSQL
env: DB=MYSQL CORE_RELEASE=3.2
- php: 5.6
env: DB=PGSQL
env: DB=PGSQL CORE_RELEASE=3.3
allow_failures:
- php: 7.0

Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,34 @@ which JSON can be stored and from which it can be queried.
Once stored, the module exposes a simple query API based on the [JSON operators found in Postgres v9.2+](https://www.postgresql.org/docs/9.5/static/functions-json.html),
but with some modifications:

In Postgres both the `->` and `->>` operators act as a string and integer key matcherx on a JSON source as array or object. The module
however treats both source types the same - they are after all *both* JSON so `->` is used as an **Integer Matcher** and `->>` as a string matcher.
In Postgres both the `->` and `->>` operators act as string and integer key matchers on a JSON array or object. The module
however treats both source types the same - they are after all *both JSON* so `->` is used as an **Integer Matcher** and `->>` as a string matcher
*regardless* of the "type" of JSON stored.

In Postgress the `#>` patch match operator can act as an object or text matcher, but again, the module wishes to simplify things and as such
In Postgress the `#>` path match operator can act as an object or a text matcher, but again, the module wishes to simplify things and as such
the `#>` operator is *just a simple path matcher*.

I see nothing but confusion if the same operator were to be treated differently
depending on the format of the source data.
depending on the format of the source data but am prepared for discussion on it if any were forthcoming.

Note: This module's query API is based on a relatively simple JSON to array conversion principle.
It does *not* use Postgres' or MySQL's native JSON operators. The aim however
It does *not* use Postgres' or MySQL's JSON operators at the ORM level. The aim however
is to allow dev's to use their preferred DB's syntax, and to this end you can set
the module into `mysql` or `postgres` mode using SS config:

```yml
JSONText:
backend: mysql
backend: postgres
```
Note: The module default is to use `postgres` which is also the only backend that will work.
Note: The module default is to use `postgres` which is also the only backend that will work at the moment.

# Stability

This is currently *alpha software*. At time of writing (June 2016) there is
only partial support for the `->` and `->>` operators and although well-tested,
they are far from complete (or even correct).
support for the `->` (Int matcher), `->>` (String matcher) and `#>` (Path matcher) operators and although well-tested,
they are far from complete.

This leads me to..

Expand Down
16 changes: 14 additions & 2 deletions code/models/JSONBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function __construct($key, $val, $idx, $operator, $operand, $jsonText)

/**
* Match on keys by INT.
*
*
* @return array
*/
public function matchIfKeyIsInt()
Expand All @@ -83,7 +83,7 @@ public function matchIfKeyIsInt()

/**
* Match on keys by STRING.
*
*
* @return array
*/
public function matchIfKeyIsStr()
Expand All @@ -101,6 +101,8 @@ public function matchIfKeyIsStr()
*
* @return array
* @throws \JSONText\Exceptions\JSONTextException
* @todo Naively only returns the first match. But what about where source JSON has legit duplicate keys? We need
* to return an array of matches..
*/
public function matchOnPath()
{
Expand Down Expand Up @@ -132,6 +134,16 @@ public function matchOnPath()
return $this->val[$vals[0]];
}

/* if ($this->key === $keys[0] && is_array($this->val) && !empty($this->val[$vals[0]])) {
$this->jsonText->updateCache($this->val[$vals[0]]);
}*/

/* if (count($this->jsonText->cache) === 1) {
return $this->jsonText->cache[0];
}*/

// return $this->jsonText->cache;

return [];
}

Expand Down
30 changes: 24 additions & 6 deletions code/models/fieldtypes/JSONText.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class JSONText extends \StringField
* @var \RecursiveIteratorIterator
*/
protected $data;

/**
* @var array
*/
protected $cache = [];

public function updateCache($val) {
$this->cache[] = $val;
}

/**
* Returns an input field.
Expand Down Expand Up @@ -130,7 +139,7 @@ public function setReturnType($type)
{
if (!in_array($type, ['json', 'array'])) {
$msg = 'Bad type: ' . $type . ' passed to ' . __FUNCTION__;
throw new \JSONText\Exceptions\JSONTextException($msg);
throw new JSONTextException($msg);
}

$this->returnType = $type;
Expand Down Expand Up @@ -158,7 +167,7 @@ public function getValueAsIterable()

if (!$this->isJson($json)) {
$msg = 'DB data is munged.';
throw new \JSONText\Exceptions\JSONTextException($msg);
throw new JSONTextException($msg);
}

if (!$this->data) {
Expand All @@ -169,7 +178,16 @@ public function getValueAsIterable()
}

return $this->data;
}

/**
* Returns the value of this field as a flattened array
*
* @return array
*/
public function getValueAsArray()
{
return iterator_to_array($this->getValueAsIterable());
}

/**
Expand Down Expand Up @@ -272,7 +290,7 @@ public function nth($n)

if (!is_int($n)) {
$msg = 'Argument passed to ' . __FUNCTION__ . ' must be an integer.';
throw new \JSONText\Exceptions\JSONTextException($msg);
throw new JSONTextException($msg);
}

$i = 0;
Expand Down Expand Up @@ -306,7 +324,7 @@ public function query($operator, $operand)

if (!$this->isValidOperator($operator)) {
$msg = 'JSON operator: ' . $operator . ' is invalid.';
throw new \JSONText\Exceptions\JSONTextException($msg);
throw new JSONTextException($msg);
}

$i = 0;
Expand Down Expand Up @@ -350,7 +368,7 @@ private function marshallQuery($key, $val, $idx, $args)

if (!in_array($operator, $operators)) {
$msg = 'Invalid ' . $backend . ' operator: ' . $operator . ', used for JSON query.';
throw new \JSONText\Exceptions\JSONTextException($msg);
throw new JSONTextException($msg);
}

foreach ($operators as $routine => $backendOperator) {
Expand All @@ -365,7 +383,7 @@ private function marshallQuery($key, $val, $idx, $args)
]);

if ($operator === $backendOperator && $result = $backendDBApiInst->$routine()) {
return $result;
return $result;
}
}

Expand Down
16 changes: 15 additions & 1 deletion tests/JSONTextTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class JSONTextTest extends SapphireTest
'hash_simple' => MODULE_DIR . '/tests/fixtures/json/hash_simple.json',
'invalid' => MODULE_DIR . '/tests/fixtures/json/invalid.json',
'hash_deep' => MODULE_DIR . '/tests/fixtures/json/hash_deep.json',
'hash_dupes' => MODULE_DIR . '/tests/fixtures/json/hash_duplicates.json',
'hash_dupes' => MODULE_DIR . '/tests/fixtures/json/hash_duplicated.json',
'empty' => MODULE_DIR . '/tests/fixtures/json/empty.json'
];

Expand Down Expand Up @@ -247,6 +247,20 @@ public function testQuery_MatchPath_AsJSON()

$this->assertEquals('{"fast":{"Kawasaki":"KR1S250"},"slow":{"Honda":"FS150"}}', $field->query('#>', '{"bikes":"japanese"}'));
}

/**
* Tests query() by means of path-matching using the Postgres path match operator: '#>' but where duplicate keys exist
* for different parent structures in source data
*/
/* public function testQuery_MatchPathDuplicate_AsArray()
{
// Hashed
$field = JSONText\Fields\JSONText::create('MyJSON');
$field->setValue($this->getFixture('hash_dupes'));
$field->setReturnType('array');
$this->assertEquals([["Kawasaki" => "KR1S250"],["Subaru" => "Impreza"]], $field->query('#>', '{"japanese":"fast"}'));
}*/

/**
* Get the contents of a fixture
Expand Down
37 changes: 37 additions & 0 deletions tests/fixtures/json/hash_duplicated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"cars":{
"american":
[
"buick",
"oldsmobile"
],
"british":
["vauxhall","morris"],
"japanese": {
"fast": {
"Subaru": "Impreza"
},
"slow": {
"Honda": "Civic"
}
}
},
"planes":{
"russian":
[
"antonov",
"mig"
],
"french":"airbus"
},
"bikes":{
"japanese":{
"fast":{
"Kawasaki":"KR1S250"
},
"slow":{
"Honda":"FS150"
}
}
}
}
18 changes: 0 additions & 18 deletions tests/fixtures/json/hash_duplicates.json

This file was deleted.

0 comments on commit 01120a2

Please sign in to comment.