Permalink
Browse files

Merge pull request #53 from doctrine/master_slave

Master slave
  • Loading branch information...
2 parents ef0f74a + 9f8dbfb commit 02569f55e704e3b1c8297aea9f5d73e271f38f46 @beberlei beberlei committed Apr 1, 2012
@@ -64,30 +64,15 @@ private function addDbalSection(ArrayNodeDefinition $node)
->beforeNormalization()
->ifTrue(function ($v) { return is_array($v) && !array_key_exists('connections', $v) && !array_key_exists('connection', $v); })
->then(function ($v) {
+ // Key that should not be rewritten to the connection config
+ $excludedKeys = array('default_connection' => true, 'types' => true, 'type' => true);
$connection = array();
- foreach (array(
- 'dbname',
- 'host',
- 'port',
- 'user',
- 'password',
- 'driver',
- 'driver_class',
- 'options',
- 'path',
- 'memory',
- 'unix_socket',
- 'wrapper_class',
- 'platform_service',
- 'charset',
- 'logging',
- 'profiling',
- 'mapping_types',
- ) as $key) {
- if (array_key_exists($key, $v)) {
- $connection[$key] = $v[$key];
- unset($v[$key]);
+ foreach ($v as $key => $value) {
+ if (isset($excludedKeys[$key])) {
+ continue;
}
+ $connection[$key] = $v[$key];
+ unset($v[$key]);
}
$v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default';
$v['connections'] = array($v['default_connection'] => $connection);
@@ -125,42 +110,98 @@ private function getDbalConnectionsNode()
$treeBuilder = new TreeBuilder();
$node = $treeBuilder->root('connections');
- $node
+ /** @var $connectionNode ArrayNodeDefinition */
+ $connectionNode = $node
->requiresAtLeastOneElement()
->useAttributeAsKey('name')
->prototype('array')
- ->fixXmlConfig('mapping_type')
- ->children()
- ->scalarNode('dbname')->end()
- ->scalarNode('host')->defaultValue('localhost')->end()
- ->scalarNode('port')->defaultNull()->end()
- ->scalarNode('user')->defaultValue('root')->end()
- ->scalarNode('password')->defaultNull()->end()
- ->scalarNode('driver')->defaultValue('pdo_mysql')->end()
- ->scalarNode('path')->end()
- ->booleanNode('memory')->end()
- ->scalarNode('unix_socket')->end()
- ->scalarNode('platform_service')->end()
- ->scalarNode('charset')->end()
- ->booleanNode('logging')->defaultValue($this->debug)->end()
- ->booleanNode('profiling')->defaultValue($this->debug)->end()
- ->scalarNode('driver_class')->end()
- ->scalarNode('wrapper_class')->end()
- ->arrayNode('options')
- ->useAttributeAsKey('key')
- ->prototype('scalar')->end()
- ->end()
- ->arrayNode('mapping_types')
- ->useAttributeAsKey('name')
- ->prototype('scalar')->end()
- ->end()
+ ;
+
+ $this->configureDbalDriverNode($connectionNode);
+
+ $connectionNode
+ ->fixXmlConfig('option')
+ ->fixXmlConfig('mapping_type')
+ ->fixXmlConfig('slave')
+ ->children()
+ ->scalarNode('driver')->defaultValue('pdo_mysql')->end()
+ ->scalarNode('platform_service')->end()
+ ->booleanNode('logging')->defaultValue($this->debug)->end()
+ ->booleanNode('profiling')->defaultValue($this->debug)->end()
+ ->scalarNode('driver_class')->end()
+ ->scalarNode('wrapper_class')->end()
+ ->arrayNode('options')
+ ->useAttributeAsKey('key')
+ ->prototype('scalar')->end()
+ ->end()
+ ->arrayNode('mapping_types')
+ ->useAttributeAsKey('name')
+ ->prototype('scalar')->end()
->end()
->end()
;
+ $slaveNode = $connectionNode
+ ->children()
+ ->arrayNode('slaves')
+ ->useAttributeAsKey('name')
+ ->prototype('array')
+ ;
+ $this->configureDbalDriverNode($slaveNode);
+
return $node;
}
+ /**
+ * Adds config keys related to params processed by the DBAL drivers
+ *
+ * These keys are available for slave configurations too.
+ *
+ * @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $node
+ */
+ private function configureDbalDriverNode(ArrayNodeDefinition $node)
+ {
+ $node
+ ->children()
+ ->scalarNode('dbname')->end()
+ ->scalarNode('host')->defaultValue('localhost')->end()
+ ->scalarNode('port')->defaultNull()->end()
+ ->scalarNode('user')->defaultValue('root')->end()
+ ->scalarNode('password')->defaultNull()->end()
+ ->scalarNode('charset')->end()
+ ->scalarNode('path')->end()
+ ->booleanNode('memory')->end()
+ ->scalarNode('unix_socket')->setInfo('The unix socket to use for MySQL')->end()
+ ->booleanNode('persistent')->setInfo('True to use as persistent connection for the ibm_db2 driver')->end()
+ ->scalarNode('protocol')->setInfo('The protocol to use for the ibm_db2 driver (default to TCPIP if ommited)')->end()
+ ->booleanNode('service')->setInfo('True to use dbname as service name instead of SID for Oracle')->end()
+ ->scalarNode('sessionMode')
+ ->setInfo('The session mode to use for the oci8 driver')
+ ->end()
+ ->booleanNode('pooled')->setInfo('True to use a pooled server with the oci8 driver')->end()
+ ->booleanNode('MultipleActiveResultSets')->setInfo('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end()
+ ->end()
+ ->beforeNormalization()
+ ->ifTrue(function($v) {return !isset($v['sessionMode']) && isset($v['session_mode']);})
+ ->then(function($v) {
+ $v['sessionMode'] = $v['session_mode'];
+ unset($v['session_mode']);
+
+ return $v;
+ })
+ ->end()
+ ->beforeNormalization()
+ ->ifTrue(function($v) {return !isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']);})
+ ->then(function($v) {
+ $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets'];
+ unset($v['multiple_active_result_sets']);
+
+ return $v;
+ })
+ ->end()
+ ;
+ }
+
private function addOrmSection(ArrayNodeDefinition $node)
{
$node
@@ -170,19 +211,18 @@ private function addOrmSection(ArrayNodeDefinition $node)
->ifTrue(function ($v) { return null === $v || (is_array($v) && !array_key_exists('entity_managers', $v) && !array_key_exists('entity_manager', $v)); })
->then(function ($v) {
$v = (array) $v;
+ // Key that should not be rewritten to the connection config
+ $excludedKeys = array(
+ 'default_entity_manager' => true, 'auto_generate_proxy_classes' => true,
+ 'proxy_dir' => true, 'proxy_namespace' => true,
+ );
$entityManager = array();
- foreach (array(
- 'result_cache_driver', 'result-cache-driver',
- 'metadata_cache_driver', 'metadata-cache-driver',
- 'query_cache_driver', 'query-cache-driver',
- 'auto_mapping', 'auto-mapping',
- 'mappings', 'mapping',
- 'connection', 'dql'
- ) as $key) {
- if (array_key_exists($key, $v)) {
- $entityManager[$key] = $v[$key];
- unset($v[$key]);
+ foreach ($v as $key => $value) {
+ if (isset($excludedKeys[$key])) {
+ continue;
}
+ $entityManager[$key] = $v[$key];
+ unset($v[$key]);
}
$v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default';
$v['entity_managers'] = array($v['default_entity_manager'] => $entityManager);
@@ -175,6 +175,28 @@ protected function getConnectionOptions($connection)
}
}
+ if (!empty($options['slaves'])) {
+ $nonRewrittenKeys = array(
+ 'driver' => true, 'driverOptions' => true, 'driverClass' => true, 'wrapperClass' => true,
+ 'platform' => true, 'slaves' => true, 'master' => true,
+ // included by safety but should have been unset already
+ 'logging' => true, 'profiling' => true, 'mapping_types' => true, 'platform_service' => true,
+ );
+ foreach ($options as $key => $value) {
+ if (isset($nonRewrittenKeys[$key])) {
+ continue;
+ }
+ $options['master'][$key] = $value;
+ unset($options[$key]);
+ }
+ if (empty($options['wrapperClass'])) {
+ // Change the wrapper class only if the user does not already forced using a custom one.
+ $options['wrapperClass'] = 'Doctrine\\DBAL\\Connections\\MasterSlaveConnection';
+ }
+ } else {
+ unset($options['slaves']);
+ }
+
return $options;
}
@@ -15,21 +15,31 @@
</xsd:element>
<xsd:attributeGroup name="connection-config">
+ <xsd:attribute name="driver" type="xsd:string" />
+ <xsd:attribute name="driver-class" type="xsd:string" />
+ <xsd:attribute name="wrapper-class" type="xsd:string" />
+ <xsd:attribute name="platform-service" type="xsd:string" />
+ <xsd:attribute name="logging" type="xsd:string" default="false" />
+ <xsd:attribute name="profiling" type="xsd:string" default="false" />
+ <xsd:attributeGroup ref="driver-config" />
+ </xsd:attributeGroup>
+
+ <xsd:attributeGroup name="driver-config">
<xsd:attribute name="dbname" type="xsd:string" />
<xsd:attribute name="host" type="xsd:string" />
<xsd:attribute name="port" type="xsd:integer" />
<xsd:attribute name="user" type="xsd:string" />
<xsd:attribute name="password" type="xsd:string" />
- <xsd:attribute name="driver" type="xsd:string" />
- <xsd:attribute name="driver-class" type="xsd:string" />
<xsd:attribute name="path" type="xsd:string" />
<xsd:attribute name="unix-socket" type="xsd:string" />
<xsd:attribute name="memory" type="xsd:boolean" />
<xsd:attribute name="charset" type="xsd:string" />
- <xsd:attribute name="wrapper-class" type="xsd:string" />
- <xsd:attribute name="platform-service" type="xsd:string" />
- <xsd:attribute name="logging" type="xsd:string" default="false" />
- <xsd:attribute name="profiling" type="xsd:string" default="false" />
+ <xsd:attribute name="persistent" type="xsd:boolean" />
+ <xsd:attribute name="protocol" type="xsd:string" />
+ <xsd:attribute name="service" type="xsd:boolean" />
+ <xsd:attribute name="session-mode" type="xsd:string" />
+ <xsd:attribute name="pooled" type="xsd:boolean" />
+ <xsd:attribute name="multiple-active-result-sets" type="xsd:boolean" />
</xsd:attributeGroup>
<xsd:complexType name="dbal">
@@ -38,6 +48,7 @@
<xsd:element name="type" type="type" />
<xsd:element name="option" type="option" />
<xsd:element name="mapping-type" type="mapping-type" />
+ <xsd:element name="slave" type="slave" />
</xsd:choice>
<xsd:attribute name="default-connection" type="xsd:string" />
@@ -72,11 +83,17 @@
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="option" type="option" />
<xsd:element name="mapping-type" type="mapping-type" />
+ <xsd:element name="slave" type="slave" />
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attributeGroup ref="connection-config" />
</xsd:complexType>
+ <xsd:complexType name="slave">
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attributeGroup ref="driver-config" />
+ </xsd:complexType>
+
<xsd:complexType name="mapping">
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="type" type="xsd:string" />
@@ -99,6 +99,33 @@ public function testDbalLoadFromXmlSingleConnections()
$this->assertEquals('/path/to/mysqld.sock', $config['unix_socket']);
}
+ public function testDbalLoadSingleMasterSlaveConnection()
+ {
+ $container = $this->getContainer();
+ $loader = new DoctrineExtension();
+ $container->registerExtension($loader);
+
+ $this->loadFromFile($container, 'dbal_service_single_master_slave_connection');
+
+ $this->compileContainer($container);
+
+ // doctrine.dbal.mysql_connection
+ $param = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
+
+ $this->assertEquals('Doctrine\\DBAL\\Connections\\MasterSlaveConnection', $param['wrapperClass']);
+ $this->assertEquals(
+ array('user' => 'mysql_user', 'password' => 'mysql_s3cr3t', 'port' => null, 'dbname' => 'mysql_db', 'host' => 'localhost', 'unix_socket' => '/path/to/mysqld.sock'),
+ $param['master']
+ );
+ $this->assertEquals(
+ array(
+ 'user' => 'slave_user', 'password' => 'slave_s3cr3t', 'port' => null, 'dbname' => 'slave_db',
+ 'host' => 'localhost', 'unix_socket' => '/path/to/mysqld_slave.sock'
+ ),
+ $param['slaves']['slave1']
+ );
+ }
+
public function testDependencyInjectionConfigurationDefaults()
{
$container = $this->getContainer();
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+
+<srv:container xmlns="http://symfony.com/schema/dic/doctrine"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:srv="http://symfony.com/schema/dic/services"
+ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
+ http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
+
+ <config>
+ <dbal dbname="mysql_db" user="mysql_user" password="mysql_s3cr3t" unix-socket="/path/to/mysqld.sock">
+ <slave name="slave1" dbname="slave_db" user="slave_user" password="slave_s3cr3t" unix-socket="/path/to/mysqld_slave.sock" />
+ </dbal>
+ </config>
+</srv:container>
@@ -0,0 +1,12 @@
+doctrine:
+ dbal:
+ dbname: mysql_db
+ user: mysql_user
+ password: mysql_s3cr3t
+ unix_socket: /path/to/mysqld.sock
+ slaves:
+ slave1:
+ user: slave_user
+ dbname: slave_db
+ password: slave_s3cr3t
+ unix_socket: /path/to/mysqld_slave.sock

0 comments on commit 02569f5

Please sign in to comment.