N1QL: DMLのRETURNING句を調査しながらGo言語の基礎を学ぶ
15 Dec 2015 | Couchbase昨日のEmbulk Output Couchbase プラグインを Scala で書く by zaneliさん、に続く、Couchbase Advent Calendar、12/15分の記事です。先日の記事、N1QL INSERTからの続きです。ほぼGo言語の勉強メモになってしまった!
まえがき
先日、N1QLでインサートしたドキュメントのメタデータを返す方法が分からず、もやもやしていました。例えば、次のようなクエリを実行するとき、タイムスタンプやUUIDを使って動的にKeyを生成した場合は、Keyが返ってきてほしいものですよね。
実行結果は次のように返却されます:
Goの勉強がてらQueryエンジンのソースコードを追ってみました。
結果から言うと、インサートしたドキュメントの返却方法はわかりませんでした。今、クエリ実装チームに問い合わせているところですw
というわけで、今日の記事はほとんど私のGo言語勉強メモです。
KVにインサートした結果のあたりからソースコードリーディング開始
前にDMLの更新モードを調査した際に、QueryサービスからDataサービスにドキュメントをインサートする箇所は分かったので、今回はそこから始めました。
metaでインサートしたドキュメントのkeyをav.SetAttachmentしている。 avってなんだ?Attachmentってなんだ?
avはNewAnnotatedValueで作成されているもの。
Goでの変数代入、”=”と”:=”の違いは何?
:=
は関数の中で変数を宣言するのに使える。varとTypeを書く必要ない。
パッケージレベルで書く場合はvar使わないといけない。
ってなことさえ知らないGo初心者です。。
A Tour of Go分かりやすくていいっすね。
this.sendItem(av)
は?
そもそもthisって誰よ?
Goにはクラスは無いが、functionをstructに紐付けてmethodとして扱える。
先のコードではSendInsert structのflushBatchというmethodになる。
Goではthis
に特別な意味合いはない。Stackoverflow
StructとAnonymous FieldでOO指向的なクラス階層
んーっと、でもinsert_send.goにはsendItemってfunctionは実装されていないんだけど、どこにあるのか。。? 最近Githubの検索機能がうまく動かずツラい。ソースをgrepすると、
execution/base.goにありました。
これまた意味不明。SendInsertとbase structの関係は一体どこで紐付いてるのか?? おー、これがAnonymous fieldsってやつか。SendInsertにはbaseって無名フィールドが定義されていて、これがbaseを継承する感じになっているらしい。
Goroutine、channel、select
baseのsendItemが呼ばれることは分かったけどー。 まずはcaseの解読。おっと、switchじゃなくて、selectだ!
selectはcaseのいずれかがreadyになっているときにそれを実行する。Readyとはchannelにアイテムがあることだろう。channelはgoroutine間でデータをやりとりするもの。 A Tour of Go
channelはmake()しないと使えない。makeの引数は何ですか? 一つ目はchannelの型。 二つ目はbufferサイズ。ちなみに以下はdeadlockになる:
execution/base.goでは、以下のようにitemChannelとstopChannelを定義している:
base.goのrunConsumer()
を見ると、consumerにitemChannelから読み込んで渡している箇所がある。
ここまでくると、実行計画を見てconsumerを特定するのが良さげか?
N1QLの実行計画を元に動きを追ってみる
今回実行しているN1QLの実行計画を見ると、最後の方で、SendInsert -> InitialProject -> FinalProjectの流れとなっている。 普通に考えると、先ほどの文脈ではSendInsertのconsumerがInitialProjectになるはず。
execution/project_initial.goを見ると、ありました。processItem
!
ここに渡ってきたitemのattachmentにmetaがあるはず。
Termsってのは、実行計画にあったresult_termsだろう。 このあたりでMETA()が何やってるか見ておこう。
やはりattachmentのmetaを取得しているのだけど、なぜ返ってこないんだろう。
まとめ
結局RETURNING句でKeyを返す方法はわかりませんでしたが、Go言語の基本的なことが分かってきたので良しとします! Keyを返す方法が分かったら共有しまーす。