本文共 3361 字,大约阅读时间需要 11 分钟。
在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
转载地址:http://heebi.baihongyu.com/