SybSQL class

目次に戻る

# SybSQL

「SQL サーバへの接続」、「SQLコマンドの発行」、及び「結果データの検 索」など、ruby と SyBaseサーバとのインターフェース全般を実装したクラスです。

### SybSQL目次

- クラスメソッド
- メソッド（接続関連）
- メソッド（コマンド発行）
- メソッド（結果データ検索）
- メソッド（サーバオプション）
- メソッド（Image/Text データへのアクセス）
- メソッド（クライアントライブラリー カーソル）

### 使用モジュール

- SybConstant

### クラスメソッド

new( hash, context_class=SybSQLContext )
  hash で与えた情報により、SyBaseクライアントライブラリーを初期化し、 SQLサーバとの接続を確立します。

  hash は、

            {'S'=>srvname, 'U'=>user, 'P'=>psw,
             'lang'=>language, 'timeout'=>time-out, 'async'=>boolean,
             'login-timeout'=>login-timeout,
             'appname'=>applicatin-name 'hostname'=>host-name }

  の形式を取り、それぞれのキーと値の組合せは以下のようになります。

  - 'S' => 接続するSQLサーバ名 （必須）
  - 'U' => SQLサーバ名へのログインユーザ名（必須）
  - 'P' => SQLサーバ名へのログインパスワード （省略時は ''）
  - 'lang' => $SYBASE/locales/locales.datに登録されてあるロケール名
  - 'timeout' => サーバ応答のタイムアウト秒（省略時は０ ； タイムアウトしない ）
  - 'login-timeout' => ログインする時のタイムアウト秒
  - 'appname' => アプリケーション名
  - 'hostname' => ホスト名
  - 'async' => マルチスレッドアプリケーションの場合、true に設定 （省略時はfalse）
    参考 SybContext.create

  context_class には、SybSQLContext の サブクラスを指定してください。
  デフォルト（SybSQLContext）で定義し ているメッセージコールバックメソッドを再定義したい時に使います。

  例： SYBSRV01 サーバに sa ユーザで接続し、ロケールにはja_JP.ujisを使う場合。

        query = SybSQL.new({'S'=>'SYBSRV01','U'=>'sa','P'=>'XXXXXX',
                                    'lang'=>'ja_JP.ujis'} )

  例： サーバメッセージコールバックを再定義

        class MyContext < SybSQLContext
          def srvmsgCB( con,msghash)
            print "My server-callback\n"
          end
        end
        query = SybSQL.new({'S'=>'SYBSRV01','U'=>'sa','P'=>'XXXXXX'}, MyContext)

### メソッド（接続関連）

context
  SybContextオブジェクトを返します

connection
  SybConnectionオブジェクトを返します

close(force=false)
  サーバとの接続を切り、SyBaseクライアントライブラリーを終了させます。
  forceに true を設定すると、サーバにログアウトメッセージを送信 せずに接続を終了します。

connection_status
  接続ステータスを得ます。
  結果は、SybConstant::CS_CONSTAT_DEAD, SybConstant::CS_CONSTAT_CONNECTED の論理和です。

connection_dead?
  接続が死んでいれば TRUE が返ります

### メソッド（コマンド発行）

sql ( command, nbind=nil )
  SQL を発行します。
  検索したデータは、後でresult メソッドにより取り出すことが出来ます。

  commandには１トランザクションで実行できる複数のＳＱＬコマン ドを指定することも可能です。

  例

         query.sql('select * from sysservers')
         raise "ERROR: SELECT" unless (query.cmd_done? )

  nbindはバインドする最大カラム番号を指定します。通常は全てバイ ンドするのでnilを指定して下さい。

sql ( command, nbind=nil ) {|cmd,st,col,row| }
  SQL を発行します。
  1 ローを検索する度に、ブロックが呼び出されます。

  ブロックの引数

    cmd | SybCommand オブジェクト
    st | SybConstant::CS_SUCCEED または SybConstant::CS_ROW_FAIL
    col | カラム名配列
    row | ローデータの配列

  リターン値

    true | rowをresultメソッドが返す結果に加える
    nil | rowをresultメソッドが返す結果に加えない。 (巨大ローを検索する時に、メモリを節約するのに使える)
    false | fetch をキャンセルする。

  例

           query.sql("select title_id, notes from titles"){
             |cm,s,c,r|
             note = r[1]
             # get first sentence
             if( note =~ /^([^\.]*)\./io ) then
      	 print r[0],"\t",$1,"\n"
             end
             nil		# Not use SybResult
           }

