Skip to content

Commit

Permalink
Merge pull request #8 from nulpunkt/named-parameters
Browse files Browse the repository at this point in the history
Named parameters
  • Loading branch information
nulpunkt authored Nov 2, 2018
2 parents 263f8d3 + f76fc58 commit ec94a6e
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 38 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ $r->getAllRows();
## Inserting a row
A database without rows is not of much use, lets insert some data:
```sql
-- name: insertRow
insert into test_table (something) values (?)
-- name: insertRow(thing)
insert into test_table (something) values (:thing)

```
```php
Expand All @@ -53,22 +53,22 @@ the query associated with it. We'll see how to make mappers further down.
## Updating a row
Maybe we need to fix some exsisting data
```sql
-- name: updateRow
update test_table set something = ? where id = ?
-- name: updateRow(id, thing)
update test_table set something = :thing where id = :id

```
```php
// returns the number of rows touched by the update
$r->updateRow('fixed thing', 3);
$r->updateRow(3, 'fixed thing');
```

## Fetching a single row
yesql-php support different modlines, lets say we know we only need to get one
row:

```sql
-- name: getById oneOrMany: one
select * from test_table where id = ?;
-- name: getById(id) oneOrMany: one
select * from test_table where id = :id;
```
```php
// Fetches one row with id 3
Expand All @@ -80,8 +80,8 @@ Maybe we want to return a modified version of the row. By specifying a
rowFunc, we can have a function called, on every row returned:

```sql
-- name: getMappedById oneOrMany: one rowFunc: MyObject::mapRow
select * from test_table where id = ?
-- name: getMappedById(id) oneOrMany: one rowFunc: MyObject::mapRow
select * from test_table where id = :id
```
```php
class MyObject {
Expand All @@ -97,8 +97,8 @@ $r->getMappedById(3);
Sometimes an object is want you want, rowClass got your back:

```sql
-- name: getObjectById oneOrMany: one rowClass: MyObject
select * from test_table where id = ?
-- name: getObjectById(id) oneOrMany: one rowClass: MyObject
select * from test_table where id = :id
```
```php
class MyObject {
Expand All @@ -107,9 +107,9 @@ class MyObject {
$r->getObjectById(3);
```

## Mapping data on the way in / Using named parameters on insert / update
## Mapping data on the way in
We may need to map our domain objects to be able to insert them into the
database. This allows us to name our parameters as well:
database.
```sql
-- name: insertObject inFunc: MyObject::toRow
insert into test_table (id, something) values (:id, :something)
Expand Down
13 changes: 9 additions & 4 deletions src/Nulpunkt/Yesql/Statement/Collector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@

class Collector
{
private $methodName;
private $method;
private $modline;
private $sql;

public function __construct($methodName, $modline)
public function __construct($method, $modline)
{
$this->methodName = $methodName;
$this->method = $method;
$this->modline = $modline;
}

public function getMethodName()
{
return $this->methodName;
return $this->method->getName();
}

public function getArgNames()
{
return $this->method->getArgNames();
}

public function getSql()
Expand Down
13 changes: 7 additions & 6 deletions src/Nulpunkt/Yesql/Statement/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public function createStatements($sqlFile)
$collected = [];
foreach (file($sqlFile) as $line) {
$isComment = strpos($line, '--') === 0;
if ($isComment && ($name = $this->getMethodName($line))) {
$collected[] = $currentCollector = new Collector($name, $line);
if ($isComment && ($method = $this->getMethod($line))) {
$collected[] = $currentCollector = new Collector($method, $line);
} elseif (!$isComment) {
$currentCollector->appendSql($line);
}
Expand All @@ -22,17 +22,18 @@ public function createStatements($sqlFile)
foreach ($collected as $c) {
$statements[$c->getMethodName()] = new MapInput(
$this->createStatement($c->getSql(), $c->getModline()),
$c->getModline()
$c->getModline(),
$c->getArgNames()
);
}

return $statements;
}

public function getMethodName($line)
public function getMethod($line)
{
preg_match("/\bname:\s*(\S+)/", $line, $m);
return isset($m[1]) ? $m[1] : null;
preg_match("/\bname:\s*([^\s(]+)\s*(\(([\w,\s]+)\))?/", $line, $m);
return isset($m[1]) ? new Method($m[1], isset($m[3]) ? $m[3] : '') : null;
}

private function createStatement($collectedSql, $modline)
Expand Down
7 changes: 6 additions & 1 deletion src/Nulpunkt/Yesql/Statement/MapInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ class MapInput implements Statement
private $statement;
private $modline;

public function __construct($statement, $modline)
public function __construct($statement, $modline, $argNames)
{
$this->statement = $statement;
$this->modline = $modline;
$this->argNames = $argNames;
$this->inFunc = $this->getInFunc();
}

Expand All @@ -19,6 +20,10 @@ public function execute($db, $args)
if ($this->inFunc) {
$args = call_user_func_array($this->inFunc, $args);
}
if (count($this->argNames) > 0) {
$args = array_combine($this->argNames, $args);

}
return $this->statement->execute($db, $args);
}

Expand Down
25 changes: 25 additions & 0 deletions src/Nulpunkt/Yesql/Statement/Method.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Nulpunkt\Yesql\Statement;

class Method
{
private $name;
private $argNames;

public function __construct($name, $argNames)
{
$this->name = $name;
$this->argNames = array_filter(array_map('trim', explode(',', $argNames)));
}

public function getName()
{
return $this->name;
}

public function getArgNames()
{
return $this->argNames;
}
}
6 changes: 1 addition & 5 deletions src/Nulpunkt/Yesql/Statement/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ public function execute($db, $args)
$this->stmt = $db->prepare($this->sql);
}

if (isset($args)) {
$this->stmt->execute($args);
} else {
$this->stmt->execute();
}
$this->stmt->execute($args);

if ($this->rowClass) {
$this->stmt->setFetchMode(\PDO::FETCH_CLASS, $this->rowClass);
Expand Down
6 changes: 1 addition & 5 deletions src/Nulpunkt/Yesql/Statement/Update.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ public function execute($db, $args)
$this->stmt = $db->prepare($this->sql);
}

if (isset($args)) {
$this->stmt->execute($args);
} else {
$this->stmt->execute();
}
$this->stmt->execute($args);

return $this->stmt->rowCount();
}
Expand Down
22 changes: 22 additions & 0 deletions test/Nulpunkt/Yesql/RepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ public function testWeCanGetOneRow()
$this->assertEquals(['id' => 1, 'something' => 'a thing'], $this->repo->getById(1));
}

