SqlServerConnector.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. namespace Illuminate\Database\Connectors;
  3. use PDO;
  4. use Illuminate\Support\Arr;
  5. class SqlServerConnector extends Connector implements ConnectorInterface
  6. {
  7. /**
  8. * The PDO connection options.
  9. *
  10. * @var array
  11. */
  12. protected $options = [
  13. PDO::ATTR_CASE => PDO::CASE_NATURAL,
  14. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  15. PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
  16. PDO::ATTR_STRINGIFY_FETCHES => false,
  17. ];
  18. /**
  19. * Establish a database connection.
  20. *
  21. * @param array $config
  22. * @return \PDO
  23. */
  24. public function connect(array $config)
  25. {
  26. $options = $this->getOptions($config);
  27. return $this->createConnection($this->getDsn($config), $config, $options);
  28. }
  29. /**
  30. * Create a DSN string from a configuration.
  31. *
  32. * @param array $config
  33. * @return string
  34. */
  35. protected function getDsn(array $config)
  36. {
  37. // First we will create the basic DSN setup as well as the port if it is in
  38. // in the configuration options. This will give us the basic DSN we will
  39. // need to establish the PDO connections and return them back for use.
  40. if ($this->prefersOdbc($config)) {
  41. return $this->getOdbcDsn($config);
  42. }
  43. if (in_array('sqlsrv', $this->getAvailableDrivers())) {
  44. return $this->getSqlSrvDsn($config);
  45. } else {
  46. return $this->getDblibDsn($config);
  47. }
  48. }
  49. /**
  50. * Determine if the database configuration prefers ODBC.
  51. *
  52. * @param array $config
  53. * @return bool
  54. */
  55. protected function prefersOdbc(array $config)
  56. {
  57. return in_array('odbc', $this->getAvailableDrivers()) &&
  58. ($config['odbc'] ?? null) === true;
  59. }
  60. /**
  61. * Get the DSN string for a DbLib connection.
  62. *
  63. * @param array $config
  64. * @return string
  65. */
  66. protected function getDblibDsn(array $config)
  67. {
  68. return $this->buildConnectString('dblib', array_merge([
  69. 'host' => $this->buildHostString($config, ':'),
  70. 'dbname' => $config['database'],
  71. ], Arr::only($config, ['appname', 'charset', 'version'])));
  72. }
  73. /**
  74. * Get the DSN string for an ODBC connection.
  75. *
  76. * @param array $config
  77. * @return string
  78. */
  79. protected function getOdbcDsn(array $config)
  80. {
  81. return isset($config['odbc_datasource_name'])
  82. ? 'odbc:'.$config['odbc_datasource_name'] : '';
  83. }
  84. /**
  85. * Get the DSN string for a SqlSrv connection.
  86. *
  87. * @param array $config
  88. * @return string
  89. */
  90. protected function getSqlSrvDsn(array $config)
  91. {
  92. $arguments = [
  93. 'Server' => $this->buildHostString($config, ','),
  94. ];
  95. if (isset($config['database'])) {
  96. $arguments['Database'] = $config['database'];
  97. }
  98. if (isset($config['readonly'])) {
  99. $arguments['ApplicationIntent'] = 'ReadOnly';
  100. }
  101. if (isset($config['pooling']) && $config['pooling'] === false) {
  102. $arguments['ConnectionPooling'] = '0';
  103. }
  104. if (isset($config['appname'])) {
  105. $arguments['APP'] = $config['appname'];
  106. }
  107. if (isset($config['encrypt'])) {
  108. $arguments['Encrypt'] = $config['encrypt'];
  109. }
  110. if (isset($config['trust_server_certificate'])) {
  111. $arguments['TrustServerCertificate'] = $config['trust_server_certificate'];
  112. }
  113. if (isset($config['multiple_active_result_sets']) && $config['multiple_active_result_sets'] === false) {
  114. $arguments['MultipleActiveResultSets'] = 'false';
  115. }
  116. if (isset($config['transaction_isolation'])) {
  117. $arguments['TransactionIsolation'] = $config['transaction_isolation'];
  118. }
  119. if (isset($config['multi_subnet_failover'])) {
  120. $arguments['MultiSubnetFailover'] = $config['multi_subnet_failover'];
  121. }
  122. return $this->buildConnectString('sqlsrv', $arguments);
  123. }
  124. /**
  125. * Build a connection string from the given arguments.
  126. *
  127. * @param string $driver
  128. * @param array $arguments
  129. * @return string
  130. */
  131. protected function buildConnectString($driver, array $arguments)
  132. {
  133. return $driver.':'.implode(';', array_map(function ($key) use ($arguments) {
  134. return sprintf('%s=%s', $key, $arguments[$key]);
  135. }, array_keys($arguments)));
  136. }
  137. /**
  138. * Build a host string from the given configuration.
  139. *
  140. * @param array $config
  141. * @param string $separator
  142. * @return string
  143. */
  144. protected function buildHostString(array $config, $separator)
  145. {
  146. if (empty($config['port'])) {
  147. return $config['host'];
  148. }
  149. return $config['host'].$separator.$config['port'];
  150. }
  151. /**
  152. * Get the available PDO drivers.
  153. *
  154. * @return array
  155. */
  156. protected function getAvailableDrivers()
  157. {
  158. return PDO::getAvailableDrivers();
  159. }
  160. }