1919import net .sf .jsqlparser .statement .select .Limit ;
2020import net .sf .jsqlparser .statement .select .OrderByElement ;
2121import org .apache .commons .collections .CollectionUtils ;
22+ import org .jetlinks .reactor .ql .exception .ReactorQLException ;
2223import org .jetlinks .reactor .ql .feature .ValueMapFeature ;
2324import org .jetlinks .reactor .ql .utils .CastUtils ;
2425import org .jetlinks .reactor .ql .utils .CompareUtils ;
@@ -229,8 +230,11 @@ private static Flux<ReactorQLRecord> limitSortRows(Flux<ReactorQLRecord> flux, l
229230 .index ()
230231 .handle ((Tuple2 <Long , ReactorQLRecord > tuple , SynchronousSink <ReactorQLRecord > sink ) -> {
231232 if (tuple .getT1 () >= maxRows ) {
232- sink .error (new UnsupportedOperationException ("order by rows exceeded setting["
233- + DefaultReactorQL .SETTING_ORDER_BY_MAX_ROWS + "]:" + maxRows ));
233+ sink .error (ReactorQLException .resourceLimit (
234+ "ORDER BY 输入行数超过 setting[" + DefaultReactorQL .SETTING_ORDER_BY_MAX_ROWS + "]: " + maxRows ,
235+ "为 ORDER BY 增加 LIMIT 以启用 Top-N 排序,或在可信场景下调大 orderBy.maxRows;无限流建议使用窗口排序。" ,
236+ "select * from test order by timestamp desc limit 100"
237+ ));
234238 } else {
235239 sink .next (tuple .getT2 ());
236240 }
@@ -242,11 +246,19 @@ private static Long topNSize(Long rowCount, Long offset) {
242246 return null ;
243247 }
244248 if (rowCount < 0 ) {
245- throw new UnsupportedOperationException ("invalid limit:" + rowCount );
249+ throw ReactorQLException .invalidArgument (
250+ "LIMIT 不能为负数: " + rowCount ,
251+ "使用非负整数 LIMIT;如果不需要返回结果,可使用 limit 0。" ,
252+ "select * from test order by timestamp desc limit 100"
253+ );
246254 }
247255 long skip = offset == null ? 0 : offset ;
248256 if (skip < 0 ) {
249- throw new UnsupportedOperationException ("invalid offset:" + skip );
257+ throw ReactorQLException .invalidArgument (
258+ "LIMIT offset 不能为负数: " + skip ,
259+ "使用非负整数 offset,或省略 offset。" ,
260+ "select * from test order by timestamp desc limit 10, 100"
261+ );
250262 }
251263 if (Long .MAX_VALUE - skip < rowCount ) {
252264 return Long .MAX_VALUE ;
@@ -270,8 +282,11 @@ private static Long limitValue(Limit limit, ReactorQLContext context, boolean ro
270282
271283 private static void assertSortRows (long rows , long maxRows ) {
272284 if (rows > maxRows || rows > Integer .MAX_VALUE ) {
273- throw new UnsupportedOperationException ("order by buffer size exceeded setting["
274- + DefaultReactorQL .SETTING_ORDER_BY_MAX_ROWS + "]:" + maxRows + ", actual:" + rows );
285+ throw ReactorQLException .resourceLimit (
286+ "ORDER BY 缓冲行数超过 setting[" + DefaultReactorQL .SETTING_ORDER_BY_MAX_ROWS + "]: " + maxRows + ", actual=" + rows ,
287+ "为 ORDER BY 增加 LIMIT,或在可信场景下调大 orderBy.maxRows;如果只需要局部有序,可设置 orderBy.windowSize。" ,
288+ "select * from test order by timestamp desc limit 100"
289+ );
275290 }
276291 }
277292
@@ -280,13 +295,27 @@ private static long longSetting(ReactorQLMetadata metadata,
280295 long defaultValue ,
281296 long hardMax ,
282297 boolean allowZero ) {
283- long value = metadata
284- .getSetting (key )
285- .map (CastUtils ::castNumber )
286- .map (Number ::longValue )
287- .orElse (defaultValue );
298+ long value ;
299+ try {
300+ value = metadata
301+ .getSetting (key )
302+ .map (CastUtils ::castNumber )
303+ .map (Number ::longValue )
304+ .orElse (defaultValue );
305+ } catch (RuntimeException e ) {
306+ throw ReactorQLException .builder (ReactorQLException .INVALID_ARGUMENT )
307+ .reason ("ORDER BY setting[" + key + "] 必须是数字" )
308+ .suggestion ("确认 setting 在允许范围内;orderBy.maxRows 必须为正数,orderBy.windowSize 可为 0 或正数。" )
309+ .example ("orderBy.maxRows=10000 或 orderBy.windowSize=1000" )
310+ .cause (e )
311+ .build ();
312+ }
288313 if ((allowZero ? value < 0 : value <= 0 ) || value > hardMax ) {
289- throw new UnsupportedOperationException ("invalid setting[" + key + "]:" + value );
314+ throw ReactorQLException .invalidArgument (
315+ "非法 ORDER BY setting[" + key + "]: " + value + ", hardMax=" + hardMax ,
316+ "确认 setting 在允许范围内;orderBy.maxRows 必须为正数,orderBy.windowSize 可为 0 或正数。" ,
317+ "orderBy.maxRows=10000 或 orderBy.windowSize=1000"
318+ );
290319 }
291320 return value ;
292321 }
0 commit comments