public function testWeCanGetOneRowWithNamedParam()
{
$this->assertEquals(['id' => 1, 'something' => 'a thing'], $this->repo->getByIdNamed(1));
}

public function testWeCanGetARowThatDoesNotExsist()
{
$this->assertNull($this->repo->getById(11));
Expand Down Expand Up @@ -82,6 +87,23 @@ public function testWeCanUpdate()
$this->assertDataSetsEqual($expectedData, $dataSet);
}

public function testWeCanUpdateWithNamedParams()
{
$rowsAffected = $this->repo->updateRowNamed(2, 'other thing updated');

$this->assertSame(1, $rowsAffected);

$dataSet = $this->createQueryDataset(
['t' => "SELECT * FROM test_table where id = 2"]
);

$expectedData = $this->createArrayDataSet(
['t' => [['id' => 2, 'something' => 'other thing updated']]]
);

$this->assertDataSetsEqual($expectedData, $dataSet);
}

public function testWeCanUpdateWithObject()
{
$o = new \TestHelper\TestObject;
Expand Down
16 changes: 13 additions & 3 deletions test/Nulpunkt/Yesql/Statement/MapInputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ public function testWeCanExecuteAStatement()
$s->expects($this->once())->method('execute')
->with('db', ['id'=> 3]);

$m = new MapInput($s, '');
$m = new MapInput($s, '', []);
$m->execute('db', ['id' => 3]);
}

public function testWeCanExecuteAStatementWithNamedParams()
{
$s = $this->getMock('Nulpunkt\Yesql\Statement\Statement');
$s->expects($this->once())->method('execute')
->with('db', ['id'=> 3]);

$m = new MapInput($s, '', ['id']);
$m->execute('db', [3]);
}

public function testWeCanExecuteAStatementWithInFunc()
{
$o = new \TestHelper\TestObject;
Expand All @@ -24,7 +34,7 @@ public function testWeCanExecuteAStatementWithInFunc()
$s->expects($this->once())->method('execute')
->with('db', ['id'=> 3, 'something' => 'from object']);

$m = new MapInput($s, $modline);
$m = new MapInput($s, $modline, []);
$m->execute('db', [$o]);
}

Expand All @@ -34,6 +44,6 @@ public function testWeCanExecuteAStatementWithInFunc()
public function testWeComplainIfInFuncIsNotCallable()
{
$modline = 'inFunc: nope.exe';
new MapInput(null, $modline);
new MapInput(null, $modline, []);
}
}
7 changes: 7 additions & 0 deletions test/Nulpunkt/Yesql/test.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
-- This will make getById a method which fetch a test row from the database
select * from test_table where id = ?

-- name: getByIdNamed(id) oneOrMany: one
select * from test_table where id = :id

-- name: getObjectByIdManually oneOrMany: one rowFunc: TestHelper\TestObject::fromRow
select * from test_table where id = ?

Expand All @@ -24,6 +27,10 @@ insert into test_table (id, something) values (:id, :something)
update test_table set something = ?
where id = ?

-- name: updateRowNamed(id, something)
update test_table set something = :something
where id = :id

-- name: updateObject inFunc: TestHelper\TestObject::toRow
update test_table set something = :something
where id = :id
Expand Down
2 changes: 1 addition & 1 deletion test/phpunit.bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
error_reporting(E_ALL | E_STRICT);
error_reporting(-1);

ini_set("memory_limit", "1024M"); // nothing to see here

Expand Down

0 comments on commit ec94a6e

Please sign in to comment.