Skip to content

Commit b645e80

Browse files
committed
Improve code coverage, remove old code.
1 parent 4755041 commit b645e80

13 files changed

+336
-486
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ and a user `apache` with password `apache`.
5959

6060
## TODO
6161

62-
A lot.
63-
6462
This is not production ready. Still tons to do on the query builder.
6563
While I hate to reinvent the wheel, I have not found a lightweight
6664
injectable query builder that is not tied to a massive framework.

src/Command.php

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22

33
class Command
44
{
5-
/**
6-
* @var Database the command is associated with.
7-
*/
8-
public $db;
9-
105
/**
116
* @var string
127
*/
@@ -18,6 +13,8 @@ class Command
1813
protected $params = [];
1914

2015
/**
16+
* TODO: Find all of these
17+
*
2118
* @var array
2219
*/
2320
protected $reserved_words = [
@@ -58,13 +55,9 @@ public function bind($key, $value = null)
5855
*/
5956
public function getPreparedQuery(Connection $connection)
6057
{
61-
$quotedSql = $this->quoteIntoSql($connection);
62-
63-
return $quotedSql;
58+
return $this->quoteIntoSql($connection);
6459
}
6560

66-
// TODO: Find all of these...
67-
6861
/**
6962
* TODO: This is exactly what I don't want to do. "Roll my own" SQL handler.
7063
* However, the requirements for this package have led to this point for now.

src/Connection.php

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
<?php namespace DustinGraham\ReactMysql;
22

3-
use React\EventLoop\Timer\TimerInterface;
4-
use React\Promise\Deferred;
5-
63
class Connection extends \mysqli
74
{
85
/**
@@ -11,6 +8,7 @@ class Connection extends \mysqli
118
protected static $nextId = 0;
129

1310
/**
11+
* Used to differentiate mysqli connections without depending on thread_id.
1412
* @var int
1513
*/
1614
public $id;
@@ -37,74 +35,4 @@ public function escape($string)
3735
{
3836
return $this->real_escape_string($string);
3937
}
40-
41-
public function execute(Command $command)
42-
{
43-
if ($this->currentQuery)
44-
{
45-
throw new \Exception('Another query is already pending for this connection.');
46-
}
47-
48-
$this->currentQuery = $command->getPreparedQuery($this);
49-
50-
$status = $this->mysqli->query($this->currentQuery, MYSQLI_ASYNC);
51-
if ($status === false)
52-
{
53-
throw new \Exception($this->mysqli->error);
54-
}
55-
56-
$deferred = new Deferred();
57-
58-
$this->loop->addPeriodicTimer(
59-
$this->pollInterval,
60-
function (TimerInterface $timer) use ($deferred)
61-
{
62-
$reads = $errors = $rejects = [$this->mysqli];
63-
64-
// Non-blocking requires a zero wait time.
65-
$this->mysqli->poll($reads, $errors, $rejects, 0);
66-
67-
$read = in_array($this->mysqli, $reads, true);
68-
$error = in_array($this->mysqli, $errors, true);
69-
$reject = in_array($this->mysqli, $rejects, true);
70-
71-
if ($read)
72-
{
73-
$result = $this->mysqli->reap_async_query();
74-
if ($result === false)
75-
{
76-
$deferred->reject($this->mysqli->error);
77-
}
78-
else
79-
{
80-
// Success!!
81-
$deferred->resolve($result);
82-
}
83-
}
84-
else
85-
{
86-
if ($error)
87-
{
88-
$deferred->reject($this->mysqli->error);
89-
}
90-
else
91-
{
92-
if ($reject)
93-
{
94-
$deferred->reject($this->mysqli->error);
95-
}
96-
}
97-
}
98-
99-
// If poll yielded something for this connection, we're done!
100-
if ($read || $error || $reject)
101-
{
102-
$this->currentQuery = false;
103-
$timer->cancel();
104-
}
105-
}
106-
);
107-
108-
return $deferred->promise();
109-
}
11038
}

src/ConnectionFactory.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@ class ConnectionFactory
77
*/
88
protected static $credentials;
99

10+
/**
11+
* @param array $credentials
12+
*/
1013
public static function init($credentials)
1114
{
1215
self::$credentials = $credentials;
1316
}
1417

18+
/**
19+
* @return Connection
20+
* @throws \Exception
21+
*/
1522
public static function createConnection()
1623
{
1724
if (is_null(self::$credentials))

src/ConnectionPool.php

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<?php namespace DustinGraham\ReactMysql;
22

3-
use React\Promise\Deferred;
4-
53
class ConnectionPool
64
{
75
/**
@@ -59,39 +57,6 @@ public function withConnection($cb)
5957
$cb($connection);
6058
}
6159

62-
/**
63-
* We use a promise in case all connections are busy.
64-
*
65-
* @deprecated Use withConnection
66-
* @return \React\Promise\Promise
67-
*/
68-
public function getConnection()
69-
{
70-
// First check idle connections.
71-
if ($this->available->count() > 0)
72-
{
73-
$connection = $this->available->dequeue();
74-
75-
return \React\Promise\resolve($connection);
76-
}
77-
78-
// Check if we have max connections
79-
if ($this->pool->count() >= $this->maxConnections)
80-
{
81-
$deferred = new Deferred();
82-
$this->waiting->enqueue($deferred);
83-
84-
return $deferred->promise();
85-
}
86-
87-
// Otherwise, create a new connection
88-
$connection = ConnectionFactory::createConnection();
89-
90-
$this->pool->attach($connection);
91-
92-
return \React\Promise\resolve($connection);
93-
}
94-
9560
/**
9661
* Once a connection has finished being used...
9762
* @param Connection $connection
@@ -101,7 +66,11 @@ public function releaseConnection(Connection $connection)
10166
// If we have any promises waiting for the connection, pass it along.
10267
if ($this->waiting->count() > 0)
10368
{
104-
$this->waiting->dequeue()->resolve($connection);
69+
$cb = $this->waiting->dequeue();
70+
71+
$cb($connection);
72+
73+
return;
10574
}
10675

10776
// Otherwise, move it to the idle queue.

src/Database.php

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -35,65 +35,6 @@ public function __construct($credentials = null)
3535
$this->pool = new ConnectionPool();
3636
}
3737

38-
/**
39-
* @param string|null $sql
40-
* @param array $params
41-
* @return Command
42-
*/
43-
public function createCommand($sql = null, $params = [])
44-
{
45-
$command = new Command($this, $sql);
46-
47-
return $command->bind($params);
48-
}
49-
50-
/**
51-
* @deprecated Use statement
52-
* @param Command $command
53-
* @return \React\Promise\Promise
54-
*/
55-
public function executeCommand(Command $command)
56-
{
57-
$deferred = new Deferred();
58-
59-
$this->pool->getConnection()
60-
->then(function (Connection $connection) use ($command, $deferred)
61-
{
62-
// Connection was retrieved from the pool. Execute the command.
63-
$connection->execute($command)
64-
->then(function (\mysqli_result $result) use ($deferred)
65-
{
66-
// We must resolve first so that the result can be closed.
67-
$deferred->resolve($result);
68-
69-
// Doesn't hurt to close it again.
70-
$result->close();
71-
})
72-
->otherwise(function ($reason) use ($deferred)
73-
{
74-
// If the connection execution fails, pass the failure back to the command.
75-
$deferred->reject($reason);
76-
})
77-
->always(function () use ($connection)
78-
{
79-
// Ensure we always return the connection to the pool.
80-
$this->pool->releaseConnection($connection);
81-
});
82-
});
83-
84-
return $deferred->promise();
85-
}
86-
87-
/**
88-
* @deprecated Remove from tests.
89-
*
90-
* @return ConnectionPool
91-
*/
92-
public function getPool()
93-
{
94-
return $this->pool;
95-
}
96-
9738
public function statement($sql, $params = null)
9839
{
9940
$command = new Command($sql, $params);

tests/CommandTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php namespace DustinGraham\ReactMysql\Tests;
2+
3+
use DustinGraham\ReactMysql\Command;
4+
use DustinGraham\ReactMysql\ConnectionFactory;
5+
6+
class CommandTest extends TestCase
7+
{
8+
public function testComplexBind()
9+
{
10+
$command = new Command("
11+
INSERT INTO simple_table (
12+
`id`,
13+
`name`,
14+
`value`,
15+
`created_at`
16+
) VALUES (
17+
:id,
18+
:name,
19+
:num,
20+
:datetime
21+
);
22+
", [
23+
':id' => null,
24+
':name' => 'John\'s Name',
25+
':num' => 7,
26+
':datetime' => 'NOW()',
27+
]);
28+
29+
$connection = ConnectionFactory::createConnection();
30+
31+
$query = $command->getPreparedQuery($connection);
32+
33+
$this->assertStringEqualsIgnoreSpacing(
34+
"INSERT INTO simple_table ( `id`, `name`, `value`, `created_at` ) VALUES ( NULL, 'John\'s Name', 7, NOW() );",
35+
$query
36+
);
37+
}
38+
39+
public function testAssertStrings()
40+
{
41+
$this->assertStringEqualsIgnoreSpacing('yes no ', 'yes no');
42+
}
43+
44+
public function testSingleBind()
45+
{
46+
$command = new Command("
47+
SELECT * FROM simple_table WHERE id = :id
48+
");
49+
50+
$command->bind(':id', 1);
51+
52+
$connection = ConnectionFactory::createConnection();
53+
54+
$command->getPreparedQuery($connection);
55+
}
56+
57+
public function testParameterReplacing()
58+
{
59+
$command = new Command;
60+
$command->sql = 'SELECT * FROM simple_table WHERE id = :id';
61+
$command->bind(':id', 2);
62+
63+
$connection = ConnectionFactory::createConnection();
64+
65+
$query = $command->getPreparedQuery($connection);
66+
67+
$this->assertStringEqualsIgnoreSpacing(
68+
'SELECT * FROM simple_table WHERE id = 2',
69+
$query
70+
);
71+
}
72+
73+
/**
74+
* TODO: This test is still todo.
75+
*
76+
* @throws \Exception
77+
*/
78+
public function testParamCounting()
79+
{
80+
// Note: Used a comma rather than => so it was failing.
81+
// param count would detect this sooner.
82+
83+
// Intentionally bad parameters to ensure check.
84+
$badParams = [':test', 1,];
85+
// The programmer's intent was:
86+
// $goodParams = [ ':test' => 1, ]
87+
88+
$command = new Command(
89+
'SELECT * FROM simple_table WHERE id = :test',
90+
$badParams
91+
);
92+
93+
$connection = ConnectionFactory::createConnection();
94+
95+
$query = $command->getPreparedQuery($connection);
96+
97+
// TODO: Here is the bad result, :test should have been 1
98+
// TODO: GetPreparedQuery should error on param mismatch
99+
$this->assertStringEqualsIgnoreSpacing(
100+
'SELECT * FROM simple_table WHERE id = :test',
101+
$query
102+
);
103+
}
104+
}

0 commit comments

Comments
 (0)