Skip to content

Commit dc42047

Browse files
committed
Support orWhere #6
1 parent a665da6 commit dc42047

File tree

3 files changed

+153
-47
lines changed

3 files changed

+153
-47
lines changed

src/Kitar/Dynamodb/Query/Builder.php

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
namespace Kitar\Dynamodb\Query;
44

55
use Closure;
6+
use BadMethodCallException;
67
use Kitar\Dynamodb\Connection;
78
use Kitar\Dynamodb\Query\Grammar;
89
use Kitar\Dynamodb\Query\Processor;
910
use Kitar\Dynamodb\Query\ExpressionAttributes;
11+
use Illuminate\Support\Str;
1012
use Illuminate\Database\Query\Expression;
1113
use Illuminate\Database\Query\Builder as BaseBuilder;
1214

@@ -56,19 +58,25 @@ class Builder extends BaseBuilder
5658
public $expression_attributes;
5759

5860
/**
59-
* Query for building FilterExpression.
61+
* Available where methods which will pass to dedicated queries.
62+
* @var array
63+
*/
64+
public $available_wheres;
65+
66+
/**
67+
* Dedicated query for building FilterExpression.
6068
* @var Kitar\Dynamodb\Query\Builder
6169
*/
6270
public $filter_query;
6371

6472
/**
65-
* Query for building ConditionExpression.
73+
* Dedicated query for building ConditionExpression.
6674
* @var Kitar\Dynamodb\Query\Builder
6775
*/
6876
public $condition_query;
6977

7078
/**
71-
* Query for building KeyConditionExpression.
79+
* Dedicated query for building KeyConditionExpression.
7280
* @var Kitar\Dynamodb\Query\Builder
7381
*/
7482
public $key_condition_query;
@@ -87,9 +95,7 @@ public function __construct(Connection $connection, Grammar $grammar, Processor
8795
$this->expression_attributes = $expression_attributes ?? new ExpressionAttributes;
8896

8997
if (! $is_nested_query) {
90-
$this->filter_query = $this->newQuery()->whereAs('FilterExpression');
91-
$this->condition_query = $this->newQuery()->whereAs('ConditionExpression');
92-
$this->key_condition_query = $this->newQuery()->whereAs('KeyConditionExpression');
98+
$this->initializeDedicatedQueries();
9399
}
94100
}
95101

@@ -141,39 +147,6 @@ public function dryRun($active = true)
141147
return $this;
142148
}
143149