set_strip(on)
  sql メソッドで検索するデータの、後続ブランクを切り詰めるかどうかを指定します。
  on = true なら切り詰められます。

sql_norow ( command )
  insert 文のように、結果ローが発生しない SQL を発行します。

  成功すると true、失敗すると false を返します。

  例

         raise "ERROR: USE DB" unless query.sql_norow('use master')

timeout?
  直前に発行した sql, sql_norowメソッドがタイムアウトした場合 true を返します
  このメソッドは、クライアントメッセージコールバックの実装に依存します。

fetch_rowfail( on )
  sql メソッドにおいて、CS_ROW_FAIL（回復可能エラー） のローを検索結果として返すか どうかを設定します。

  fetch_rowfail(true) なら、CS_ROW_FAIL のロー結果はデータとし て含まれますが、fetch_rowfail(false)なら、CS_ROW_FAIL のロー結果はnilと して、結果に含まれます。

  デフォルトの振舞いは、fetch_rowfail(false) です。

### メソッド（結果データ検索）

results
  以前に発行したsql、sql_norow、sql_getimage 及び、sql_iodesc メソッドの結果データを SybResult オブジェクトの配列として返します。

  注 意
    sqlメソッドなどでフェッチするSyBaseデータ型とrubyデータ型 の対応は以下のようになっています。

    SyBaseデータ型 | rubyデータ型
    --- | ---
    TINYINT | Integer
    SMALLINT | Integer
    INT | Integer
    REAL | Float
    FLOAT | Float
    その他 | String

each_results( type=SybConstant::CS_ROW_RESULT ){|r| ..}
  以前に発行した sqlメソッドの結果データのうち、restypeが typeと等しいSybResult オブジェクトを与える イテレータです。

nth_results(nth=0, type = SybConstant::CS_ROW_RESULT )
  以前に発行した sqlメソッドの結果データのうち、restypeが typeと等しいnth番目のSybResult オブジェクトを返します。

  type に指定可能なSybConstant定数は、

  - CS_CMD_SUCCEED (ローを返さないコマンドの正常終了通知)
  - CS_CMD_DONE (コマンドの正常処理を通知)
  - CS_CMD_FAIL(サーバエラーを通知)
  - CS_ROW_RESULT(通常ロー結果)
  - CS_PARAM_RESULT(リターンパラメータ結果)
  - CS_STATUS_RESULT(ストアドプロシジャー リターンステータス)
  - CS_COMPUTE_RESULT(compute ロー結果) のいずれかです。

    例： 二つの結果ローをプリントする

          query.sql("select * from table1\n select * from table2")
          raise "failed, SELECT" unless (query.cmd_done? )
          raise "No result in table1" unless (res = query.nth_results(0, CS_ROW_RESULT) )
          res.rows.each {
            |r| print "  #{r.join('|')}\n"
          }
          raise "No result table2" unless (res = query.nth_results(1, CS_ROW_RESULT) )
          res.rows.each {
            |r| print "  #{r.join('|')}\n"
          }

top_row_result
  最初の通常ロー(CS_ROW_RESULT)を持つ、SybResult オブジェクトを返します。
  `nth_results(0, SybConstant::CS_ROW_RESULT)`と同義

top_param_result
  最初のパラメータロー(CS_PARAM_RESULT)を持つ、 SybResult オブジェクトを返します。
  `nth_results(0, SybConstant::CS_PARAM_RESULT)`と同義

top_status_result
  最初のリターンステータス値（integer)を返す。

cmd_done?
  以前に発行した sql メソッドの結果データにつ いて、それが正しく処理されたかどうか(true/false)を返す。
  （結果データにCS_CMD_FAIL がなく、かつ、 CS_CMD_DONE があるか？）

cmd_succeed?
  以前に発行したローを返さないコマンド(sql_norow メソッド) が正しく処理されたかどうか(true/false)を返す。
  （結果データにCS_CMD_FAIL がなく、かつ、 CS_CMD_SUCCEED があるか？）

