@@ -45,8 +45,7 @@ module.exports.series = async (query, fromMs, toMs) => {
45
45
const fromS = Math . floor ( fromMs / 1000 )
46
46
const toS = Math . floor ( toMs / 1000 )
47
47
const matchers = prometheus . pqlMatchers ( query )
48
- const conds = getMatchersIdxCond ( matchers [ 0 ] )
49
- const idx = getIdxSubquery ( conds , fromMs , toMs )
48
+ const idx = getIdxSubqueryV2 ( matchers [ 0 ] , fromMs , toMs )
50
49
const withIdx = new Sql . With ( 'idx' , idx , ! ! clusterName )
51
50
const req = ( new Sql . Select ( ) )
52
51
. with ( withIdx )
@@ -72,51 +71,90 @@ module.exports.series = async (query, fromMs, toMs) => {
72
71
}
73
72
}
74
73
74
+ /**
75
+ *
76
+ * @param matcher {[string]}
77
+ */
78
+ const getMatcherIdxCond = ( matcher ) => {
79
+ const res = [
80
+ Sql . Eq ( 'key' , matcher [ 0 ] )
81
+ ]
82
+ switch ( matcher [ 1 ] ) {
83
+ case '=' :
84
+ res . push ( Sql . Eq ( 'val' , matcher [ 2 ] ) )
85
+ break
86
+ case '!=' :
87
+ res . push ( Sql . Ne ( 'val' , matcher [ 2 ] ) )
88
+ break
89
+ case '=~' :
90
+ res . push ( Sql . Eq ( new Sql . Raw ( `match(val, ${ Sql . quoteVal ( matcher [ 2 ] ) } )` ) , 1 ) )
91
+ break
92
+ case '!~' :
93
+ res . push ( Sql . Ne ( new Sql . Raw ( `match(val, ${ Sql . quoteVal ( matcher [ 2 ] ) } )` ) , 1 ) )
94
+ }
95
+ return res
96
+ }
97
+
75
98
/**
76
99
*
77
100
* @param matchers {[[string]]}
78
101
*/
79
102
const getMatchersIdxCond = ( matchers ) => {
80
- const matchesCond = [ ]
81
- for ( const matcher of matchers ) {
82
- const _matcher = [
83
- Sql . Eq ( 'key' , matcher [ 0 ] )
84
- ]
85
- switch ( matcher [ 1 ] ) {
86
- case '=' :
87
- _matcher . push ( Sql . Eq ( 'val' , matcher [ 2 ] ) )
88
- break
89
- case '!=' :
90
- _matcher . push ( Sql . Ne ( 'val' , matcher [ 2 ] ) )
91
- break
92
- case '=~' :
93
- _matcher . push ( Sql . Eq ( new Sql . Raw ( `match(val, ${ Sql . quoteVal ( matcher [ 2 ] ) } )` ) , 1 ) )
94
- break
95
- case '!~' :
96
- _matcher . push ( Sql . Ne ( new Sql . Raw ( `match(val, ${ Sql . quoteVal ( matcher [ 2 ] ) } )` ) , 1 ) )
97
- }
98
- matchesCond . push ( Sql . And ( ..._matcher ) )
99
- }
100
- return matchesCond
103
+ return matchers . map ( matcher => Sql . And ( ...getMatcherIdxCond ( matcher ) ) )
101
104
}
102
105
103
- const getIdxSubquery = ( conds , fromMs , toMs ) => {
106
+ const getIdxSubqueryV2 = ( matchers , fromMs , toMs ) => {
104
107
const fromS = Math . floor ( fromMs / 1000 )
105
108
const toS = Math . floor ( toMs / 1000 )
106
- return ( new Sql . Select ( ) )
107
- . select ( 'fingerprint' )
108
- . from ( [ DATABASE_NAME ( ) + '.time_series_gin' , 'time_series_gin' ] )
109
- . where ( Sql . And (
110
- Sql . Or ( ...conds ) ,
111
- Sql . Gte ( 'date' , new Sql . Raw ( `toDate(fromUnixTimestamp(${ fromS } ))` ) ) ,
112
- Sql . Lte ( 'date' , new Sql . Raw ( `toDate(fromUnixTimestamp(${ toS } ))` ) ) ,
113
- new Sql . In ( 'type' , 'in' , [ bothType , metricType ] ) ) )
114
- . having (
115
- Sql . Eq (
116
- new Sql . Raw ( 'groupBitOr(' + conds . map (
117
- ( m , i ) => new Sql . Raw ( `bitShiftLeft((${ m } )::UInt64, ${ i } )` )
118
- ) . join ( '+' ) + ')' ) , ( 1 << conds . length ) - 1 )
119
- ) . groupBy ( 'fingerprint' )
109
+ const nonEmptyMatchers = matchers . filter ( m => m [ 2 ] !== '' )
110
+ const emptyMatchers = matchers . filter ( m => m [ 2 ] === '' && [ '=' , '!=' ] . includes ( m [ 1 ] ) )
111
+ let req = null
112
+ if ( nonEmptyMatchers . length ) {
113
+ const nonEmptyConds = getMatchersIdxCond ( nonEmptyMatchers )
114
+ req = ( new Sql . Select ( ) )
115
+ . select ( 'fingerprint' )
116
+ . from ( [ DATABASE_NAME ( ) + '.time_series_gin' , 'time_series_gin' ] )
117
+ . where ( Sql . And (
118
+ Sql . Or ( ...nonEmptyConds ) ,
119
+ Sql . Gte ( 'date' , new Sql . Raw ( `toDate(fromUnixTimestamp(${ fromS } ))` ) ) ,
120
+ Sql . Lte ( 'date' , new Sql . Raw ( `toDate(fromUnixTimestamp(${ toS } ))` ) ) ,
121
+ new Sql . In ( 'type' , 'in' , [ bothType , metricType ] ) ) )
122
+ . having (
123
+ Sql . Eq (
124
+ new Sql . Raw ( 'groupBitOr(' + nonEmptyConds . map (
125
+ ( m , i ) => new Sql . Raw ( `bitShiftLeft((${ m } )::UInt64, ${ i } )` )
126
+ ) . join ( '+' ) + ')' ) , ( 1 << nonEmptyConds . length ) - 1 )
127
+ ) . groupBy ( 'fingerprint' )
128
+ }
129
+ if ( emptyMatchers . length ) {
130
+ const emptyConds = emptyMatchers . map ( m => {
131
+ const visitParamHas = new Sql . Raw ( '' )
132
+ visitParamHas . toString = function ( ) {
133
+ return `visitParamHas(labels, ${ Sql . quoteVal ( m [ 0 ] ) } )`
134
+ }
135
+ switch ( m [ 1 ] ) {
136
+ case '=' :
137
+ return Sql . Eq ( visitParamHas , new Sql . Raw ( '0' ) )
138
+ case '!=' :
139
+ return Sql . Ne ( visitParamHas , new Sql . Raw ( '1' ) )
140
+ default :
141
+ return null
142
+ }
143
+ } ) . filter ( m => ! ! m )
144
+ const emptyReq = ( new Sql . Select ( ) )
145
+ . select ( 'fingerprint' )
146
+ . from ( `time_series${ _dist } ` )
147
+ . where ( Sql . And ( ...emptyConds ) )
148
+ if ( nonEmptyMatchers . length ) {
149
+ const withNonEmptyIdx = new Sql . With ( 'nonEmptyIdx' , req , ! ! clusterName )
150
+ emptyReq . with ( withNonEmptyIdx )
151
+ . where (
152
+ new Sql . In ( 'fingerprint' , 'in' , new Sql . WithReference ( withNonEmptyIdx ) )
153
+ )
154
+ }
155
+ req = emptyReq
156
+ }
157
+ return req
120
158
}
121
159
122
160
module . exports . getData = async ( matchers , fromMs , toMs , subqueries ) => {
@@ -128,8 +166,7 @@ module.exports.getData = async (matchers, fromMs, toMs, subqueries) => {
128
166
null , db , { responseType : 'arraybuffer' } )
129
167
return new Uint8Array ( data . data )
130
168
}
131
- const matches = getMatchersIdxCond ( matchers )
132
- const idx = getIdxSubquery ( matches , fromMs , toMs )
169
+ const idx = getIdxSubqueryV2 ( matchers , fromMs , toMs )
133
170
const withIdx = new Sql . With ( 'idx' , idx , ! ! clusterName )
134
171
const timeSeries = ( new Sql . Select ( ) )
135
172
. select (
@@ -138,7 +175,7 @@ module.exports.getData = async (matchers, fromMs, toMs, subqueries) => {
138
175
) . from ( DATABASE_NAME ( ) + '.time_series' )
139
176
. where ( Sql . And (
140
177
new Sql . In ( 'fingerprint' , 'in' , new Sql . WithReference ( withIdx ) ) ,
141
- new Sql . In ( 'type' , 'in' , [ bothType , metricType ] ) ) )
178
+ new Sql . In ( 'type' , 'in' , [ bothType , metricType ] ) ) )
142
179
const withTimeSeries = new Sql . With ( 'timeSeries' , timeSeries , ! ! clusterName )
143
180
const raw = ( new Sql . Select ( ) )
144
181
. with ( withIdx )
0 commit comments