Skip to content

Commit 88307b4

Browse files
committed
PHPC-381: Server::executeQuery/Command() should take a read preference
1 parent b8a8f89 commit 88307b4

File tree

5 files changed

+204
-6
lines changed

5 files changed

+204
-6
lines changed

src/MongoDB/Server.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,48 +58,50 @@ PHP_METHOD(Server, __construct)
5858
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "Accessing private constructor");
5959
}
6060
/* }}} */
61-
/* {{{ proto MongoDB\Driver\Cursor Server::executeCommand(string $db, MongoDB\Driver\Command $command)
61+
/* {{{ proto MongoDB\Driver\Cursor Server::executeCommand(string $db, MongoDB\Driver\Command $command[, MongoDB\Driver\ReadPreference $readPreference = null]))
6262
Executes a command on this server */
6363
PHP_METHOD(Server, executeCommand)
6464
{
6565
php_phongo_server_t *intern;
6666
char *db;
6767
int db_len;
6868
zval *command;
69+
zval *readPreference = NULL;
6970
php_phongo_command_t *cmd;
7071
(void)return_value_ptr;
7172

7273

7374
intern = (php_phongo_server_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
7475

75-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &db, &db_len, &command, php_phongo_command_ce) == FAILURE) {
76+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|O!", &db, &db_len, &command, php_phongo_command_ce, &readPreference, php_phongo_readpreference_ce) == FAILURE) {
7677
return;
7778
}
7879

7980

8081
cmd = (php_phongo_command_t *)zend_object_store_get_object(command TSRMLS_CC);
81-
phongo_execute_command(intern->client, db, cmd->bson, NULL, intern->server_id, return_value, return_value_used TSRMLS_CC);
82+
phongo_execute_command(intern->client, db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC);
8283
}
8384
/* }}} */
84-
/* {{{ proto MongoDB\Driver\Cursor Server::executeQuery(string $namespace, MongoDB\Driver\Query $zquery)
85+
/* {{{ proto MongoDB\Driver\Cursor Server::executeQuery(string $namespace, MongoDB\Driver\Query $zquery[, MongoDB\Driver\ReadPreference $readPreference = null]))
8586
Executes a Query */
8687
PHP_METHOD(Server, executeQuery)
8788
{
8889
php_phongo_server_t *intern;
8990
char *namespace;
9091
int namespace_len;
9192
zval *zquery;
93+
zval *readPreference = NULL;
9294
(void)return_value_ptr;
9395

9496

9597
intern = (php_phongo_server_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
9698

97-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &namespace, &namespace_len, &zquery, php_phongo_query_ce) == FAILURE) {
99+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|O!", &namespace, &namespace_len, &zquery, php_phongo_query_ce, &readPreference, php_phongo_readpreference_ce) == FAILURE) {
98100
return;
99101
}
100102

101103

