123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- <?php
- /**
- * @file
- * Define a MigrateSource for importing from Microsoft SQL Server databases.
- */
- /**
- * Implementation of MigrateSource, to handle imports from remote MS SQL Server db servers.
- */
- class MigrateSourceMSSQL extends MigrateSource {
- /**
- * Array containing information for connecting to SQL Server:
- * servername - Hostname of the SQL Server
- * username - Username to connect as
- * password - Password for logging in
- * database (optional) - Database to select after connecting
- *
- * @var array
- */
- protected $configuration;
- /**
- * The active MS SQL Server connection for this source.
- *
- * @var resource
- */
- protected $connection;
- /**
- * The SQL query from which to obtain data. Is a string.
- */
- protected $query;
- /**
- * The result object from executing the query - traversed to process the
- * incoming data.
- */
- protected $result;
- /**
- * By default, mssql_query fetches all results - severe memory problems with
- * big tables. So, we will fetch a batch at a time.
- *
- * @var int
- */
- protected $batchSize;
- /**
- * Return an options array for MS SQL sources.
- *
- * @param int $batch_size
- * Number of rows to pull at once (defaults to 500).
- * @param boolean $cache_counts
- * Indicates whether to cache counts of source records.
- */
- static public function options($batch_size, $cache_counts) {
- return compact('batch_size', 'cache_counts');
- }
- /**
- * Simple initialization.
- */
- public function __construct(array $configuration, $query, $count_query,
- array $fields, array $options = array()) {
- parent::__construct($options);
- $this->query = $query;
- $this->countQuery = $count_query;
- $this->configuration = $configuration;
- $this->fields = $fields;
- $this->batchSize = isset($options['batch_size']) ? $options['batch_size'] : 500;
- }
- /**
- * Return a string representing the source query.
- *
- * @return string
- */
- public function __toString() {
- return $this->query;
- }
- /**
- * Connect lazily to the DB server.
- */
- protected function connect() {
- if (!isset($this->connection)) {
- if (!extension_loaded('mssql')) {
- throw new Exception(t('You must configure the mssql extension in PHP.'));
- }
- if (isset($this->configuration['port'])) {
- $host = $this->configuration['servername'] . ':' . $this->configuration['port'];
- }
- else {
- $host = $this->configuration['servername'];
- }
- $this->connection = mssql_connect(
- $host,
- $this->configuration['username'],
- $this->configuration['password'],
- TRUE);
- if (isset($this->configuration['database'])) {
- return mssql_select_db($this->configuration['database'], $this->connection);
- }
- }
- }
- /**
- * Returns a list of fields available to be mapped from the source query.
- *
- * @return array
- * Keys: machine names of the fields (to be passed to addFieldMapping)
- * Values: Human-friendly descriptions of the fields.
- */
- public function fields() {
- // The fields are passed to the constructor for this plugin.
- return $this->fields;
- }
- /**
- * Return a count of all available source records.
- */
- public function computeCount() {
- migrate_instrument_start('MigrateSourceMSSQL count');
- if ($this->connect()) {
- $result = mssql_query($this->countQuery);
- $count = reset(mssql_fetch_object($result));
- }
- else {
- // Do something else?
- $count = FALSE;
- }
- migrate_instrument_stop('MigrateSourceMSSQL count');
- return $count;
- }
- /**
- * Implementation of MigrateSource::performRewind().
- */
- public function performRewind() {
- /*
- * Replace :criteria placeholder with idlist or highwater clauses. We
- * considered supporting both but it is not worth the complexity. Run twice
- * instead.
- */
- if (!empty($this->idList)) {
- $keys = array();
- foreach ($this->activeMap->getSourceKey() as $field_name => $field_schema) {
- // Allow caller to provide an alias to table containing the primary key.
- if (!empty($field_schema['alias'])) {
- $field_name = $field_schema['alias'] . '.' . $field_name;
- }
- $keys[] = $field_name;
- }
- // TODO: Sanitize. not critical as this is admin supplied data in drush.
- $this->query = str_replace(':criteria',
- $keys[0] . ' IN (' . implode(',', $this->idList) . ')', $this->query);
- }
- else {
- if (isset($this->highwaterField['name']) && $highwater = $this->activeMigration->getHighwater()) {
- if (empty($this->highwaterField['alias'])) {
- $highwater_name = $this->highwaterField['name'];
- }
- else {
- $highwater_name = $this->highwaterField['alias'] . '.' . $this->highwaterField['name'];
- }
- $this->query = str_replace(':criteria', "$highwater_name > '$highwater'", $this->query);
- }
- else {
- // No idlist or highwater. Replace :criteria placeholder with harmless WHERE
- // clause instead of empty since we don't know if an AND follows.
- $this->query = str_replace(':criteria', '1=1', $this->query);
- }
- }
- migrate_instrument_start('mssql_query');
- $this->connect();
- $this->result = mssql_query($this->query, $this->connection, $this->batchSize);
- migrate_instrument_stop('mssql_query');
- }
- /**
- * Implementation of MigrateSource::getNextRow().
- *
- * Returns the next row of the result set as an object, dealing with the
- * difference between the end of the batch and the end of all data.
- */
- public function getNextRow() {
- $row = mssql_fetch_object($this->result);
- // Might be totally out of data, or just out of this batch - request another
- // batch and see
- if (!is_object($row)) {
- mssql_fetch_batch($this->result);
- $row = mssql_fetch_object($this->result);
- }
- if (is_object($row)) {
- return $row;
- }
- else {
- return NULL;
- }
- }
- }
|