cmd_fail?
  以前に発行した sql及びsql_norow メソッドの結果データにつ いて、失敗したかどうかを返す。
  （結果データにCS_CMD_FAIL があるか？）

### メソッド（サーバオプション）

set_rowcount(maxrows)
  fetchするローの最大数を maxrowsに制限します。
  制限を外す場合は、maxrows = 0 (default)にしてください。
  （T-SQL の set rowcount コマンドに相当）

set_forceplan( val )
  val が true の場合、set forceplan on を実行します
  val が false の場合、set forceplan off を実行します

### メソッド（Image/Text データへのアクセス）

image_transize (size=nil)
  sql_getimage及びsend_imagefileメソッドにおける、データ転送サイズを設 定、または検索（size省略時)する。

  デフォルト状態では、1024 バイトに設定されています。

image_log( lg)
  send_imagefile及びsend_imageメソッドによって、Image/Text データを送 出する場合のトランザクションログを取るか取らないかを設定します。

  lg = false ならば、トランザクションログは取られません。 ただし、あらかじめ select into/bulkcopy オプションがDBに設定する必要 があります。

  デフォルトでは、ログは取られない設定になっています

sql_getimage( sqlstr, id) { |rowid,row, clmid, clm, data| }
  IMAGE/TEXT データを受信します。

  データは、image_transize() メソッドで指定したバイトづつ受信されます。

  - sqlstr
    Image/Textカラムをフェッチするための SQL 文
    返されるカラムの順番が、Image/Textカラムが最後になるようにしなけれ ばなりません

  - id
    最初の Image/Text 項目のカラム番号( start from 1 )

  - ブロック
    データを受信した時、繰り返し呼ばれるユーザ定義ブロックを指定します。

    ブロックの引数

      rowid | フェッチしたデータのロー番号(start from 0)
      row | フェッチしたローデータ配列
      clmid | 受信したImage/Textデータのカラム順(start from 0)
      clm | 受信したImage/Textデータのカラム名配列
      data | String : 受信したImage/Textデータ nil : データの最後を受信した false: エラーが起きた

    エラーが起きると、RuntimeError例外を発行します。

    例 au_pix テーブルからのイメージデータ検索

          query=SybSQL.new( {'S'=>'SYBASE', 'U'=>'sa', 'P'=>'XXXXXX'} )
          raise "ERROR use pubs2" unless( query.sql_norow("use pubs2") )

          # CS_OPT_TEXTSIZE （サーバが返す最大の Image/Text データサイズ）の拡張
          unless( query.connection.setopt(CS_OPT_TEXTSIZE, 1024 * 1024)) then
            $stderr.print("NG setopt(CS_OPT_TEXTSIZE)\n");
          end

          file = File.open("486-29-1786.ras","w")   # 格納するファイルのオープン
          query.image_transize(8192)   # 転送サイズ設定
          imgsize = 0
          sql = "select au_id ,pic from au_pix where au_id = '486-29-1786'"
          query.sql_getimage(sql, 2){
            |rid,r,cid,clm, data|
            if( data.kind_of?(String) )then
              file.write(data)
              imgsize += data.length
            elsif (data.nil?) then
              print "End of data\n"
              file.close
            end
          }
          print "Size=#{imgsize}\n"

sql_iodesc( sqlstr, id)

  SybIODesc(データ I/O 記述子構造体) を検 索します。

  SybIODesc オブジェクトは、Image/Text データを効率的に送信する場合に 必要になってきます。

  - sqlstr
    カラムをフェッチするための SQL 文
    返されるカラムの順番が、検索したいSybIODesc項目（通常は Image/Textカラム）が最後になるようにしなければなりません

  - id
    最初の 検索したいSybIODesc項目（通常はImage/Textカラム）のカラム番号 ( start from 1 )

    返却値は 検索した SybIODescオブジェクトです。エラーが起きると、 RuntimeError例外を発行します。

send_image(iodesc, imagesize) {|cmd| }

  IMAGE/TEXT データをサーバに送信します。

  - iodesc
    SybIODesc オブジェクト( SyBase データ I/O 記述子構造体)を指定します。 このオブジェクトは破壊的に変更されます。

  - imagesize
    転送する Image/Text データの総バイト数を指定します。０を指定すると、 NULLでアップデートされます。

  - ブロック
    転送の準備が整った段階で、繰り返し呼ばれるユーザ定義ブロックです。転 送するデータブロックを返すように設計します。

    ブロックの引数
      cmd --- SybCommandオブジェクト

    ブロックの返り値
      実際に転送すべき String データ、または、転送終了を示す nil を返す ように設計してください。

    エラーが起きると、RuntimeError例外を発行します。

