package Ġcom . github . s uk h inin . prometheus . click house . reader . query Ċ Ċ import Ġcom . github . s uk h inin . prometheus . click house . reader . config . Query Config Ċ import Ġcom . github . s uk h inin . prometheus . click house . reader . data . Label Matcher Ċ import Ġcom . github . s uk h inin . prometheus . click house . reader . data . Query Ċ Ċ class ĠParameter ized Statement Builder ( private Ġval Ġconfig : ĠQuery Config ) Ġ{ ĊĠĠĠ Ġfun Ġget For Query ( query : ĠQuery ): ĠParameter ized Statement Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġselect Statement Ġ= Ġbuild Data Select ing Statement ( query ) ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( query . hints . step _ ms Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrap With Grouping Query ( select Statement , Ġquery ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrap With Simple Query ( select Statement ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġbuild Data Select ing Statement ( query : ĠQuery ): ĠParameter ized Statement Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġval Ġparameters Ġ= ĠArrayList < String >() ĊĊĠĠĠĠĠĠĠ Ġbuilder . append (" SELECT Ġ* Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" FROM Ġ${ config . database }.${ config . table } Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" WHERE Ġtimestamp Ġ>= Ġ${ query . start _ timestamp _ ms Ġ/ Ġ 1 0 0 0 } Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" AND Ġtimestamp Ġ<= Ġ${ query . end _ timestamp _ ms Ġ/ Ġ 1 0 0 0 } Ġ") ĊĠĠĠĠĠĠĠ Ġfor Ġ( matcher Ġin Ġquery . matchers ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( expr , Ġparams ) Ġ= Ġrender Filter ( matcher ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append (" AND Ġ($ expr ) Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparameters . addAll ( params ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠParameter ized Statement ( builder . toString (), Ġparameters ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwrap With Simple Query ( stmt : ĠParameter ized Statement ): ĠParameter ized Statement Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġval Ġextracted Tags Ġ= Ġconfig . extract Tags ĊĠĠĠĠĠĠĠ Ġval Ġextracted Columns Ġ= Ġif Ġ( extract ed Tags . isEmpty ()) Ġ"" Ġelse Ġextracted Tags . join ToString (", Ġ", Ġ", Ġ", Ġ" Ġ") ĊĊĠĠĠĠĠĠĠ Ġbuilder . append (" SELECT Ġmetric , Ġvalue Ġas Ġvalue , Ġtags . name , Ġtags . value , Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" to Unix Timestamp ( timestamp ) Ġ* Ġ 1 0 0 0 ĠAS Ġt Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append ( extract ed Columns ) ĊĠĠĠĠĠĠĠ Ġbuilder . append (" FROM Ġ( Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append ( stmt . body ) ĊĠĠĠĠĠĠĠ Ġbuilder . append (" ) Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" ORDER ĠBY Ġt ĠASC Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" LIMIT Ġ${ config . limit Rows } Ġ") ĊĊĠĠĠĠĠĠĠ Ġreturn ĠParameter ized Statement ( builder . toString (), Ġstmt . params ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwrap With Grouping Query ( stmt : ĠParameter ized Statement , Ġquery : ĠQuery ): ĠParameter ized Statement Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġval Ġstep Ġ= Ġquery . hints . step _ ms ĊĠĠĠĠĠĠĠ Ġval Ġextracted Tags Ġ= Ġconfig . extract Tags ĊĠĠĠĠĠĠĠ Ġval Ġextracted Columns Ġ= Ġif Ġ( extract ed Tags . isEmpty ()) Ġ"" Ġelse Ġextracted Tags . join ToString (", Ġ", Ġ", Ġ", Ġ" Ġ") ĊĊĠĠĠĠĠĠĠ Ġbuilder . append (" SELECT Ġmetric , ĠMAX ( value ) Ġas Ġvalue , Ġtags . name , Ġtags . value , Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" int Div ( to Unix Timestamp ( timestamp ) Ġ* Ġ 1 0 0 0 , Ġ$ step ) Ġ* Ġ$ step ĠAS Ġt Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append ( extract ed Columns ) ĊĠĠĠĠĠĠĠ Ġbuilder . append (" FROM Ġ( Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append ( stmt . body ) ĊĠĠĠĠĠĠĠ Ġbuilder . append (" ) Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" GROUP ĠBY Ġmetric , Ġtags . name , Ġtags . value , Ġt Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append ( extract ed Columns ) ĊĠĠĠĠĠĠĠ Ġbuilder . append (" ORDER ĠBY Ġt ĠASC Ġ") ĊĠĠĠĠĠĠĠ Ġbuilder . append (" LIMIT Ġ${ config . limit Rows } Ġ") ĊĊĠĠĠĠĠĠĠ Ġreturn ĠParameter ized Statement ( builder . toString (), Ġstmt . params ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrender Filter ( matcher : ĠLabel Matcher ): ĠPair < String , ĠList < String >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( matcher . type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLabel Matcher . MATCH _ TYPE _ EQ Ġ-> Ġrender Equality Filter ( matcher . name , Ġmatcher . value , Ġ"=" ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLabel Matcher . MATCH _ TYPE _ N EQ Ġ-> Ġrender Equality Filter ( matcher . name , Ġmatcher . value , Ġ"! =") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLabel Matcher . MATCH _ TYPE _ RE Ġ-> Ġrender Regex Filter ( matcher . name , Ġmatcher . value , Ġ"=", Ġ" LIKE ", Ġ" OR ") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLabel Matcher . MATCH _ TYPE _ N RE Ġ-> Ġrender Regex Filter ( matcher . name , Ġmatcher . value , Ġ"! =", Ġ" NOT ĠLIKE ", Ġ" AND ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠRuntimeException (" Unknown Ġmatcher Ġtype : Ġ${ matcher . type }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrender Equality Filter ( name : ĠString , Ġvalue : ĠString , Ġop : ĠString ): ĠPair < String , ĠList < String >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( name ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"__ name __ " Ġ-> ĠPair (" metric Ġ$ op Ġ?", ĠlistOf ( value )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġconfig . extract Tags Ġ-> ĠPair ("$ name Ġ$ op Ġ?", ĠlistOf ( value )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠPair (" tags . value [ indexOf ( tags . name , Ġ? )] Ġ$ op Ġ?", ĠlistOf ( name , Ġvalue )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrender Regex Filter ( name : ĠString , Ġregex : ĠString , Ġeq Op : ĠString , Ġre Op : ĠString , Ġbool Op : ĠString ): ĠPair < String , ĠList < String >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfilters Ġ= Ġregex . split ('| '). map Ġ{ Ġexpr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( expr . contains (" .* ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrender Equality Filter ( name , Ġexpr . replace (" .* ", Ġ"% "), Ġre Op ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrender Equality Filter ( name , Ġexpr , Ġeq Op ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġexpr Ġ= Ġfilters . join ToString (" Ġ$ bool Op Ġ") Ġ{ Ġ( expr , Ġ_) Ġ-> Ġexpr Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġparams Ġ= Ġfilters . map Ġ{ Ġ(_, Ġparams ) Ġ-> Ġparams Ġ}. flatten () ĊĠĠĠĠĠĠĠ Ġreturn ĠPair ( expr , Ġparams ) ĊĠĠĠ Ġ} Ċ } Ċ