144-
/**
145-
* where for FilterExpression.
146-
* @return $this
147-
*/
148-
public function filter($column, $operator = null, $value = null, $boolean = 'and')
149-
{
150-
$this->filter_query = $this->filter_query->where($column, $operator, $value, $boolean);
151-
152-
return $this;
153-
}
154-
155-
/**
156-
* where for ConditionExpression.
157-
* @return $this
158-
*/
159-
public function condition($column, $operator = null, $value = null, $boolean = 'and')
160-
{
161-
$this->condition_query = $this->condition_query->where($column, $operator, $value, $boolean);
162-
163-
return $this;
164-
}
165-
166-
/**
167-
* where for KeyConditionExpression.
168-
* @return $this
169-
*/
170-
public function keyCondition($column, $operator = null, $value = null, $boolean = 'and')
171-
{
172-
$this->key_condition_query = $this->key_condition_query->where($column, $operator, $value, $boolean);
173-
174-
return $this;
175-
}
176-
177150
/**
178151
* Set key name of wheres. eg. FilterExpression
179152
* @param string $condition_key_name
@@ -241,6 +214,51 @@ public function scan()
241214
return $this->process('scan', 'processMultipleItems');
242215
}
243216

217+
/**
218+
* Make individual Builder instance for condition types. (Filter, Condition and KeyCondition)
219+
* @return void
220+
*/
221+
public function initializeDedicatedQueries()
222+
{
223+
$this->filter_query = $this->newQuery()->whereAs('FilterExpression');
224+
$this->condition_query = $this->newQuery()->whereAs('ConditionExpression');
225+
$this->key_condition_query = $this->newQuery()->whereAs('KeyConditionExpression');
226+
227+
// Make method map.
228+
// Array of: 'incomingMethodName' => [ 'target_builder_instance_name', 'targetMethodName' ]
229+
foreach (['filter', 'condition', 'key_condition'] as $query_type) {
230+
foreach (['', 'or'] as $boolean) {
231+
foreach ([''] as $where_type) {
232+
$target_query = $query_type . '_query';
233+
$source_method = Str::camel(implode('_', [$boolean, $query_type, $where_type]));
234+
$target_method = Str::camel(implode('_', [$boolean, 'where', $where_type]));
235+
236+
$this->available_wheres[$source_method] = [$target_query, $target_method];
237+
}
238+
}
239+
}
240+
}
241+
242+
/**
243+
* Perform where methods within dedicated queries.
244+
* @param string $method
245+
* @param array $parameters
246+
* @return $this
247+
*/
248+
public function __call($method, $parameters)
249+
{
250+
if (isset($this->available_wheres[$method])) {
251+
$target_query = $this->available_wheres[$method][0];
252+
$target_method = $this->available_wheres[$method][1];
253+
254+
$this->$target_query = call_user_func_array([$this->$target_query, $target_method], $parameters);
255+
256+
return $this;
257+
}
258+
259+
throw new BadMethodCallException('Call to undefined method ' . static::class . "::{$method}()");
260+
}
261+
244262
/**
245263
* @inheritdoc
246264
*/
@@ -249,7 +267,7 @@ public function where($column, $operator = null, $value = null, $boolean = 'and'
249267
// Convert column and value to ExpressionAttributes.
250268
if (! $column instanceof Closure) {
251269
$column = $this->expression_attributes->addName($column);
252-
if (! empty($value)) {
270+
if ($value !== null) {
253271
$value = $this->expression_attributes->addValue($value);
254272
}
255273
}

src/Kitar/Dynamodb/Query/ExpressionAttributes.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ public function __construct()
2222

2323
public function addName($name)
2424
{
25-
if (! in_array($name, $this->names)) {
25+
if (! in_array($name, $this->names, true)) {
2626
$this->names[$this->makeNameKey()] = $name;
2727
}
2828

29-
return array_search($name, $this->names);
29+
return array_search($name, $this->names, true);
3030
}
3131

3232
public function addValue($value)
3333
{
34-
if (! in_array($value, $this->values)) {
34+
if (! in_array($value, $this->values, true)) {
3535
$this->values[$this->makeValueKey()] = $value;
3636
}
3737

38-
return array_search($value, $this->values);
38+
return array_search($value, $this->values, true);
3939
}
4040

4141
public function makeNameKey()

tests/Query/BuilderTest.php

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function it_can_set_consistent_read()
6262
}
6363

6464
/** @test */
65-
public function it_can_compile_wheres_to_filter_expression()
65+
public function it_can_process_filter()
6666
{
6767
$params = [
6868
'TableName' => 'test',
@@ -84,7 +84,7 @@ public function it_can_compile_wheres_to_filter_expression()
8484
}
8585

8686
/** @test */
87-
public function it_can_compile_wheres_to_condition_expression()
87+
public function it_can_process_condition()
8888
{
8989
$params = [
9090
'TableName' => 'test',
@@ -106,7 +106,7 @@ public function it_can_compile_wheres_to_condition_expression()
106106
}
107107

108108
/** @test */
109-
public function it_can_compile_wheres_to_key_condition_expression()
109+
public function it_can_process_key_condition()
110110
{
111111
$params = [
112112
'TableName' => 'test',
@@ -127,6 +127,94 @@ public function it_can_compile_wheres_to_key_condition_expression()
127127
$this->assertEquals($params, $query['params']);
128128
}
129129

130+
/** @test */
131+
public function it_can_process_key_condition_and_filter_at_the_same_time()
132+
{
133+
$params = [
134+
'TableName' => 'test',
135+
'KeyConditionExpression' => '#1 = :1 and #2 = :2',
136+
'FilterExpression' => '#3 > :3',
137+
'ExpressionAttributeNames' => [
138+
'#1' => 'ForumName',
139+
'#2' => 'Subject',
140+
'#3' => 'Views'
141+
],
142+
'ExpressionAttributeValues' => [
143+
':1' => [
144+
'S' => 'Amazon DynamoDB'
145+
],
146+
':2' => [
147+
'S' => 'DynamoDB Thread 1'
148+
],
149+
':3' => [
150+
'N' => '3'
151+
]
152+
]
153+
];
154+
155+
$query = $this->builder
156+
->keyCondition('ForumName', '=', 'Amazon DynamoDB')
157+
->keyCondition('Subject', '=', 'DynamoDB Thread 1')
158+
->filter('Views', '>', 3)
159+
->query();
160+
161+
$this->assertEquals($params, $query['params']);
162+
}
163+
164+
/** @test */
165+
public function it_can_process_or_filter()
166+
{
167+
$params = [
168+
'TableName' => 'test',
169+
'FilterExpression' => '#1 > :1 or #1 = :2',
170+
'ExpressionAttributeNames' => [
171+
'#1' => 'Views'
172+
],
173+
'ExpressionAttributeValues' => [
174+
':1' => [
175+
'N' => '3'
176+
],
177+
':2' => [
178+
'N' => '0'
179+
]
180+
]
181+
];
182+
183+
$query = $this->builder
184+
->filter('Views', '>', 3)
185+
->orFilter('Views', '=', 0)
186+
->scan();
187+
188+
$this->assertEquals($params, $query['params']);
189+
}
190+
191+
/** @test */
192+
public function it_can_process_or_condition()
193+
{
194+
$params = [
195+
'TableName' => 'test',
196+
'ConditionExpression' => '#1 > :1 or #1 = :2',
197+
'ExpressionAttributeNames' => [
198+
'#1' => 'Views'
199+
],
200+
'ExpressionAttributeValues' => [
201+
':1' => [
202+
'N' => '3'
203+
],
204+
':2' => [
205+
'N' => '0'
206+
]
207+
]
208+
];
209+
210+
$query = $this->builder
211+
->condition('Views', '>', 3)
212+
->orCondition('Views', '=', 0)
213+
->scan();
214+
215+
$this->assertEquals($params, $query['params']);
216+
}
217+
130218
/** @test */
131219
public function it_can_process_get_item()
132220
{

0 commit comments

Comments
 (0)