@@ -1504,10 +1504,26 @@ mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS
1504
1504
uri = mongoc_uri_new (uri_string );
1505
1505
MONGOC_DEBUG ("Connection string: '%s'" , uri_string );
1506
1506
1507
+ if (!uri ) {
1508
+ return NULL ;
1509
+ }
1510
+
1507
1511
if (options && bson_iter_init (& iter , options )) {
1508
1512
while (bson_iter_next (& iter )) {
1509
1513
const char * key = bson_iter_key (& iter );
1510
1514
1515
+ /* Skip read preference and write concern options, as those must be
1516
+ * processed after the mongoc_client_t is constructed. */
1517
+ if (!strcasecmp (key , "journal" ) ||
1518
+ !strcasecmp (key , "readpreference" ) ||
1519
+ !strcasecmp (key , "readpreferencetags" ) ||
1520
+ !strcasecmp (key , "safe" ) ||
1521
+ !strcasecmp (key , "slaveok" ) ||
1522
+ !strcasecmp (key , "w" ) ||
1523
+ !strcasecmp (key , "wtimeoutms" )) {
1524
+ continue ;
1525
+ }
1526
+
1511
1527
if (mongoc_uri_option_is_bool (key )) {
1512
1528
mongoc_uri_set_option_as_bool (uri , key , bson_iter_as_bool (& iter ));
1513
1529
}
@@ -1591,6 +1607,199 @@ void php_phongo_populate_default_ssl_ctx(php_stream_context *ctx, zval *driverOp
1591
1607
#undef SET_STRING_CTX
1592
1608
} /* }}} */
1593
1609
1610
+ bool php_phongo_apply_rp_options_to_client (mongoc_client_t * client , bson_t * options TSRMLS_DC ) /* {{{ */
1611
+ {
1612
+ bson_iter_t iter ;
1613
+ mongoc_read_prefs_t * new_rp ;
1614
+ const mongoc_read_prefs_t * old_rp ;
1615
+
1616
+ if (!(old_rp = mongoc_client_get_read_prefs (client ))) {
1617
+ phongo_throw_exception (PHONGO_ERROR_MONGOC_FAILED TSRMLS_CC , "Client does not have a read preference" );
1618
+
1619
+ return false;
1620
+ }
1621
+
1622
+ /* Return early if there are no options to apply */
1623
+ if (bson_empty0 (options )) {
1624
+ return true;
1625
+ }
1626
+
1627
+ if (!bson_iter_init_find_case (& iter , options , "slaveok" ) &&
1628
+ !bson_iter_init_find_case (& iter , options , "readpreference" ) &&
1629
+ !bson_iter_init_find_case (& iter , options , "readpreferencetags" )) {
1630
+ return true;
1631
+ }
1632
+
1633
+ new_rp = mongoc_read_prefs_copy (old_rp );
1634
+
1635
+ if (bson_iter_init_find_case (& iter , options , "slaveok" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1636
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY_PREFERRED );
1637
+ }
1638
+
1639
+ if (bson_iter_init_find_case (& iter , options , "readpreference" ) && BSON_ITER_HOLDS_UTF8 (& iter )) {
1640
+ const char * str = bson_iter_utf8 (& iter , NULL );
1641
+
1642
+ if (0 == strcasecmp ("primary" , str )) {
1643
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_PRIMARY );
1644
+ } else if (0 == strcasecmp ("primarypreferred" , str )) {
1645
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_PRIMARY_PREFERRED );
1646
+ } else if (0 == strcasecmp ("secondary" , str )) {
1647
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY );
1648
+ } else if (0 == strcasecmp ("secondarypreferred" , str )) {
1649
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY_PREFERRED );
1650
+ } else if (0 == strcasecmp ("nearest" , str )) {
1651
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_NEAREST );
1652
+ } else {
1653
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Unsupported readPreference value: '%s'" , str );
1654
+ mongoc_read_prefs_destroy (new_rp );
1655
+
1656
+ return false;
1657
+ }
1658
+ }
1659
+
1660
+ if (bson_iter_init_find_case (& iter , options , "readpreferencetags" ) && BSON_ITER_HOLDS_ARRAY (& iter )) {
1661
+ bson_t tags ;
1662
+ uint32_t len ;
1663
+ const uint8_t * data ;
1664
+
1665
+ bson_iter_array (& iter , & len , & data );
1666
+
1667
+ if (bson_init_static (& tags , data , len )) {
1668
+ mongoc_read_prefs_set_tags (new_rp , & tags );
1669
+ }
1670
+ }
1671
+
1672
+ if (mongoc_read_prefs_get_mode (new_rp ) == MONGOC_READ_PRIMARY &&
1673
+ !bson_empty (mongoc_read_prefs_get_tags (new_rp ))) {
1674
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Primary read preference mode conflicts with tags" );
1675
+ mongoc_read_prefs_destroy (new_rp );
1676
+
1677
+ return false;
1678
+ }
1679
+
1680
+ /* This may be redundant in light of the last check (primary with tags), but
1681
+ * we'll check anyway in case additional validation is implemented. */
1682
+ if (!mongoc_read_prefs_is_valid (new_rp )) {
1683
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Read preference is not valid" );
1684
+ mongoc_read_prefs_destroy (new_rp );
1685
+
1686
+ return false;
1687
+ }
1688
+
1689
+ mongoc_client_set_read_prefs (client , new_rp );
1690
+ mongoc_read_prefs_destroy (new_rp );
1691
+
1692
+ return true;
1693
+ } /* }}} */
1694
+
1695
+ bool php_phongo_apply_wc_options_to_client (mongoc_client_t * client , bson_t * options TSRMLS_DC ) /* {{{ */
1696
+ {
1697
+ bson_iter_t iter ;
1698
+ int32_t wtimeoutms ;
1699
+ mongoc_write_concern_t * new_wc ;
1700
+ const mongoc_write_concern_t * old_wc ;
1701
+
1702
+ if (!(old_wc = mongoc_client_get_write_concern (client ))) {
1703
+ phongo_throw_exception (PHONGO_ERROR_MONGOC_FAILED TSRMLS_CC , "Client does not have a write concern" );
1704
+
1705
+ return false;
1706
+ }
1707
+
1708
+ /* Return early if there are no options to apply */
1709
+ if (bson_empty0 (options )) {
1710
+ return true;
1711
+ }
1712
+
1713
+ if (!bson_iter_init_find_case (& iter , options , "journal" ) &&
1714
+ !bson_iter_init_find_case (& iter , options , "safe" ) &&
1715
+ !bson_iter_init_find_case (& iter , options , "w" ) &&
1716
+ !bson_iter_init_find_case (& iter , options , "wtimeoutms" )) {
1717
+ return true;
1718
+ }
1719
+
1720
+ wtimeoutms = mongoc_write_concern_get_wtimeout (old_wc );
1721
+
1722
+ new_wc = mongoc_write_concern_copy (old_wc );
1723
+
1724
+ if (bson_iter_init_find_case (& iter , options , "safe" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1725
+ mongoc_write_concern_set_w (new_wc , bson_iter_bool (& iter ) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED );
1726
+ }
1727
+
1728
+ if (bson_iter_init_find_case (& iter , options , "wtimeoutms" ) && BSON_ITER_HOLDS_INT32 (& iter )) {
1729
+ wtimeoutms = bson_iter_int32 (& iter );
1730
+ }
1731
+
1732
+ if (bson_iter_init_find_case (& iter , options , "journal" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1733
+ mongoc_write_concern_set_journal (new_wc , bson_iter_bool (& iter ));
1734
+ }
1735
+
1736
+ if (bson_iter_init_find_case (& iter , options , "w" )) {
1737
+ if (BSON_ITER_HOLDS_INT32 (& iter )) {
1738
+ int32_t value = bson_iter_int32 (& iter );
1739
+
1740
+ switch (value ) {
1741
+ case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED :
1742
+ case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED :
1743
+ mongoc_write_concern_set_w (new_wc , value );
1744
+ break ;
1745
+
1746
+ default :
1747
+ if (value > 0 ) {
1748
+ mongoc_write_concern_set_w (new_wc , value );
1749
+ break ;
1750
+ }
1751
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Unsupported w value: %d" , value );
1752
+ mongoc_write_concern_destroy (new_wc );
1753
+
1754
+ return false;
1755
+ }
1756
+ } else if (BSON_ITER_HOLDS_UTF8 (& iter )) {
1757
+ const char * str = bson_iter_utf8 (& iter , NULL );
1758
+
1759
+ if (0 == strcasecmp ("majority" , str )) {
1760
+ mongoc_write_concern_set_wmajority (new_wc , wtimeoutms );
1761
+ } else {
1762
+ mongoc_write_concern_set_wtag (new_wc , str );
1763
+ }
1764
+ }
1765
+ }
1766
+
1767
+ /* Only set wtimeout if it's still applicable; otherwise, clear it. */
1768
+ if (mongoc_write_concern_get_w (new_wc ) > 1 ||
1769
+ mongoc_write_concern_get_wmajority (new_wc ) ||
1770
+ mongoc_write_concern_get_wtag (new_wc )) {
1771
+ mongoc_write_concern_set_wtimeout (new_wc , wtimeoutms );
1772
+ } else {
1773
+ mongoc_write_concern_set_wtimeout (new_wc , 0 );
1774
+ }
1775
+
1776
+ if (mongoc_write_concern_get_journal (new_wc )) {
1777
+ int32_t w = mongoc_write_concern_get_w (new_wc );
1778
+
1779
+ if (w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED ) {
1780
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Journal conflicts with w value: %d" , w );
1781
+ mongoc_write_concern_destroy (new_wc );
1782
+
1783
+ return false;
1784
+ }
1785
+ }
1786
+
1787
+ /* This may be redundant in light of the last check (unacknowledged w with
1788
+ journal), but we'll check anyway in case additional validation is
1789
+ implemented. */
1790
+ if (!_mongoc_write_concern_is_valid (new_wc )) {
1791
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Write concern is not valid" );
1792
+ mongoc_write_concern_destroy (new_wc );
1793
+
1794
+ return false;
1795
+ }
1796
+
1797
+ mongoc_client_set_write_concern (client , new_wc );
1798
+ mongoc_write_concern_destroy (new_wc );
1799
+
1800
+ return true;
1801
+ } /* }}} */
1802
+
1594
1803
mongoc_client_t * php_phongo_make_mongo_client (const mongoc_uri_t * uri , zval * driverOptions TSRMLS_DC ) /* {{{ */
1595
1804
{
1596
1805
zval * * tmp ;
@@ -1621,7 +1830,7 @@ mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, zval *dri
1621
1830
client = mongoc_client_new_from_uri (uri );
1622
1831
1623
1832
if (!client ) {
1624
- RETURN (false );
1833
+ RETURN (NULL );
1625
1834
}
1626
1835
1627
1836
@@ -1982,6 +2191,7 @@ void _phongo_debug_bson(bson_t *bson)
1982
2191
str = bson_as_json (bson , & str_len );
1983
2192
1984
2193
php_printf ("JSON: %s\n" , str );
2194
+ bson_free (str );
1985
2195
}
1986
2196
/* LCOV_EXCL_STOP */
1987
2197
#endif
0 commit comments