万年素人からHackerへの道

万年素人がHackerになれるまで殴り書きするぜ。

  • ・資産運用おすすめ
    10万円は1000円くらい利益
    資産運用ブログ アセマネ
    • ・寄付お願いします
      YENTEN:YYzNPzdsZWqr5THWAdMrKDj7GT8ietDc2W
      BitZenny:ZfpUbVya8MWQkjjGJMjA7P9pPkqaLnwPWH
      c0ban:8KG95GXdEquNpPW8xJAJf7nn5kbimQ5wj1
      Skycoin:KMqcn7x8REwwzMHPi9fV9fbNwdofYAWKRo

    Boo Language Advent Calendar 2012 9日目 Title:「Sqlite+Boo連携! in Unity」

    URL: http://atnd.org/events/34622

    SqliteとBoo連携をUnityでやってる人はいないんじゃないんでしょうか?
    てことで書きます。まぁ、Unityでsqliteやってる人もあまり見ない。
    ていうかBooは更にすくないかも?

    まず、Boo公式のドキュメントを読む(Copyright 2003-2006)
    URL: http://boo.codehaus.org/SQLite+Database

    念のため書くが、

    print myRow[myColumn])
    

    の最後の「)」カッコはバグ

    「Mono.Data.SqliteClient.dll」を使いましょうとコメントで書いてある。

    //Requires Mono.Data.SqliteClient.dll which is included with Mono.

    探すとこの日本語のBlog(2007-02-23)にたどり着いた。
    URL: http://d.hatena.ne.jp/atsushieno/20070223

    「これまで使われていたMono.Data.SqliteClient.dllは、vladが2002年にやっつけたのが起源で(彼は今でこそfirefox3の主要開発者だが、昔はXimianインターンだった)、その後ずっとメンテナーフリーの状態だった。で、最近になってここで開発されているSystem.Data.SqliteClientが出来が良いらしい、ということで、これをMarek(ASP.NETの方)がmono向けに移植しているようだ。」

    このBlogを鵜呑みにして解釈すると、「Mono.Data.SqliteClient.dll」は最近になってより良い「System.Data.SqliteClient」になったということだろう。

    Boo公式のドキュメントが2003-2006と書かれてたので、最高でも2006年の情報なので、2007-02-23のこのBlogの方が新しい(5年前・・・むしろ6年弱前)であろう。

    なので、
    URL: http://sourceforge.net/projects/sqlite-dotnet2/
    から「Mono.Data.Sqlite.dll」をダウンロードした。
    Last Updateが「2010-12-10」なので、2年前だが・・。

    やりかたとしては、先ほどの「Mono.Data.Sqlite.dll」を「Plugins」というフォルダに突っ込んだ。こうするとUnityがDLL認識してくれる。

    さらに、公式BlogのBooコードをUnityらしく記載してみた。
    ※Awakeに書いて、printをDebug.Log("String")にした

    このコードをMain Cameraにアタッチしたよ。
    ・SqliteTest

    import System
    import System.Data from System.Data
    import Mono.Data.Sqlite
    
    class SqliteTest (MonoBehaviour):
    
        def Awake ():
            Debug.Log('If this test works, you should get:')
            Debug.Log('Data 1: 5')
            Debug.Log('Data 2: Mono')
            Debug.Log('create SqliteConnection...')
            dbcon as SqliteConnection = SqliteConnection()
            connectionString as string = 'URI=file:SqliteTest.db'
            Debug.Log('setting ConnectionString using: ' + connectionString)
            dbcon.ConnectionString = connectionString
            Debug.Log('open the connection...')
            dbcon.Open()
            Debug.Log('create SqliteCommand to CREATE TABLE MONO_TEST')
            dbcmd as SqliteCommand = SqliteCommand()
            dbcmd.Connection = dbcon
            dbcmd.CommandText = 'CREATE TABLE MONO_TEST ( ' + 'NID INT, ' + 'NDESC TEXT )'
            Debug.Log('execute command...')
            dbcmd.ExecuteNonQuery()
            Debug.Log('set and execute command to INSERT INTO MONO_TEST')
            dbcmd.CommandText = 'INSERT INTO MONO_TEST  ' + '(NID, NDESC )' + 'VALUES(5,\'Mono\')'
            dbcmd.ExecuteNonQuery()
            Debug.Log('set command to SELECT FROM MONO_TEST')
            dbcmd.CommandText = 'SELECT * FROM MONO_TEST'
            reader as SqliteDataReader
            Debug.Log('execute reader...')
            reader = dbcmd.ExecuteReader()
            Debug.Log('read and display data...')
            while reader.Read():
                Debug.Log('Data 1: ' + reader[0].ToString())
                Debug.Log('Data 2: ' + reader[1].ToString())
    
            Debug.Log('read and display data using DataAdapter...')
            adapter as SqliteDataAdapter = SqliteDataAdapter('SELECT * FROM MONO_TEST', connectionString)
            dataset as DataSet = DataSet()
            adapter.Fill(dataset)
            for myTable as DataTable in dataset.Tables:
                for myRow as DataRow in myTable.Rows:
                    for myColumn as DataColumn in myTable.Columns:
                        Debug.Log(myRow[myColumn])
    
            Debug.Log('clean up...')
            dataset.Dispose()
            adapter.Dispose()
            reader.Close()
            dbcmd.Dispose()
            dbcon.Close()
            Debug.Log('Done.')
    

    しかし、

    adapter.Fill(dataset)
    

    の行で怒られた!!

    エラーは↓

    EntryPointNotFoundException: sqlite3_column_origin_name
    Mono.Data.Sqlite.SQLite3.ColumnOriginalName (Mono.Data.Sqlite.SqliteStatement stmt, Int32 index)
    Mono.Data.Sqlite.SqliteDataReader.GetSchemaTable (Boolean wantUniqueInfo, Boolean wantDefaultValue)
    Mono.Data.Sqlite.SqliteDataReader.GetSchemaTable ()
    System.Data.Common.DataAdapter.BuildSchema (IDataReader reader, System.Data.DataTable table, SchemaType schemaType, MissingSchemaAction missingSchAction, MissingMappingAction missingMapAction, System.Data.Common.DataTableMappingCollection dtMapping)
    System.Data.Common.DataAdapter.BuildSchema (IDataReader reader, System.Data.DataTable table, SchemaType schemaType)
    System.Data.Common.DataAdapter.FillTable (System.Data.DataTable dataTable, IDataReader dataReader, Int32 startRecord, Int32 maxRecords, System.Int32& counter)
    System.Data.Common.DataAdapter.FillInternal (System.Data.DataSet dataSet, System.String srcTable, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
    System.Data.Common.DataAdapter.Fill (System.Data.DataSet dataSet, System.String srcTable, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
    System.Data.Common.DbDataAdapter.Fill (System.Data.DataSet dataSet, Int32 startRecord, Int32 maxRecords, System.String srcTable, IDbCommand command, CommandBehavior behavior)
    System.Data.Common.DbDataAdapter.Fill (System.Data.DataSet dataSet)
    SqliteTest.Awake () (at Assets/SqliteTest.boo:40)

    ちなみに、DBファイル自体は「SqliteTest.db」ファイルがプロジェクトディレクトリ直下に作られてます。
    ※Unityエディタ上の「Project」直下では無いですよ!



    ちなみに2度実行すると

    dbcmd.CommandText = 'CREATE TABLE MONO_TEST ( ' + 'NID INT, ' + 'NDESC TEXT )'

    の行で、MONO_TESTテーブルを生成しているため、すでにMONO_TESTテーブルが有るよと怒られるので注意!
    ※僕は面倒なので「SqliteTest.db」ファイルを削除しましたw

    SqliteException: SQLite error
    table MONO_TEST already exists


    先ほどのエラーの話に戻ります、
    「adapter.Fill(dataset)」の行でエラーになるからコメントアウトしてみたら、

            for myTable as DataTable in dataset.Tables:
                for myRow as DataRow in myTable.Rows:
                    for myColumn as DataColumn in myTable.Columns:
                        Debug.Log(myRow[myColumn])
    

    が表示できませんでした、「dataset」が空だからあたりまえか・・。
    解決策が分かれば、Advent Calenderに書きます!
    NHibernate連携も書きたいですね!

    では、次回の方!僕かしら?