102-
phongo_execute_query(intern->client, namespace, phongo_query_from_zval(zquery TSRMLS_CC), NULL, intern->server_id, return_value, return_value_used TSRMLS_CC);
104+
phongo_execute_query(intern->client, namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC);
103105
}
104106
/* }}} */
105107
/* {{{ proto MongoDB\Driver\WriteResult Server::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, MongoDB\Driver\WriteConcern $writeConcern = null])
@@ -391,11 +393,13 @@ PHP_METHOD(Server, isPassive)
391393
ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeCommand, 0, 0, 2)
392394
ZEND_ARG_INFO(0, db)
393395
ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
396+
ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 1)
394397
ZEND_END_ARG_INFO();
395398

396399
ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeQuery, 0, 0, 2)
397400
ZEND_ARG_INFO(0, namespace)
398401
ZEND_ARG_OBJ_INFO(0, zquery, MongoDB\\Driver\\Query, 0)
402+
ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 1)
399403
ZEND_END_ARG_INFO();
400404

401405
ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeBulkWrite, 0, 0, 2)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
--TEST--
2+
MongoDB\Driver\Server::executeCommand() takes a read preference
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("REPLICASET"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(REPLICASET);
10+
11+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
12+
$secondary = $manager->selectServer($rp);
13+
14+
$command = new MongoDB\Driver\Command(array('profile' => 2));
15+
$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
16+
$result = current($cursor->toArray());
17+
18+
if (empty($result->ok)) {
19+
exit("Could not set profile level\n");
20+
}
21+
22+
$command = new MongoDB\Driver\Command(array(
23+
'aggregate' => COLLECTION_NAME,
24+
'pipeline' => array(array('$match' => array('x' => 1))),
25+
));
26+
$secondary->executeCommand(DATABASE_NAME, $command, $rp);
27+
28+
$query = new MongoDB\Driver\Query(
29+
array(
30+
'op' => 'command',
31+
'ns' => DATABASE_NAME . '.$cmd',
32+
),
33+
array(
34+
'sort' => array('ts' => -1),
35+
'limit' => 1,
36+
)
37+
);
38+
$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
39+
$profileEntry = current($cursor->toArray());
40+
41+
var_dump($profileEntry->command);
42+
43+
$command = new MongoDB\Driver\Command(array('profile' => 0));
44+
$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
45+
$result = current($cursor->toArray());
46+
47+
if (empty($result->ok)) {
48+
exit("Could not set profile level\n");
49+
}
50+
51+
?>
52+
===DONE===
53+
<?php exit(0); ?>
54+
--EXPECTF--
55+
object(stdClass)#%d (%d) {
56+
["aggregate"]=>
57+
string(32) "server_server_executeCommand_002"
58+
["pipeline"]=>
59+
array(1) {
60+
[0]=>
61+
object(stdClass)#%d (%d) {
62+
["$match"]=>
63+
object(stdClass)#%d (%d) {
64+
["x"]=>
65+
int(1)
66+
}
67+
}
68+
}
69+
["$readPreference"]=>
70+
object(stdClass)#%d (%d) {
71+
["mode"]=>
72+
string(9) "secondary"
73+
["tags"]=>
74+
array(0) {
75+
}
76+
}
77+
}
78+
===DONE===
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
MongoDB\Driver\Server::executeCommand() with conflicting read preference for secondary
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("REPLICASET"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(REPLICASET);
10+
11+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
12+
$secondary = $manager->selectServer($rp);
13+
14+
echo throws(function() use ($secondary) {
15+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY);
16+
$secondary->executeCommand(NS, new MongoDB\Driver\Command(array('ping' => 1)), $rp);
17+
}, "MongoDB\Driver\Exception\RuntimeException"), "\n";
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECT--
23+
OK: Got MongoDB\Driver\Exception\RuntimeException
24+
not master and slaveOk=false
25+
===DONE===
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
--TEST--
2+
MongoDB\Driver\Server::executeQuery() takes a read preference
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("REPLICASET"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(REPLICASET);
10+
11+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
12+
$secondary = $manager->selectServer($rp);
13+
14+
$command = new MongoDB\Driver\Command(array('profile' => 2));
15+
$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
16+
$result = current($cursor->toArray());
17+
18+
if (empty($result->ok)) {
19+
exit("Could not set profile level\n");
20+
}
21+
22+
$secondary->executeQuery(NS, new MongoDB\Driver\Query(array("x" => 1)), $rp);
23+
24+
$query = new MongoDB\Driver\Query(
25+
array(
26+
'op' => 'query',
27+
'ns' => NS,
28+
),
29+
array(
30+
'sort' => array('ts' => -1),
31+
'limit' => 1,
32+
)
33+
);
34+
$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
35+
$profileEntry = current($cursor->toArray());
36+
37+
var_dump($profileEntry->query);
38+
39+
$command = new MongoDB\Driver\Command(array('profile' => 0));
40+
$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
41+
$result = current($cursor->toArray());
42+
43+
if (empty($result->ok)) {
44+
exit("Could not set profile level\n");
45+
}
46+
47+
?>
48+
===DONE===
49+
<?php exit(0); ?>
50+
--EXPECTF--
51+
object(stdClass)#%d (%d) {
52+
["$query"]=>
53+
object(stdClass)#%d (%d) {
54+
["x"]=>
55+
int(1)
56+
}
57+
["$readPreference"]=>
58+
object(stdClass)#%d (%d) {
59+
["mode"]=>
60+
string(9) "secondary"
61+
["tags"]=>
62+
array(0) {
63+
}
64+
}
65+
}
66+
===DONE===
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
MongoDB\Driver\Server::executeQuery() with conflicting read preference for secondary
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("REPLICASET"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(REPLICASET);
10+
11+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
12+
$secondary = $manager->selectServer($rp);
13+
14+
echo throws(function() use ($secondary) {
15+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY);
16+
$secondary->executeQuery(NS, new MongoDB\Driver\Query(array("x" => 1)), $rp);
17+
}, "MongoDB\Driver\Exception\RuntimeException"), "\n";
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECT--
23+
OK: Got MongoDB\Driver\Exception\RuntimeException
24+
not master and slaveOk=false
25+
===DONE===

0 commit comments

Comments
 (0)