send_imagefile(iodesc, filename)

  ファイルの内容を IMAGE/TEXT データとしてサーバに送信します。

  転送する時のブロックサイズは、image_transizeメソッドで決定されます。

  - iodesc
    SybIODesc オブジェクト( SyBase データ I/O 記述子構造体)を指定します。 このオブジェクトは破壊的に変更されます。

  - filename
    ファイル名を指定してください。

    エラーが起きると、RuntimeError例外を発行します。

    例 pubs2のau_pixテーブルに、新しいイメージデータを持つローを追加します。

          query=SybSQL.new( {'S'=>'SYBASE', 'U'=>'sa', 'P'=>'XXXXXX'} )

          # bulkcopy オプションを設定 (すでに設定されていれば必要ない）
          raise "ERROR use master" unless( query.sql_norow("use master") )
          query.sql("exec sp_dboption pubs2,'select into/bulkcopy',true")
          raise "ERROR sp_dboption" unless (query.cmd_done? )
          # sp_dboption の リターンステータスをチェック
          raise "ERROR sp_dboption" if( query.top_status_result != 0 )
          # checkpoint
          raise "ERROR use pubs2" unless( query.sql_norow("use pubs2") )
          raise "ERROR checkpoint" unless( query.sql_norow("checkpoint") )

          # 新しいローを追加
          sql = "insert au_pix (au_id,format_type ) values ('my-image-1', 'JPG')"
          raise "ERROR insert" unless( query.sql_norow(sql) )

          # Image項目をNULL で Update する （必須）
          sql = 'update au_pix set pic=NULL where au_id = "my-image-1"'
          raise "ERROR update" unless( query.sql_norow(sql) )

          query.image_transize( 2048 )	# 転送サイズの設定
          query.image_log( false )	# LOG は切捨て

          # SybIODesc の検索
          sql = 'select au_id,pic from au_pix where au_id = "my-image-1"'
          query.sql_iodesc(sql,2)
          iodesc = query.top_row_result.nthrow(0,1)
          raise "Cannot fetch IODESC" unless( iodesc.kind_of?(SybIODesc) )

          # ファイル my-image-1.jpg の内容を DB に転送する。
          query.send_imagefile(iodesc, "my-image-1.jpg")
          print "Success Insert image file\n"

### メソッド（クライアントライブラリー カーソル）

do_cursor ( csrname, langcmd, rowcount=nil, curopt=nil, nbind=nil) {|cmd,st,col,row| }
  クライアントライブラリー カーソルを割り当てて、それを実行します。
  備考：
  - do_cursor メソッドが終了すれば、カーソルは自動で廃棄されます
  - 言語カーソルは、sql メソッドで処理してください。

  csrname には、割り当てるカーソルの名前を指定します

  langcmdにはカーソルボディを表す SQL コマンドストリングを指定します。
  (参照： SybCommand#cursor_new)

  rowcount には、１回のフェッチ要求で返されるロー数を指定します。
  (参照： SybCommand#cursor_rows)

  curopt には、カーソル割り当てのオプションを指定します。
  (参照： SybCommand#cursor_new)

  nbindはバインドする最大カラム番号を指定します。通常は全てバイ ンドするのでnilを指定して下さい。

  ブロックそ指定すれば、1 ローを検索する度に、ブロックが呼び出され、 select, update, delete などのネストされたコマンド実行もできます

  ブロックの引数

    cmd | SybCommand オブジェクト
    st | SybConstant::CS_SUCCEED または SybConstant::CS_ROW_FAIL
    col | カラム名配列
    row | ローデータの配列

  リターン値

    true | rowをresultメソッドが返す結果に加える
    nil | rowをresultメソッドが返す結果に加えない。 (巨大ローを検索する時に、メモリを節約するのに使える)
    false | fetch をキャンセルする。

  例
  sample/cursor_disp.rb 及び sample/cursor_update.rb を参考にしてく ださい。