Greenplum获取一个SQL结果的字段名

来源:互联网 发布:cydia安装软件路径 编辑:程序博客网 时间:2024/05/21 20:34

 在Greenplum中,对于任意一个SQL,我们想获取这个SQL执行后的字段名是比较难的。

比方说在写一个通用工具的时候,使用copy命令将一个SQL导出成文本,但是每个字段的名称导出的文本中却没有,如果使用自己解析SQL的话就太复杂了

如果我们想取得这些字段名的话,不真正执行sql,因为在生成执行计划的时候已经,我知道的有以下几种方法:

1.使用JDBC,prepareStatement先生成执行计划,然后获取字段名:

             PreparedStatement pstmt = conn.prepareStatement("select * from gp_segment_configuration a");             ResultSetMetaData metaData=pstmt.getMetaData();             for(int i=1;i<=metaData.getColumnCount();i++){              System.out.println(metaData.getColumnName(i)+" \t\t :"+metaData.getColumnTypeName(i));             }

ps:不止是JDBC,其他的客户端接口估计都会有这种接口将字段给取出来。看了jdbc的源码,在获取metaData信息的时候,是直接跟数据库交互,然后将这些信息接收过来的。对于其他的,应该都是有定义好的接口的,这个需要自己去挖掘。


2.explain 如果加上verbose会将整个解析后的语法数打印出来。如下:

aligputf8=# explain verbose select * from cxfa;                              QUERY PLAN                           ----------------------------------------------------------------    {MOTION     :motionID 1     :motionType 1     :sendToSecondary false     :sendSorted false     :numInputSegs 3     :inputSegIdx <>     :numHashSegs 0     :hashSegIdx     :hashExpr <>     :hashDataTypes <>     :numOutputSegs 1     :outputSegIdx -1     :numSortCols 0     :sortColIdx     :sortOperators     :plan_node_id 1     :plan_parent_node_id -1     :startup_cost 0.00     :total_cost 0.00     :plan_rows 1     :plan_width 36 

其中最上层的targetlist就是 SQL要返回的字段列表。

   :targetlist (       {TARGETENTRY        :expr           {VAR           :varno 1           :varattno 1           :vartype 23           :vartypmod -1           :varlevelsup 0           :varnoold 1           :varoattno 1          }       :resno 1        :resname a        :ressortgroupref 0        :resorigtbl 28569230        :resorigcol 1        :resjunk false       }       {TARGETENTRY        :expr           {VAR           :varno 1           :varattno 2           :vartype 25           :vartypmod -1           :varlevelsup 0           :varnoold 1           :varoattno 2          }       :resno 2        :resname b        :ressortgroupref 0        :resorigtbl 28569230        :resorigcol 2        :resjunk false       }    )


这样,我们能不能利用这个写一个函数,来将这个字段名给取出来呢,如果直接解析这个语法树还是比较麻烦的。我们发现,字段名前面都有一个      :resname开头,我们可以遍历这个数,把“     :resname”开头的都给找出来,就是字段名了。

函数的代码如下:

CREATE or replace FUNCTION public.get_sql_column_name(sqlori text)      RETURNS setof textAS $    sql_ori=sqlori.strip().lower()    if not sql_ori.startswith('select'):        return ['SQL is not Select SQL,Please check!']    retext=[]    sql="explain verbose " + sql_ori    #plpy.info(sql)    rv = plpy.execute(sql)    for i in rv:        if i['QUERY PLAN'].startswith("      :resname"):            retext.append(i['QUERY PLAN'].replace("      :resname",''))    return retext;$ LANGUAGE plpythonu;


执行效果如下:

aligputf8=# select get_sql_column_name('select * from cxfa'); get_sql_column_name ---------------------  a   b (2 rows)Time: 32.037 msaligputf8=# select get_sql_column_name(pg_get_viewdef('pg_partitions'));    get_sql_column_name     ----------------------------  schemaname   tablename   partitionschemaname   partitiontablename   partitionname   parentpartitiontablename   parentpartitionname   partitiontype   partitionlevel   partitionrank   partitionposition   partitionlistvalues   partitionrangestart   partitionstartinclusive   partitionrangeend   partitionendinclusive   partitioneveryclause   partitionisdefault   partitionboundary (19 rows)Time: 44.404 ms


 

 

  

原创粉丝点击