LoginSignup
2
0

More than 5 years have passed since last update.

rails dbconsoleでSQL Serverに接続しようとしたときのメモ

Last updated at Posted at 2018-02-11

Rails5からrails dbを使ってSQL Serverに接続したかったので調べて試した結果をメモ。
結果としては接続はできた。
ただしSQL Server側がDatabaseの切り替えをサポートしていないので接続先のデータベースが指定できないということもあり実用性無し。
そのためtsqlコマンドで接続することに変更した。

環境

OS : CentOS7.3
ruby : 2.4.2
Rails : 5.1.4
DB : SQL Server(Azure)のtest-database(事前に作成済み)

FreeTSDのインストール

レポジトリにあるFreeTDS(0.9系)を使うと接続時にwarning: TinyTds: :use_utf16 option not supported in this version of FreeTDS.という警告が出る。
それを回避するにはバージョンが1.0以上のFreeTDSをインストールしないと駄目なのでソースからビルドする。

$ cd /usr/local/src
$ wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-1.00.9.tar.gz
$ tar zxvf freetds-1.00.9.tar.gz
$ cd  freetds-1.00.9
$ ./configure --prefix=/usr/local/freetds
$ make
$ make install
$ vi /etc/profile.d/freetds.sh
export PATH="/usr/local/freetds/bin:${PATH}"
export LD_LIBRARY_PATH="/usr/local/freetds/lib:${LD_LIBRARY_PATH}"
$ exec ${SHELL} -l
$ tsql -C
Compile-time settings (established with the "configure" script)
                            Version: freetds v1.00.9
             freetds.conf directory: /usr/local/freetds/etc
     MS db-lib source compatibility: no
        Sybase binary compatibility: no
                      Thread safety: yes
                      iconv library: yes
                        TDS version: auto
                              iODBC: no
                           unixodbc: no
              SSPI "trusted" logins: no
                           Kerberos: no
                            OpenSSL: yes
                             GnuTLS: no
                               MARS: no

sqshのインストール

rails dbで接続するにはsqshというコマンドが必要なのでこれもソースからインストールする。

$ SYBASE=/usr/local/freetds
$ export SYBASE
$ cd /usr/local/src
$ wget https://jaist.dl.sourceforge.net/project/sqsh/sqsh/sqsh-2.5/sqsh-2.5.16.1.tgz
$ tar zxvf sqsh-2.5.16.1.tgz
$ cd sqsh-2.5/

三箇所ほどソースに手を加えないとエラーでこけるので以下のように修正する。
まず一箇所目。
修正前

/usr/local/src/sqsh-2.5/src/cmd_connect.c
/* 860行目付近 */
#if !defined(CS_TDS_50)
        /* Then we use freetds which uses enum instead of defines */
        else if (strcmp(tds_version, "7.0") == 0)
            version = CS_TDS_70;
        else if (strcmp(tds_version, "8.0") == 0)
            version = CS_TDS_80;

修正後

/usr/local/src/sqsh-2.5/src/cmd_connect.c
#if !defined(CS_TDS_50)
        /* Then we use freetds which uses enum instead of defines */
        else if (strcmp(tds_version, "7.0") == 0)
            version = CS_TDS_70;
        #else if (strcmp(tds_version, "8.0") == 0)
        #    version = CS_TDS_80;
        else if (strcmp(tds_version, "7.1") == 0)
            version = CS_TDS_71;
        else if (strcmp(tds_version, "7.2") == 0)
            version = CS_TDS_72;
        else if (strcmp(tds_version, "7.3") == 0)
            version = CS_TDS_73;

続いて二箇所目。
修正前

/usr/local/src/sqsh-2.5/src/cmd_connect.c
/* 1260行目付近 */
#if !defined(CS_TDS_50)
                case CS_TDS_70:
                    env_set( g_env, "tds_version", "7.0" );
                case CS_TDS_80:
                    env_set( g_env, "tds_version", "8.0" );
                    break;

修正後

