ほんの、触りだけです。
前にCQLを使っていて、すごい低レイヤのコードを書いていたわけですが、なんかJDBCドライバが存在するっぽいです。
cassandra-jdbc
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/
というかですね、ネットに転がってるサンプルとかを見てると普通にJDBCドライバがorg.apache.cassandra.cql.jdbcパッケージにいたようなのですが、最近のCassandraではいなくなっています。
何かあったのかなぁ…。
んで、前述のcassandra-jdbcを軽く触ってみました。
Maven Central Repositoryにも登録されています。
まずは普通にJDBCで。
@GrabConfig(systemClassLoader = true) @Grab('org.apache.cassandra:cassandra-all:1.2.4') @Grab('org.apache-extras.cassandra-jdbc:cassandra-jdbc:1.2.1') import java.sql.DriverManager Class.forName('org.apache.cassandra.cql.jdbc.CassandraDriver') def conn = DriverManager.getConnection('jdbc:cassandra://localhost:9160/cqldemo') try { def ps = conn.prepareStatement('SELECT isbn13, price, publish_date, title FROM books WHERE isbn13 = ?') ps.setString(1, '978-4798128436') def rs = ps.executeQuery() while (rs.next()) { def isbn13 = rs.getString('isbn13') // rs.getString(1)とかでもOK def price = rs.getInt('price') def publishDate = rs.getTimestamp('publish_date') def title = rs.getString('title') println("isbn13 = $isbn13, price = $price, publishDate = $publishDate, title = $title") } } finally { conn.close() }
対象のテーブルとデータはこんな感じです。cqlshで確認しています。
cqlsh:cqldemo> DESCRIBE TABLE books; CREATE TABLE books ( isbn13 text PRIMARY KEY, price int, publish_date timestamp, title text ) WITH bloom_filter_fp_chance=0.010000 AND caching='KEYS_ONLY' AND comment='' AND dclocal_read_repair_chance=0.000000 AND gc_grace_seconds=864000 AND read_repair_chance=0.100000 AND replicate_on_write='true' AND populate_io_cache_on_flush='false' AND compaction={'class': 'SizeTieredCompactionStrategy'} AND compression={'sstable_compression': 'SnappyCompressor'}; cqlsh:cqldemo> SELECT * FROM books; isbn13 | price | publish_date | title ----------------+-------+--------------------------+----------------------------------------- 978-4798128436 | 3360 | 2013-01-16 00:00:00+0900 | Cassandra実用システムインテグレーション 978-4873115290 | 3570 | 2011-12-24 00:00:00+0900 | Cassandra
JDBCのURLは、データベース名にあたる部分にはキースペースの名前を設定します。
def conn = DriverManager.getConnection('jdbc:cassandra://localhost:9160/cqldemo')
ポート番号は、Thriftで接続する際のものでOKなようです。なぜか、JDBCドライバのサイトだと9170になっていましたが…。
いきなりPreparedStatmentを使用してみましたが、とりあえず動作しました。
isbn13 = 978-4798128436, price = 3360, publishDate = 2013-01-16 00:00:00.0, title = Cassandra実用システムインテグレーション
ちなみに、WHERE句が使えるとはいえ、プライマリキー以外の項目をWHERE句に付けると怒られます。
cqlsh:cqldemo> SELECT * FROM books WHERE price > 3000; Bad Request: No indexed columns present in by-columns clause with Equal operator Perhaps you meant to use CQL 2? Try using the -2 option when starting cqlsh.
Thrift APIでセカンダリインデックスが必要だったように、こちらもインデックスを貼らなくちゃいけないということなんでしょうね。
で、せっかくなのでGroovyのJDBC拡張を使っても試してみました。
import groovy.sql.Sql Sql.withInstance('jdbc:cassandra://localhost:9160/cqldemo', 'org.apache.cassandra.cql.jdbc.CassandraDriver') { sql -> sql.eachRow('SELECT isbn13, price, publish_date, title FROM books', { println("row -> $it") })
これ、動くには動いたのですが
row -> [isbn13:978-4798128436, price:3360, publish_date:Wed Jan 16 00:00:00 JST 2013, title:Cassandra実用システムインテグレーション] row -> [isbn13:978-4873115290, price:3570, publish_date:Sat Dec 24 00:00:00 JST 2011, title:Cassandra]
PreparedStatementにすると、途端にコケます。
Sql.withInstance('jdbc:cassandra://localhost:9160/cqldemo', 'org.apache.cassandra.cql.jdbc.CassandraDriver') { sql -> try { sql.eachRow('SELECT isbn13, price, publish_date, title FROM books WHERE isbn13 = ?', ['978-4873115290'], { println("row -> $it") }) } catch (e) { e.printStackTrace() // 5 06, 2013 8:27:27 午後 groovy.sql.Sql eachRow // WARNING: Failed to execute: SELECT isbn13, price, publish_date, title FROM books WHERE isbn13 = ? because: the Cassandra implementation does not support this method // java.sql.SQLFeatureNotSupportedException: the Cassandra implementation does not support this method // at org.apache.cassandra.cql.jdbc.CassandraConnection.prepareStatement(CassandraConnection.java:365) // at groovy.sql.Sql$CreatePreparedStatementCommand.execute(Sql.java:3996) // at groovy.sql.Sql$CreatePreparedStatementCommand.execute(Sql.java:3978) // at groovy.sql.Sql.getAbstractStatement(Sql.java:3858) // at groovy.sql.Sql.getPreparedStatement(Sql.java:3873) // at groovy.sql.Sql.getPreparedStatement(Sql.java:3921) // at groovy.sql.Sql.eachRow(Sql.java:1241) // at groovy.sql.Sql.eachRow(Sql.java:1329) // at groovy.sql.Sql.eachRow(Sql.java:1383) } }
Connectionの実装で、以下のメソッドが未実装だからなようです…。
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
public PreparedStatement prepareStatement(String arg0, int arg1, int arg2) throws SQLException { throw new SQLFeatureNotSupportedException(NOT_SUPPORTED); }
とりあえず、触りだけでした。
そして、cassandra-jdbcはそもそもプロジェクト的にどういう位置付けなのでしょうか…?