シリーズ:パイソン+ ANTLR決意ハイブSQLデータ取得親族(C)

目標

第二シリーズ pushMsg出力のHiveParser.gの使用ではなく、AST(抽象構文木抽象構文木)、ない実用的でありませんでした。ASTを得るために加えて、第二の端部には、次の3つの実用的な問題に対処する必要があります

  1. トークン、ハイブのとでは微妙な問題許容SELECT選択
  2. あるセミコロンの問題は、複数のSQL文を含む文字列の状況を解決できなければなりません
  3. 受け入れるために、このハイブに、選択し、挿入に似たルールを、解析するが、HiveParser.g文書は状況を定義していません。

Benpianそれは問題のASTを解決する方法をクリアにし、その後、解決実用的にインサートを選択

取得AST

前のコードでは、実際に最後の仕上げになってきました。入口の分析としてparser.statement()、この方法の値が返され、デフォルトで自動的に生成されたクラスを生成した戻り型である、HiveParser.statement_return、このクラスに隠されたASTは、このクラスgetTree()は、タイプをCommonTreeを与えることができこれは、オブジェクト。python以下のコードで、このコードを取得CommonTree

import jnius_config
jnius_config.set_classpath('./','./grammar/hive110/antlr-3.4-complete.jar')
import jnius

StringStream = jnius.autoclass('org.antlr.runtime.ANTLRStringStream')
Lexer  = jnius.autoclass('grammar.hive110.HiveLexer')
Parser  = jnius.autoclass('grammar.hive110.HiveParser')
TokenStream  = jnius.autoclass('org.antlr.runtime.CommonTokenStream')

sql_string = (
    "SELECT DISTINCT a1.c1 AS c2,\n"
    " a1.c3 AS c4,\n"
    " '' c5\n"
    " FROM db2.tb2 AS a1 ;\n"
    )

sqlstream = StringStream(sql_string)
inst = Lexer(sqlstream)
ts = TokenStream(inst)
parser = Parser(ts)
ret  = parser.statements()
treeroot = ret.getTree()

AST生成された構成

コンフィギュレーションのオプションを持っているHiveParser.gが必要、ASTのためのANTLR生成されたコードの出力、ここでは特定の場所のオプションので、

options
{
tokenVocab=HiveLexer;
output=AST;
ASTLabelType=CommonTree;
backtrack=false;
k=3;
}

出力構造トラバーサルおよびAST

このクラスCommonTreeかどうか確認するにはASTトラバーサル必要APIドキュメントを

各ノードは、トークン自体トークンフィールドのアクセス・ノードを表しており、このクラスのCommonTree ASTのインスタンスであり、このような方法はのgetTypeのgetText缶子属性を持って、直接アクセストークン上のノードは、子どもたちのフィールドにアクセスすることができますそれは、メソッドGetChildrenメソッドによって得られ、また、対応する親のgetParentすることができます。これらを使用すると、全体のASTは自由に木を歩くことができます。

ここで、深さトラバーサル、および印刷されたテキストと数値コードが各ノードに対応するように、ルートから開始して、単純な再帰的なコードです。目の前に実行される追加のコードの後

def walktree(node,depth = 0):
    print("%s%s=%s" % ("  "*depth,node.getText(),node.getType()))
    children = node.children
    if not children:
        return
    ch_size = children.size()
    for i in range(ch_size):
        ch =children.get(i)
        walktree(ch,depth + 1)

walktree(treeroot,0)

子供のJava型は、反復は、Pythonで直接のために訪問したインデックスを反復処理するためのコードを実行することはできません、java.util.Listにあります。上記のコードが出力されます

None=0
  TOK_QUERY=777
    TOK_FROM=681
      TOK_TABREF=864
        TOK_TABNAME=863
          db2=26
          tb2=26
        a1=26
    TOK_INSERT=707
      TOK_DESTINATION=660
        TOK_TAB=835
          TOK_TABNAME=863
            db1=26
            tb1=26
      TOK_SELECTDI=792
        TOK_SELEXPR=793
          .=17
            TOK_TABLE_OR_COL=860
              a1=26
            c1=26
          c2=26
        TOK_SELEXPR=793
          .=17
            TOK_TABLE_OR_COL=860
              a1=26
            c3=26
          c4=26
        TOK_SELEXPR=793
          ''=302
          c5=26
  ;=299
  <EOF>=-1

あなたは私たちがテーブル名に興味がある、見ることができ、列名がタイプに対応した彼らの数の当社の出力内容に登場リーフノードの下、として使用されてきたが、識別子26です。
ASTの根はなしになっていたのpythonに変換nullは、トークンで、数値型は0で固定します。
クエリの印として、デジタルタイプは、TOK_QUERY 777です。
この隙間から私たちの究極の目標は、はっきりと見えます。

実用的な挿入を、選択し解決

インサートの選択をするためのコードをテストする1つの

INSERT OVERWRITE db1.tb1 SELECT DISTINCT a1.c1 c2, a1.c3 c4, '' c5 FROM db2.tb2 a1;

ポスト.GファイルinsertClauseはselectClauseを表示されない理由を理解しようとしたときに大きなを書く時間は、TABLEキーワードを逃し、文言は、実際に間違って見つけることができませんでした正しい言葉遣いです

INSERT OVERWRITE TABLE db1.tb1 SELECT DISTINCT a1.c1 c2, a1.c3 c4, '' c5 FROM db2.tb2 a1;

もちろん、時間の文書は、.G白セミコロンしなかった読んで、敏感な現実的な問題を解決し、次への具体的なソリューションを提供しています。

公開された18元の記事 ウォンの賞賛0 ビュー661

おすすめ

転載: blog.csdn.net/bigdataolddriver/article/details/103935723