SqlServerConnector.php 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 (in_array('dblib', $this->getAvailableDrivers())) {
  41. return $this->getDblibDsn($config);
  42. } elseif ($this->prefersOdbc($config)) {
  43. return $this->getOdbcDsn($config);
  44. }
  45. return $this->getSqlSrvDsn($config);
  46. }
  47. /**
  48. * Determine if the database configuration prefers ODBC.
  49. *
  50. * @param array $config
  51. * @return bool
  52. */
  53. protected function prefersOdbc(array $config)
  54. {
  55. return in_array('odbc', $this->getAvailableDrivers()) &&
  56. ($config['odbc'] ?? null) === true;
  57. }
  58. /**
  59. * Get the DSN string for a DbLib connection.
  60. *
  61. * @param array $config
  62. * @return string
  63. */
  64. protected function getDblibDsn(array $config)
  65. {
  66. return $this->buildConnectString('dblib', array_merge([
  67. 'host' => $this->buildHostString($config, ':'),
  68. 'dbname' => $config['database'],
  69. ], Arr::only($config, ['appname', 'charset', 'version'])));
  70. }
  71. /**
  72. * Get the DSN string for an ODBC connection.
  73. *
  74. * @param array $config
  75. * @return string
  76. */
  77. protected function getOdbcDsn(array $config)
  78. {
  79. return isset($config['odbc_datasource_name'])
  80. ? 'odbc:'.$config['odbc_datasource_name'] : '';
  81. }
  82. /**
  83. * Get the DSN string for a SqlSrv connection.
  84. *
  85. * @param array $config
  86. * @return string
  87. */
  88. protected function getSqlSrvDsn(array $config)
  89. {
  90. $arguments = [
  91. 'Server' => $this->buildHostString($config, ','),
  92. ];
  93. if (isset($config['database'])) {
  94. $arguments['Database'] = $config['database'];
  95. }
  96. if (isset($config['readonly'])) {
  97. $arguments['ApplicationIntent'] = 'ReadOnly';
  98. }
  99. if (isset($config['pooling']) && $config['pooling'] === false) {
  100. $arguments['ConnectionPooling'] = '0';
  101. }
  102. if (isset($config['appname'])) {
  103. $arguments['APP'] = $config['appname'];
  104. }
  105. if (isset($config['encrypt'])) {
  106. $arguments['Encrypt'] = $config['encrypt'];
  107. }
  108. if (isset($config['trust_server_certificate'])) {
  109. $arguments['TrustServerCertificate'] = $config['trust_server_certificate'];
  110. }
  111. if (isset($config['multiple_active_result_sets']) && $config['multiple_active_result_sets'] === false) {
  112. $arguments['MultipleActiveResultSets'] = 'false';
  113. }
  114. if (isset($config['transaction_isolation'])) {
  115. $arguments['TransactionIsolation'] = $config['transaction_isolation'];
  116. }
  117. if (isset($config['multi_subnet_failover'])) {
  118. $arguments['MultiSubnetFailover'] = $config['multi_subnet_failover'];
  119. }
  120. return $this->buildConnectString('sqlsrv', $arguments);
  121. }
  122. /**
  123. * Build a connection string from the given arguments.
  124. *
  125. * @param string $driver
  126. * @param array $arguments
  127. * @return string
  128. */
  129. protected function buildConnectString($driver, array $arguments)
  130. {
  131. return $driver.':'.implode(';', array_map(function ($key) use ($arguments) {
  132. return sprintf('%s=%s', $key, $arguments[$key]);
  133. }, array_keys($arguments)));
  134. }
  135. /**
  136. * Build a host string from the given configuration.
  137. *
  138. * @param array $config
  139. * @param string $separator
  140. * @return string
  141. */
  142. protected function buildHostString(array $config, $separator)
  143. {
  144. if (isset($config['port']) && ! empty($config['port'])) {
  145. return $config['host'].$separator.$config['port'];
  146. } else {
  147. return $config['host'];
  148. }
  149. }
  150. /**
  151. * Get the available PDO drivers.
  152. *
  153. * @return array
  154. */
  155. protected function getAvailableDrivers()
  156. {
  157. return PDO::getAvailableDrivers();
  158. }
  159. }