/usr/local/src/sqsh-2.5/src/cmd_connect.c
#if !defined(CS_TDS_50)
                case CS_TDS_70:
                    env_set( g_env, "tds_version", "7.0" );
                    break;
                #case CS_TDS_80:
                #    env_set( g_env, "tds_version", "8.0" );
                #    break;
                case CS_TDS_71:
                    env_set( g_env, "tds_version", "7.1" );
                    break;
                case CS_TDS_72:
                    env_set( g_env, "tds_version", "7.2" );
                    break;
                case CS_TDS_73:
                    env_set( g_env, "tds_version", "7.3" );
                    break;

ラスト
修正前

/usr/local/src/sqsh-2.5/src/dsp_conv.c
/* 664行目付近 */
    /*
     * Take the existing format and strip it down according to the
     * type of date that we are processing and replace the ms
     * field if it exists.
     */
     #if defined(CS_BIGDATETIME_TYPE) && defined(CS_BIGTIME_TYPE)
       if (dt_fmt->datatype == CS_BIGDATETIME_TYPE || dt_fmt->datatype == CS_BIGTIME_TYPE)
          fmt = dsp_datetime_strip( dt_fmt->datatype, conv_fmt, (int) dr.datesecfrac );
       else
     #endif

        fmt = dsp_datetime_strip( dt_fmt->datatype, conv_fmt, (int) dr.datemsecond );

修正後

/usr/local/src/sqsh-2.5/src/dsp_conv.c
/* 修正後 */
    /*
     * Take the existing format and strip it down according to the
     * type of date that we are processing and replace the ms
     * field if it exists.
     */
     fmt = dsp_datetime_strip( dt_fmt->datatype, conv_fmt, (int) dr.datemsecond );

修正を終えたらビルドしてインストールする。

$ ./configure --prefix=/usr/local/sqsh
$ make clean
$ make
$ make install
$ vi /etc/profile.d/sqsh.sh
export PATH="/usr/local/sqsh/bin:${PATH}"
$ exec ${SHELL} -l
$ sqsh -v
sqsh-2.5.16.1

これでRailsで接続する準備が出来た。

Rails側の環境構築

プロジェクトを作成する際にはsqlserverを指定する。
必要なgemは一緒にインストールされるのでGemfileは編集しなくもOK。
ただしfreetdsのインストール先を設定する必要あり。
SQL Serverへの接続はactiverecord-sqlserver-adapterとtiny_tdsが使われる。

$ rails new Sample -d sqlserver -B -T --api
$ cd Sample
$ bundle config build.tiny_tds -- --with-freetds-dir=/usr/local/freetds
$ bundle install --path vendor/bundle

database.ymlを編集する。

config/database.yml
default: &default
  adapter: sqlserver
  username: rails
  password: <%= ENV['DB_PASSWORD'] %>
  host: hostname or IP
  port: 1433  # ポート番号に変更が無いなら省略可
  azure: true # Azure上のSQL Serverにつなぐには必要らしい

development:
  <<: *default
  database: test-database

接続確認

準備できたので接続できるか試す

$ rails db
sqsh-2.5.16.1 Copyright (C) 1995-2001 Scott C. Gray
Portions Copyright (C) 2004-2014 Michael Peppler and Martin Wesdorp
This is free software with ABSOLUTELY NO WARRANTY
For more information type '\warranty'
Msg 40508, Level 16, State 1
Server 'XXXXXXXXXXXXXX', Line 1
USE statement is not supported to switch between databases. Use a new connection to connect to a different database.
[5] XXXXXXXXXXXXXX.master.1>

接続はできたっぽいけどtest-databaseには接続できていないっぽい?masterってなんだ・・・。
軽く調べた限りではSQLServer(Azure)側がUSEコマンドをサポートしてないのが原因っぽい。
DB側が未サポートなのはどうにもならないので別の方法で接続することに変更。

tsqlコマンドで接続確認

rails dbじゃあ接続できないのでFreeTDSのtsqlを使って接続する。
まずfreetds.confに接続先の情報を追記

/usr/local/freetds/etc/freetds.conf
[conn-test]
        host = hostname or IP
        port = 1433
        tds version = 7.0

続いてtsqlコマンドを実行。

$ tsql -S conn-test -U "ユーザ名" -D "test-database"
Password: 
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Setting test-database as default database in login packet
1> 

接続できた。やったね。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0