Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hacking PostgreSQL to Gain SQL Parsing Superpowers

Hacking PostgreSQL to Gain SQL Parsing Superpowers

Talk at Microsoft Reactor / Open Source Show And Tell

https://github.com/lfittl/pg_query

Lukas Fittl

April 22, 2016
Tweet

More Decks by Lukas Fittl

Other Decks in Programming

Transcript

  1. @LukasFittl EXPLAIN  (PARSETREE  TRUE)      SELECT  *  FROM  x

     WHERE  y  =  1 Unfortunately doesn’t exist.
  2. @LukasFittl tree = raw_parser(query_str); str = nodeToString(tree); printf(str); ({SELECT  :distinctClause

     <>                    :intoClause  <>                    :targetList  (                        {RESTARGET                            :name  <>                            :indirection  <>                            :val  {COLUMNREF  :fields  ({A_STAR})  :location  7}                            :location  7})                    :fromClause  (                        {RANGEVAR                            :schemaname  <>                            :relname  x                            :inhOpt  2                            :relpersistence  p                            :alias  <>                            :location  14})                    :whereClause  {AEXPR    :name  (“=")                        :lexpr  {COLUMNREF  :fields  ("y")  :location  22}                        :rexpr  {PARAMREF  :number  0  :location  26}                        :location  24}                    :groupClause  <>                    :havingClause  <>                    :windowClause  <>  
  3. @LukasFittl PgQuery._raw_parse( “SELECT * FROM x WHERE y = 1”)

    ({SELECT  :distinctClause  <>                    :intoClause  <>                    :targetList  (                        {RESTARGET                            :name  <>                            :indirection  <>                            :val  {COLUMNREF  :fields  ({A_STAR})  :location  7}                            :location  7})                    :fromClause  (                        {RANGEVAR                            :schemaname  <>                            :relname  x                            :inhOpt  2                            :relpersistence  p                            :alias  <>                            :location  14})                    :whereClause  {AEXPR    :name  (“=")                        :lexpr  {COLUMNREF  :fields  ("y")  :location  22}                        :rexpr  {PARAMREF  :number  0  :location  26}                        :location  24}                    :groupClause  <>                    :havingClause  <>                    :windowClause  <>                    :valuesLists  <>  
  4. @LukasFittl PgQuery._raw_parse( “SELECT * FROM x WHERE y = 1”)

    [{     "SelectStmt":  {       "targetList":  [{         "ResTarget":  {           "val":  {             "ColumnRef":  {               "fields":  [{                 "A_Star":  {}               }],               "location":  7             }           },           "location":  7         }       }],       "fromClause":  [{         "RangeVar":  {           "relname":  "x",           "inhOpt":  2,           "relpersistence":  "p",           "location":  14         }       }],       "whereClause":  {         "A_Expr":  {  
  5. @LukasFittl q  =  PgQuery.parse(‘SELECT  *  FROM  the_table’)   =>  

    [{"SelectStmt"  =>  {      "targetList"  =>[…],      "fromClause"  =>  [{          "RangeVar"  =>  {       "relname"  =>  “the_table",              …          }      }]   }}]   q.tree[0][‘SelectStmt']['fromClause'][0][‘RangeVar'] ['relname']  =  ‘the_other_table'   q.deparse   =>  "SELECT  *  FROM  \"the_other_table\"
  6. @LukasFittl pg_query_go package  main   import  (      "github.com/lfittl/pg_query_go"

      )   func  main()  {      tree,  err  :=  pg_query.Parse("SELECT  1")      if  err  !=  nil  {          panic(err);      }      …   }
  7. @LukasFittl pg_query.ParsetreeList{          Statements:  []nodes.Node{    

             nodes.SelectStmt{                  TargetList:  []nodes.Node{                      nodes.ResTarget{                          Val:  nodes.A_Const{                              Type:  "integer",                              Val:  nodes.Value{                                  Type:  nodes.T_Integer,                                  Ival:  1,                              },                              Location:  7,                          },                          Location:  7,                      },                  },              },          }, tree  :=  pg_query.Parse(“SELECT  1")