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