{"id":373929,"date":"2024-05-21T05:47:55","date_gmt":"2024-05-21T05:47:55","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=373929"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=373929","title":{"rendered":"<span>\u0418\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u043e ETL. \u041f\u0438\u0448\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a SQL \u043d\u0430 Spark [\u0447\u0430\u0441\u0442\u044c 6]<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/x1\/lx\/17\/x1lx17qduwak6ilxb0z0y6y0srg.png\" alt=\"\u041d\u042c\u042e!\" data-src=\"https:\/\/habrastorage.org\/webt\/x1\/lx\/17\/x1lx17qduwak6ilxb0z0y6y0srg.png\"\/><\/p>\n<p>  <\/p>\n<blockquote><p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u0435\u0440\u0438\u044f\u0445 (<a href=\"https:\/\/habr.com\/ru\/articles\/762862\/\">FAQ<\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/760504\/\"> 1 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/760778\/\"> 2 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761094\/\"> 3 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761328\/\"> 4 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761760\/\"> 5 <\/a>) \u043c\u044b \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 Java \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430 SQL \u043f\u043e\u0432\u0435\u0440\u0445 Spark RDD API, \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p><\/blockquote>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f SQL \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,<\/p>\n<p>  <\/p>\n<pre><code class=\"sql\">SELECT     MAX(score1, score2, score3, score4, score5) AS max_score,     MIN(score1, score2, score3, score4, score5) AS min_score,     MEDIAN(score1, score2, score3, score4, score5) AS median_score,     score1 + score2 + score3 + score4 + score5 AS score_sum FROM raw_scores INTO final_scores WHERE ABS(score1 + score2 + score3 + score4 + score5) > $score_margin;<\/code><\/pre>\n<p>  <\/p>\n<p>\u2014 \u0442\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>MAX<\/code>, <code>MIN<\/code> \u0438 <code>MEDIAN<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 \u043b\u044e\u0431\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u0438\u043f\u0430 <code>Double<\/code> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 <code>Double<\/code>, \u0430 <code>ABS<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0442\u0430\u043a\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435, \u043a\u0440\u043e\u043c\u0435 \u043e\u0431\u0449\u0435\u0439 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438, \u0432 \u043b\u044e\u0431\u043e\u043c \u0443\u0432\u0430\u0436\u0430\u044e\u0449\u0435\u043c \u0441\u0435\u0431\u044f \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0435 SQL \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0441 \u0434\u0430\u0442\u043e\u0439\/\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. \u0418\u0445 \u043c\u044b \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c. \u0412 classpath, \u0447\u0442\u043e\u0431\u044b \u0434\u0432\u0438\u0436\u043e\u043a \u043c\u043e\u0433 \u0438\u0445 \u043e\u0442\u0442\u0443\u0434\u0430 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c. \u0414\u043e \u043a\u0443\u0447\u0438, \u0435\u0449\u0451 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 <code>>=<\/code> \u0438\u043b\u0438 <code>LIKE<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b, \u043d\u043e \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u043e\u043c, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a\u0438\u043c\u0438 \u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p>\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u0432 \u0446\u0435\u043b\u043e\u043c \u0432\u044b\u0441\u043e\u043a\u0438\u0439. \u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u044e\u0442\u0441\u044f, \u0434\u0430 \u0438 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0449\u0435 \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0447\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435. \u041d\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u0435\u0451 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0433\u0447\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u0443\u0436\u0435 \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0438\u0441\u044c \u043f\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u043e \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u0438.<\/p>\n<\/div><\/div>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<blockquote><p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u00ab\u0444\u0443\u043d\u043a\u0446\u0438\u044f\u00bb \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c, \u0438 \u043a\u0430\u043a \u043e\u043d\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u00ab\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u00bb.<\/p><\/blockquote>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u2014 \u0434\u0430 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0441 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0437\u0430\u043f\u0438\u0441\u044c <code>sum(a, b)<\/code> \u044d\u0442\u043e \u0440\u043e\u0432\u043d\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 <code>a + b<\/code>. \u0418 \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c <code>+(a, b)<\/code>, \u0442\u043e \u0441\u0438\u043c\u0432\u043e\u043b <code>+<\/code> \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u043e\u043c \u0434\u043b\u044f \u0438\u043c\u0435\u043d\u0438 <code>sum<\/code>. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0435\u0449\u0451 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u0435\u0435: <code>~HEX<\/code> \u043f\u0440\u043e\u0442\u0438\u0432 <code>bitwise_negation(HEX)<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u0445 \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u043e \u0438 \u0442\u043e\u0436\u0435, \u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e. \u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0443\u0440\u043e\u0432\u043d\u044f \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0438, \u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  <\/p>\n<p>\u0410 \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0435\u0441\u0442\u044c \u043b\u0435\u043a\u0441\u0435\u0440\/\u043f\u0430\u0440\u0441\u0435\u0440, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 ANTLR, \u0430 \u0432 \u043d\u0451\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">expression  : ( is_op | between_op | in_op | comparison_op | var_name | property_name | L_NUMERIC | L_STRING | S_NULL | S_TRUE | S_FALSE | S_OPEN_PAR | S_CLOSE_PAR | expression_op | digest_op | random_op | bool_op | default_op )+ ;<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043d\u0430\u043c, \u0447\u0442\u043e \u00ab\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u00bb \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u043d\u0435\u043a\u0438\u0439 \u00ab\u0441\u0443\u043f\u00bb \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445:<br \/>  \u2022 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0438 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u044b,<br \/>  \u2022 \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0434\u043b\u044f \u0431\u0443\u043b\u0435\u0439 \u0438 \u043d\u0443\u043b\u0435\u0439,<br \/>  \u2022 \u0438\u043c\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0437\u0430\u043f\u0438\u0441\u0435\u0439,<br \/>  \u2022 \u0446\u0435\u043b\u0430\u044f \u043a\u0443\u0447\u0430 \u043f\u043e\u0434\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u044f\u043a\u0438\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u0433\u0440\u0443\u043f\u043f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0445 \u0432 \u0441\u0435\u0431\u044f SQL-\u043d\u044b\u0435 <code>IS<\/code>\/<code>BETWEEN<\/code>\/<code>IN<\/code>, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u043b\u043e\u0433\u0438\u043a\u0443, \u0438 \u0435\u0449\u0451 \u043f\u0430\u0440\u0443 \u0448\u0442\u0443\u043a \u043d\u0443\u0436\u043d\u044b\u0445 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043c,<br \/>  \u2022 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u043a\u043e\u0431\u043a\u0438 \u2014 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f.<\/p>\n<p>  <\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0432\u0435\u043b\u0438\u043a\u0438\u0439 \u0441\u0443\u043f \u0437\u0430\u0432\u0430\u0440\u0438\u043b\u0438. \u0427\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u0440\u0430\u0441\u0445\u043b\u0435\u0431\u0430\u0442\u044c \u0432\u043e \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435, \u043c\u043e\u0436\u043d\u043e \u0441 \u0443\u0441\u043f\u0435\u0445\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shunting_yard_algorithm\" rel=\"nofollow noopener noreferrer\">Shunting Yard<\/a>, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u00ab<a href=\"https:\/\/en.wikipedia.org\/wiki\/Reverse_Polish_notation\" rel=\"nofollow noopener noreferrer\">\u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u043f\u043e\u043b\u044c\u0441\u043a\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438<\/a>\u00bb. \u0410 \u043b\u044e\u0431\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 RPN \u043c\u043e\u0436\u043d\u043e \u0443\u0436\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430 \u0435\u0449\u0451 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u043c <a href=\"https:\/\/en.wikipedia.org\/wiki\/Stack-oriented_programming\" rel=\"nofollow noopener noreferrer\">\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0442\u0435\u043a\u0430<\/a>, \u0447\u0435\u043c \u0441\u0430\u043c Shunting Yard.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u043d\u0430 Java \u044d\u0442\u0438 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a (\u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e, Java \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u0430):<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">Shunting Yard<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p>\u0412\u044b\u0436\u0438\u043c\u043a\u0430 \u0438\u0437 <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\/blob\/9633eb3dc8612d8be2dd4107b63de3f3f47e1d44\/commons\/src\/main\/java\/io\/github\/pastorgl\/datacooker\/scripting\/TDL4Interpreter.java#L578-L762\" rel=\"nofollow noopener noreferrer\">TDL4Interpreter.java<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">    private List&lt;Expression&lt;?>> expression(List&lt;ParseTree> exprChildren, ExpressionRules rules) {         List&lt;Expression&lt;?>> items = new ArrayList&lt;>();          Deque&lt;ParseTree> whereOpStack = new LinkedList&lt;>();         List&lt;ParseTree> predExpStack = new ArrayList&lt;>();         int i = 0;         \/\/ doing Shunting Yard         for (; i &lt; exprChildren.size(); i++) {             ParseTree child = exprChildren.get(i);              if ((child instanceof TDL4.Expression_opContext)                     || (child instanceof TDL4.Comparison_opContext)                     || (child instanceof TDL4.Bool_opContext)                     || (child instanceof TDL4.In_opContext)                     || (child instanceof TDL4.Is_opContext)                     || (child instanceof TDL4.Between_opContext)                     || (child instanceof TDL4.Digest_opContext)                     || (child instanceof TDL4.Random_opContext)                     || (child instanceof TDL4.Default_opContext)) {                 while (!whereOpStack.isEmpty()) {                     ParseTree peek = whereOpStack.peek();                      if (peek instanceof TerminalNode) {                         TerminalNode tn = (TerminalNode) peek;                         int tt = tn.getSymbol().getType();                         if (tt == TDL4Lexicon.S_OPEN_PAR) {                             break;                         }                     }                     if (isHigher(child, peek)) {                         predExpStack.add(whereOpStack.pop());                     } else {                         break;                     }                 }                  whereOpStack.push(child);                 continue;             }              if (child instanceof TerminalNode) {                 TerminalNode tn = (TerminalNode) child;                 int tt = tn.getSymbol().getType();                 if (tt == TDL4Lexicon.S_OPEN_PAR) {                     whereOpStack.add(child);                     continue;                 }                  if (tt == TDL4Lexicon.S_CLOSE_PAR) {                     while (true) {                         if (whereOpStack.isEmpty()) {                             throw new RuntimeException(\"Mismatched parentheses at query token #\" + i);                         }                         ParseTree pop = whereOpStack.pop();                         if (!(pop instanceof TerminalNode)) {                             predExpStack.add(pop);                         } else {                             break;                         }                     }                     continue;                 }             }              \/\/ expression             predExpStack.add(child);         }          while (!whereOpStack.isEmpty()) {             predExpStack.add(whereOpStack.pop());         }          for (ParseTree exprItem : predExpStack) {             if (exprItem instanceof TDL4.Property_nameContext) {                 switch (rules) {                     case QUERY: {                         String propName = resolveName(((TDL4.Property_nameContext) exprItem).L_IDENTIFIER());                          items.add(Expressions.propItem(propName));                         continue;                     }                     case AT: {                         String propName = resolveName(((TDL4.Property_nameContext) exprItem).L_IDENTIFIER());                          items.add(Expressions.stringItem(propName));                         continue;                     }                     default: {                         throw new InvalidConfigurationException(\"Attribute name is not allowed in this context: \" + exprItem.getText());                     }                 }             }              if (exprItem instanceof TDL4.Var_nameContext) {                 TDL4.Var_nameContext varNameCtx = (TDL4.Var_nameContext) exprItem;                  String varName = resolveName(varNameCtx.L_IDENTIFIER());                  items.add(Expressions.varItem(varName));                 continue;             }              if (exprItem instanceof TDL4.Between_opContext) {                 TDL4.Between_opContext between = (TDL4.Between_opContext) exprItem;                  items.add(Expressions.stackGetter(1));                  double l = resolveNumericLiteral(between.L_NUMERIC(0)).doubleValue();                 double r = resolveNumericLiteral(between.L_NUMERIC(1)).doubleValue();                 items.add((between.S_NOT() == null)                         ? Expressions.between(l, r)                         : Expressions.notBetween(l, r)                 );                  continue;             }              if (exprItem instanceof TDL4.In_opContext) {                 TDL4.In_opContext inCtx = (TDL4.In_opContext) exprItem;                 if (inCtx.array() != null) {                     items.add(Expressions.setItem(resolveArray(inCtx.array(), ExpressionRules.QUERY)));                 }                 if (inCtx.var_name() != null) {                     items.add(Expressions.arrItem(resolveName(inCtx.var_name().L_IDENTIFIER())));                 }                 if (inCtx.property_name() != null) {                     items.add(Expressions.propItem(resolveName(inCtx.property_name().L_IDENTIFIER())));                 }                  items.add(Expressions.stackGetter(2));                  boolean not = inCtx.S_NOT() != null;                 items.add(not ? Expressions.notIn() : Expressions.in());                  continue;             }              \/\/ column_name IS NOT? NULL             if (exprItem instanceof TDL4.Is_opContext) {                 items.add(Expressions.stackGetter(1));                  items.add((((TDL4.Is_opContext) exprItem).S_NOT() == null) ? Expressions.isNull() : Expressions.nonNull());                  continue;             }              if ((exprItem instanceof TDL4.Expression_opContext)                     || (exprItem instanceof TDL4.Comparison_opContext)                     || (exprItem instanceof TDL4.Bool_opContext)                     || (exprItem instanceof TDL4.Digest_opContext)                     || (exprItem instanceof TDL4.Random_opContext)                     || (exprItem instanceof TDL4.Default_opContext)) {                 Operator eo = Operator.get(exprItem.getText());                 if (eo == null) {                     throw new RuntimeException(\"Unknown operator token \" + exprItem.getText());                 } else {                     items.add(Expressions.stackGetter(eo.ariness));                     items.add(Expressions.opItem(eo));                 }                  continue;             }              TerminalNode tn = (TerminalNode) exprItem;             int type = tn.getSymbol().getType();             if (type == TDL4Lexicon.L_NUMERIC) {                 items.add(Expressions.numericItem(resolveNumericLiteral(tn)));                 continue;             }             if (type == TDL4Lexicon.L_STRING) {                 items.add(Expressions.stringItem(resolveStringLiteral(tn)));                 continue;             }             if (type == TDL4Lexicon.S_NULL) {                 items.add(Expressions.nullItem());                 continue;             }             if ((type == TDL4Lexicon.S_TRUE) || (type == TDL4Lexicon.S_FALSE)) {                 items.add(Expressions.boolItem(Boolean.parseBoolean(tn.getText())));                 continue;             }         }          return items;     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u0442\u0435\u043a\u043e\u0432\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f RPN<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p>\u0412\u044b\u0436\u0438\u043c\u043a\u0430 \u0438\u0437 <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\/blob\/9633eb3dc8612d8be2dd4107b63de3f3f47e1d44\/commons\/src\/main\/java\/io\/github\/pastorgl\/datacooker\/scripting\/Operator.java#L461-L526\" rel=\"nofollow noopener noreferrer\">Operator.java<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">    public static Object eval(AttrGetter props, List&lt;Expression&lt;?>> item, VariablesContext vc) {         if (item.isEmpty()) {             return null;         }          Deque&lt;Object> stack = new LinkedList&lt;>();         Deque&lt;Object> top = null;         for (Expression&lt;?> ei : item) {             \/\/ these all push to expression stack             if (ei instanceof Expressions.PropItem) {                 stack.push(((Expressions.PropItem) ei).get(props));                 continue;             }             if (ei instanceof Expressions.VarItem) {                 stack.push(((Expressions.VarItem) ei).get(vc));                 continue;             }             if (ei instanceof Expressions.StringItem) {                 stack.push(((Expressions.StringItem) ei).get());                 continue;             }             if (ei instanceof Expressions.NumericItem) {                 stack.push(((Expressions.NumericItem) ei).get());                 continue;             }             if (ei instanceof Expressions.NullItem) {                 stack.push(((Expressions.NullItem) ei).get());                 continue;             }             if (ei instanceof Expressions.BoolItem) {                 stack.push(((Expressions.BoolItem) ei).get());                 continue;             }             if (ei instanceof Expressions.SetItem) {                 stack.push(((Expressions.SetItem) ei).get());                 continue;             }             if (ei instanceof Expressions.OpItem) {                 stack.push(((Expressions.OpItem) ei).eval(top));                 continue;             }             if (ei instanceof Expressions.IsExpr) {                 stack.push(((Expressions.IsExpr) ei).eval(top.pop()));                 continue;             }             if (ei instanceof Expressions.InExpr) {                 stack.push(((Expressions.InExpr) ei).eval(top.pop(), top.pop()));                 continue;             }             if (ei instanceof Expressions.BetweenExpr) {                 stack.push(((Expressions.BetweenExpr) ei).eval(top.pop()));                 continue;             }             \/\/ and this one pops from it             if (ei instanceof Expressions.StackGetter) {                 top = ((Expressions.StackGetter) ei).get(stack);                 continue;             }         }          if (stack.size() != 1) {             throw new RuntimeException(\"Invalid SELECT item expression\");         }          return stack.pop();     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041a\u043e\u0434\u0430 \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u043f\u043e \u043d\u0443\u0436\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u0430\u043c \u0441\u0442\u0435\u043a\u0430, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044f \u0438\u0445 \u0432 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u0442\u0438\u043f\u0430<br \/>  \u2022 \u00ab\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0442\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0432\u0438\u0434\u0430\u00bb,<br \/>  \u2022 \u00ab\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0438\u00bb,<br \/>  \u2022 \u00ab\u0432\u0437\u044f\u0442\u044c \u0441\u043e \u0441\u0442\u0435\u043a\u0430 N \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432\u00bb,<br \/>  \u2022 \u00ab\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0441\u043e \u0432\u0437\u044f\u0442\u044b\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438\u00bb,<br \/>  \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u2014 \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0431\u0435\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443, \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430, \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d. \u0415\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043d\u0435 \u043e\u0434\u0438\u043d, \u0442\u043e \u043b\u0438\u0431\u043e \u0433\u0434\u0435-\u0442\u043e \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u043f\u0430\u043b\u0438\u0441\u044c \u043d\u0435\u0441\u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438, \u043b\u0438\u0431\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e. \u0410 \u043a\u0430\u043a \u0432 \u044d\u0442\u043e\u0442 \u0441\u0443\u043f \u0437\u0430\u043f\u0438\u0445\u043d\u0443\u0442\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439? \u0412 \u043d\u0438\u0445 \u0432\u0435\u0434\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u0441\u043a\u043e\u0431\u043e\u0447\u043a\u0438 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u0435\u043d\u044f\u044e\u0442 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u043d\u043e \u0435\u0449\u0451 \u0438 \u0437\u0430\u0434\u0430\u044e\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0443\u0436\u0435 \u0434\u0430\u0436\u0435 \u043d\u0435 \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u0430\u043c\u0438, \u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u041d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u0443\u043f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e. (\u0412\u043e\u043f\u0440\u043e\u0441 \u0441\u043e \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u043e\u0439 \u00ab\u043a\u0430\u043a \u0435\u0433\u043e \u0440\u0430\u0441\u0445\u043b\u0435\u0431\u0430\u0442\u044c \u043d\u0435\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e?*\u00bb \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u043d\u0430 \u0441\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0430\u0432\u0442\u043e\u0440 \u043d\u0430\u043f\u0440\u043e\u0447\u044c \u0431\u0435\u0441\u0441\u043e\u0432\u0435\u0441\u0442\u043d\u044b\u0439, \u0438 \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0435 \u0436\u0435\u043b\u0430\u0435\u0442. \u041f\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u0443\u0436.)<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">expression  : ( is_op | between_op | in_op | comparison_op | var_name | L_NUMERIC | L_STRING | S_NULL | S_TRUE | S_FALSE | expression_op | digest_op | bool_op | default_op | func_call )+  ;  attr_expr  : ( is_op | between_op | in_op | comparison_op | var_name | L_NUMERIC | L_STRING | S_NULL | S_TRUE | S_FALSE | expression_op | digest_op | bool_op | default_op | func_attr | attr )+  ;  func_call  : func S_OPEN_PAR expression ( S_COMMA expression )* S_CLOSE_PAR  | func S_OPEN_PAR S_CLOSE_PAR  | S_OPEN_PAR expression S_CLOSE_PAR  ;  func_attr  : func S_OPEN_PAR attr_expr ( S_COMMA attr_expr )* S_CLOSE_PAR  | func S_OPEN_PAR S_CLOSE_PAR  | S_OPEN_PAR attr_expr S_CLOSE_PAR  ;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0447\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u2014 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u0441\u0430\u043c\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441\u0442\u0430\u043b\u043e \u0434\u0432\u0430. \u041e\u0434\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c \u0437\u0430\u043f\u0438\u0441\u0435\u0439, \u0442\u043e \u0435\u0441\u0442\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0445 \u0432 <code>SELECT \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, ... FROM ... WHERE \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435_\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/code>. \u0414\u0440\u0443\u0433\u043e\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0442\u0438\u043f\u0430 <code>LET $\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f = \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0438 \u043d\u0438 \u043a \u043a\u0430\u043a\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044f\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u043c\u043e\u0433\u0443\u0442.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0432 \u043f\u0430\u0440\u0441\u0435\u0440\u0435, \u043c\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u043c\u0441\u044f \u043e\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430\u0431\u044b\u043b\u0438. \u0420\u0430\u0431\u043e\u0442\u0430 \u043d\u0430\u0434 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u2014 \u0432\u0430\u0436\u043d\u0430!<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430:<br \/>  \u2022 <code>func(expression[, expression]...)<\/code><br \/>  \u2022 <code>func()<\/code><br \/>  \u2022 <code>(expression)<\/code><\/p>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u043a\u0443\u0441\u043e\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445 \u0431\u0435\u0437 \u0438\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c \u2014 \u044d\u0442\u043e \u0443 \u043d\u0430\u0441 \u0442\u043e\u0436\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u00ab\u0444\u0443\u043d\u043a\u0446\u0438\u044f\u00bb, \u043f\u0440\u0430\u0432\u0434\u0430, \u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u0430\u044f, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u043d\u0430 \u043d\u0430\u043c \u0441\u0432\u043e\u0439 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043b\u0438\u0431\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043a\u043e\u0431\u043e\u043a \u0438\u0437 Shunting Yard:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">Shunting Yard \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043a\u043e\u0431\u043e\u043a<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p>\u0412\u044b\u0436\u0438\u043c\u043a\u0430 \u0438\u0437 <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\/blob\/3930395e022b00036c8ac8a8f25e737bb8916a28\/commons\/src\/main\/java\/io\/github\/pastorgl\/datacooker\/scripting\/TDL4Interpreter.java#L578-L817\" rel=\"nofollow noopener noreferrer\">TDL4Interpreter.java<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">    private List&lt;ParseTree> doShuntingYard(List&lt;ParseTree> exprChildren) {         Deque&lt;ParseTree> whereOpStack = new LinkedList&lt;>();         List&lt;ParseTree> predExpStack = new ArrayList&lt;>();         int i = 0;         \/\/ doing Shunting Yard         for (; i &lt; exprChildren.size(); i++) {             ParseTree child = exprChildren.get(i);              if ((child instanceof TDL4.Expression_opContext)                     || (child instanceof TDL4.Comparison_opContext)                     || (child instanceof TDL4.Bool_opContext)                     || (child instanceof TDL4.In_opContext)                     || (child instanceof TDL4.Is_opContext)                     || (child instanceof TDL4.Between_opContext)                     || (child instanceof TDL4.Digest_opContext)                     || (child instanceof TDL4.Default_opContext)) {                 while (!whereOpStack.isEmpty()) {                     ParseTree peek = whereOpStack.peek();                      if (isHigher(child, peek)) {                         predExpStack.add(whereOpStack.pop());                     } else {                         break;                     }                 }                  whereOpStack.push(child);                 continue;             }              if (child instanceof TDL4.Func_callContext) {                 TDL4.Func_callContext funcCall = (TDL4.Func_callContext) child;                 if (funcCall.expression() != null) {                     for (TDL4.ExpressionContext e : funcCall.expression()) {                         predExpStack.addAll(doShuntingYard(e.children));                     }                 }                  if (funcCall.func() != null) {                     predExpStack.add(funcCall);                 }                 continue;             }              if (child instanceof TDL4.Func_attrContext) {                 TDL4.Func_attrContext funcAttr = (TDL4.Func_attrContext) child;                 if (funcAttr.attr_expr() != null) {                     for (TDL4.Attr_exprContext e : funcAttr.attr_expr()) {                         predExpStack.addAll(doShuntingYard(e.children));                     }                 }                  if (funcAttr.func() != null) {                     predExpStack.add(funcAttr);                 }                 continue;             }              \/\/ expression             predExpStack.add(child);         }          while (!whereOpStack.isEmpty()) {             predExpStack.add(whereOpStack.pop());         }          return predExpStack;     }      private List&lt;Expressions.ExprItem&lt;?>> expression(List&lt;ParseTree> exprChildren, ExpressionRules rules) {         List&lt;Expressions.ExprItem&lt;?>> items = new ArrayList&lt;>();          List&lt;ParseTree> predExpStack = doShuntingYard(exprChildren);          for (ParseTree exprItem : predExpStack) {             if (exprItem instanceof TDL4.AttrContext) {                 switch (rules) {                     case QUERY: {                         String propName = resolveName(((TDL4.AttrContext) exprItem).L_IDENTIFIER());                          items.add(Expressions.attrItem(propName));                         continue;                     }                     case AT: {                         String propName = resolveName(((TDL4.AttrContext) exprItem).L_IDENTIFIER());                          items.add(Expressions.stringItem(propName));                         continue;                     }                     default: {                         throw new InvalidConfigurationException(\"Attribute name is not allowed in this context: \" + exprItem.getText());                     }                 }             }              if (exprItem instanceof TDL4.Var_nameContext) {                 TDL4.Var_nameContext varNameCtx = (TDL4.Var_nameContext) exprItem;                  String varName = resolveName(varNameCtx.L_IDENTIFIER());                  items.add(Expressions.varItem(varName));                 continue;             }              if (exprItem instanceof TDL4.Between_opContext) {                 TDL4.Between_opContext between = (TDL4.Between_opContext) exprItem;                  items.add(Expressions.stackGetter(1));                  double l = resolveNumericLiteral(between.L_NUMERIC(0)).doubleValue();                 double r = resolveNumericLiteral(between.L_NUMERIC(1)).doubleValue();                 items.add((between.S_NOT() == null)                         ? Expressions.between(l, r)                         : Expressions.notBetween(l, r)                 );                  continue;             }              if (exprItem instanceof TDL4.In_opContext) {                 TDL4.In_opContext inCtx = (TDL4.In_opContext) exprItem;                 if (inCtx.array() != null) {                     items.add(Expressions.setItem(resolveArray(inCtx.array(), ExpressionRules.QUERY)));                 }                 if (inCtx.var_name() != null) {                     items.add(Expressions.arrItem(resolveName(inCtx.var_name().L_IDENTIFIER())));                 }                 if (inCtx.attr() != null) {                     items.add(Expressions.attrItem(resolveName(inCtx.attr().L_IDENTIFIER())));                 }                  items.add(Expressions.stackGetter(2));                  boolean not = inCtx.S_NOT() != null;                 items.add(not ? Expressions.notIn() : Expressions.in());                  continue;             }              \/\/ column_name IS NOT? NULL             if (exprItem instanceof TDL4.Is_opContext) {                 items.add(Expressions.stackGetter(1));                  items.add((((TDL4.Is_opContext) exprItem).S_NOT() == null) ? Expressions.isNull() : Expressions.nonNull());                  continue;             }              if ((exprItem instanceof TDL4.Expression_opContext)                     || (exprItem instanceof TDL4.Comparison_opContext)                     || (exprItem instanceof TDL4.Bool_opContext)                     || (exprItem instanceof TDL4.Digest_opContext)                     || (exprItem instanceof TDL4.Default_opContext)) {                 Operator&lt;?> eo = Operators.get(exprItem.getText());                 if (eo == null) {                     throw new RuntimeException(\"Unknown operator token \" + exprItem.getText());                 } else {                     int arity = eo.arity();                     items.add(Expressions.stackGetter(arity));                     items.add(Expressions.opItem(eo));                 }                  continue;             }              if (exprItem instanceof TDL4.Func_callContext) {                 TDL4.Func_callContext funcCall = (TDL4.Func_callContext) exprItem;                 TDL4.FuncContext funcCtx = funcCall.func();                 Function&lt;?> ef = Functions.get(resolveName(funcCtx.L_IDENTIFIER()));                 if (ef == null) {                     throw new RuntimeException(\"Unknown function token \" + exprItem.getText());                 } else {                     int arity = ef.arity();                     if (arity == Function.ARBITR_ARY) {                         items.add(Expressions.stackGetter(funcCall.expression().size()));                     } else if (arity > 0) {                         items.add(Expressions.stackGetter(arity));                     }                     items.add(Expressions.funcItem(ef));                 }                  continue;             }              if (exprItem instanceof TDL4.Func_attrContext) {                 TDL4.Func_attrContext funcAttr = (TDL4.Func_attrContext) exprItem;                 TDL4.FuncContext funcCtx = funcAttr.func();                 Function&lt;?> ef = Functions.get(resolveName(funcCtx.L_IDENTIFIER()));                 if (ef == null) {                     throw new RuntimeException(\"Unknown function token \" + exprItem.getText());                 } else {                     int arity = ef.arity();                     switch (arity) {                         case Function.KEY_LEVEL: {                             items.add(Expressions.keyItem());                             break;                         }                         case Function.RECORD_LEVEL: {                             items.add(Expressions.recItem());                             break;                         }                         case Function.ARBITR_ARY: {                             items.add(Expressions.stackGetter(funcAttr.attr_expr().size()));                             break;                         }                         case Function.NO_ARGS: {                             break;                         }                         default: {                             items.add(Expressions.stackGetter(arity));                         }                     }                     items.add(Expressions.funcItem(ef));                 }                  continue;             }              TerminalNode tn = (TerminalNode) exprItem;             int type = tn.getSymbol().getType();             if (type == TDL4Lexicon.L_NUMERIC) {                 items.add(Expressions.numericItem(resolveNumericLiteral(tn)));                 continue;             }             if (type == TDL4Lexicon.L_STRING) {                 items.add(Expressions.stringItem(resolveStringLiteral(tn)));                 continue;             }             if (type == TDL4Lexicon.S_NULL) {                 items.add(Expressions.nullItem());                 continue;             }             if ((type == TDL4Lexicon.S_TRUE) || (type == TDL4Lexicon.S_FALSE)) {                 items.add(Expressions.boolItem(Boolean.parseBoolean(tn.getText())));                 continue;             }         }          return items;     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f RPN, \u0442\u043e \u0442\u0430\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0441\u044f \u043c\u0430\u043b\u044e\u0441\u0435\u043d\u044c\u043a\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0435\u0439\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">            \/\/ special case             if (ei instanceof ObjItem) {                 top = new LinkedList&lt;>();                 top.add(((ObjItem) ei).recOrKey() ? rec : key);                 continue;             }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2014 \u043e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 <code>SELECT<\/code> \u043c\u043e\u0433\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0435\u0451 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438. \u041e\u043f, \u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u0437\u0430\u0431\u0435\u0436\u0430\u043b \u0432\u043f\u0435\u0440\u0451\u0434. \u0427\u0442\u043e \u0436, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u044d\u0442\u0443 \u043e\u043f\u043b\u043e\u0448\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0447\u0430\u0441\u0442\u0435\u0439, \u0447\u0442\u043e \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u043c \u043d\u0430\u043c\u0438 \u0434\u0432\u0438\u0436\u043a\u0435 SQL \u0432\u0441\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u0440\u043e\u043c\u0435 \u0441\u0430\u043c\u044b\u0445 \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 SQL, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u044f\u043c\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u043c\u0438.<\/p><\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u2014 \u0440\u0430\u0432\u043d\u043e \u043a\u0430\u043a \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u2014 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0435\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 classpath, \u0438 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u0435\u043c, \u043a\u0430\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u041d\u0430\u0437\u043e\u0432\u0451\u043c \u0435\u0433\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>Evaluator<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">public interface Evaluator&lt;R> extends Serializable {     R call(Deque&lt;Object> args);      String name();     String descr();      int arity();      \/\/ \u0422\u0443\u0442 \u0435\u0449\u0451 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0435\u043a\u043e\u043c,     \/\/ \u0442\u0438\u043f\u0430 popDouble(Deque&lt;Object> args), \u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043d\u0438\u0445 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0443 \u043d\u0430\u0441 \u0442\u0443\u0442? \u0422\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f generic \u0442\u0438\u043f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 <code>call<\/code> \u043d\u0430\u0434 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432\/\u043e\u043f\u0435\u0440\u0430\u043d\u0434\u043e\u0432, \u0438\u043c\u044f (\u0438\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b) \u0441 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e-\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0430\u043c\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432\/\u043e\u043f\u0435\u0440\u0430\u043d\u0434\u043e\u0432 \u2014 \u0442\u043e \u0435\u0441\u0442\u044c, \u0430\u0440\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0435\u0449\u0451 \u043a\u043e\u0435-\u0447\u0442\u043e. \u041e\u043f\u0438\u0448\u0435\u043c \u0438\u0445 \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u043a \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">public abstract class Operator&lt;R> implements Evaluator&lt;R> {     public abstract int prio();      public boolean rightAssoc() {         return false;     }      public boolean handleNull() {         return false;     }      protected abstract R op0(Deque&lt;Object> args);      public Operator() {     }      @Override     public R call(Deque&lt;Object> args) {         if (!handleNull()) {             for (Object a : args) {                 if (a == null) {                     return null;                 }             }         }          return op0(args);     }      public static abstract class Unary&lt;R, T> extends Operator&lt;R> {         @Override         public int arity() {             return 1;         }     }      public static abstract class Binary&lt;R, T1, T2> extends Operator&lt;R> {         @Override         public int arity() {             return 2;         }     }      public static abstract class Ternary&lt;R, T1, T2, T3> extends Operator&lt;R> {         @Override         public int arity() {             return 3;         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0444\u043b\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u043e-\u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439, \u0438\u0437\u043c\u0435\u043d\u044f\u044f \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0418 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0444\u043b\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u043d\u0434 \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c <code>NULL<\/code>. \u0410 \u0442\u043e \u0432\u0435\u0434\u044c, \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0443\u0441\u0442\u043e\u044f\u0432\u0448\u0438\u043c\u0441\u044f \u0432 SQL \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c, \u043b\u044e\u0431\u043e\u0439 \u0437\u0430\u0442\u0435\u0441\u0430\u0432\u0448\u0438\u0439\u0441\u044f \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 <code>NULL<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0438\u0442\u043e\u0433\u0435 <code>NULL<\/code>. \u042d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u0443 \u043d\u0430\u0441 \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u0436\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c <code>NULL<\/code> \u043a\u0430\u043a-\u0442\u043e \u0438\u043d\u0430\u0447\u0435, \u0438 \u043c\u044b \u0442\u0430\u043a\u0443\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u043c \u043e\u0431\u044f\u0437\u0430\u043d\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0443 \u043d\u0430\u0441 \u0431\u044b\u0432\u0430\u044e\u0442 \u0443\u043d\u0430\u0440\u043d\u044b\u0435, \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435, \u0438 \u0442\u0435\u0440\u043d\u0430\u0440\u043d\u044b\u0435.<\/p>\n<p>  <\/p>\n<p>\u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043a\u043e\u043b\u0435\u043d\u043a\u043e\u0440, \u043d\u043e \u0447\u0443\u0442\u043e\u0447\u043a\u0443 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 (\u0442\u043e \u0435\u0441\u0442\u044c, \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043d\u0438 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0449\u0435):<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">public abstract class Function&lt;R> implements Evaluator&lt;R> {     public static final int KEY_LEVEL = -3;     public static final int RECORD_LEVEL = -2;     public static final int ARBITR_ARY = -1;     public static final int NO_ARGS = 0;      public Function() {     }      public static abstract class KeyLevel&lt;R> extends Function&lt;R> {         @Override         public int arity() {             return KEY_LEVEL;         }     }      public static abstract class RecordLevel&lt;R, REC extends Record&lt;?>> extends Function&lt;R> {         @Override         public int arity() {             return RECORD_LEVEL;         }     }      public static abstract class ArbitrAry&lt;R, TA> extends Function&lt;R> {         @Override         public int arity() {             return ARBITR_ARY;         }     }      public static abstract class NoArgs&lt;R> extends Function&lt;R> {         @Override         public int arity() {             return NO_ARGS;         }     }      public static abstract class Unary&lt;R, T> extends Function&lt;R> {         @Override         public int arity() {             return 1;         }     }      public static abstract class Binary&lt;R, T1, T2> extends Function&lt;R> {         @Override         public int arity() {             return 2;         }     }      public static abstract class Ternary&lt;R, T1, T2, T3> extends Function&lt;R> {         @Override         public int arity() {             return 3;         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u043e \u0437\u0434\u0435\u0441\u044c \u0443 \u043d\u0430\u0441, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0445, \u0441\u043b\u043e\u0432\u043d\u043e \u0438\u0437 \u043d\u0438\u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u044b\u0435 \u0430\u0440\u043d\u043e\u0441\u0442\u0438:<br \/>  \u2022 \u00ab\u043d\u0443\u043b\u044f\u0440\u043d\u0430\u044f\u00bb \u2014 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432,<br \/>  \u2022 \u00ab\u043c\u0438\u043d\u0443\u0441 \u043f\u0435\u0440\u0432\u0430\u044f\u00bb \u2014 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432,<br \/>  \u2022 \u00ab\u0443\u0440\u043e\u0432\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0438\u00bb \u2014 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 SELECT, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442 \u0446\u0435\u043b\u0438\u043a\u043e\u043c,<br \/>  \u2022 \u00ab\u0443\u0440\u043e\u0432\u043d\u044f \u043a\u043b\u044e\u0447\u0430 \u0437\u0430\u043f\u0438\u0441\u0438\u00bb \u2014 \u0442\u043e\u0436\u0435 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 SELECT, \u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a \u043a\u043b\u044e\u0447\u0443 \u0437\u0430\u043f\u0438\u0441\u0438, \u0434\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0438\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u0432\u043e\u043e\u0431\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043d\u0435 \u0434\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>  <\/p>\n<blockquote><p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0432\u0435 \u0438\u043c\u0435\u044e\u0442 \u0441\u043c\u044b\u0441\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e SQL, \u043a\u0430\u043a \u043d\u0430\u0448. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u043d\u0430\u0431\u043e\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043d\u0451\u043c \u2014 \u044d\u0442\u043e Spark RDD, \u0438 \u043a\u0430\u0436\u0434\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043f\u0430\u0440\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u044e\u0447\u0430 (\u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 \u0431\u0430\u0439\u0442, \u043d\u043e \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e, \u0445\u043e\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0430, \u0445\u043e\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438) \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 (\u0442\u043e \u0435\u0441\u0442\u044c, \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 <code>Record&lt;?><\/code>, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 API \u0434\u0432\u0438\u0436\u043a\u0430). \u0421\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043a\u0430\u043a \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 RDBMS.<\/p><\/blockquote>\n<p>\u041a\u043b\u044e\u0447 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u043d\u0430\u0431\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0448\u0442\u0443\u043a\u0430 \u0434\u043b\u044f SQL \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0443\u0436\u0434\u0430\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u043d \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u043d\u0438 \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c \u0437\u0430\u043f\u0438\u0441\u0438, \u043d\u0438 \u0434\u0430\u0436\u0435 \u0441 \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u0430\u043d \u0438\u0437\u0432\u043d\u0435 \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0440\u043e\u043b\u044c \u0443 \u043d\u0435\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430\u044f, \u0432\u0435\u0434\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e\u043f\u0430\u0434\u0451\u0442. \u0414\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0434\u043e \u043d\u0435\u0433\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0442\u043e\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e, \u0440\u0430\u0437 \u043e\u043d \u043e\u0431\u0440\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u043d\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u043e \u043a\u043e\u043b\u0438 \u0443\u0436 \u0445\u043e\u0447\u0435\u0442\u0441\u044f (\u0434\u0430), \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">REC_KEY<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"plaintext\">public static class KEY extends KeyLevel&lt;Object> {     @Override     public Object call(Deque&lt;Object> args) {         return args.pop();     }      @Override     public String name() {         return \"REC_KEY\";     }      @Override     public String descr() {         return \"Returns the Key of DS Record\";     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0430\u043c\u0430 \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0435\u0451 \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 <code>eval()<\/code> \u043d\u0430 \u0447\u0442\u043e-\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">    public static boolean boolLoose(List&lt;ExprItem&lt;?>> item, VariablesContext vc) {         return boolAttr(null, null, item, vc);     }      public static Object evalAttr(Object key, Record&lt;?> rec, List&lt;ExprItem&lt;?>> item, VariablesContext vc) { \/\/...     }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0432 <code>evalAttr()<\/code> \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0438\u0441\u0438, \u043a\u0430\u043a \u0440\u0430\u043d\u044c\u0448\u0435, \u043d\u043e \u0435\u0449\u0451 \u0438 \u043a\u043b\u044e\u0447. \u0410 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c\u044b\u0445 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0433\u0434\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043d\u0435\u0442, \u0434\u0451\u0440\u0433\u0430\u0442\u044c <code>evalLoose()<\/code>. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u043e \u0442\u043e\u0447\u0435\u0447\u043d\u043e\u0435, \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043e\u0441\u043e\u0431\u043e \u043d\u0435 \u0430\u0444\u0444\u0435\u043a\u0442\u0438\u0442.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0422\u0430\u043a\u0436\u0435, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 Data Cooker ETL \u0437\u0430\u0442\u043e\u0447\u0435\u043d \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 ETL, \u0438 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u043e\u0439 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u0434\u0438\u044e \u043d\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0421\u0423\u0411\u0414. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u044b \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u044b, \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u043e\u043a\u043e\u043d\u043a\u0438, \u0442\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c. Spark \u044d\u0442\u043e \u0432\u0441\u0451 \u0443\u043c\u0435\u0435\u0442, \u043d\u043e \u043d\u0430\u0448 \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e\u0431\u044b \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430, \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043e\u043d\u044b\u043c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e.<\/p><\/blockquote>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0442\u0438\u043f\u0430 <code>COUNT(*)<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0445\u043b\u043e\u043f\u044b\u0432\u0430\u044e\u0442 \u0432\u0435\u0441\u044c \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0434\u043d\u0443 \u0437\u0430\u043f\u0438\u0441\u044c, \u0443 \u043d\u0430\u0441 \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0412\u0441\u0435 \u043d\u0430\u0448\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043b\u0438\u0431\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438, \u043b\u0438\u0431\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0442\u0438\u043f\u044b \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u044b, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0442\u0440\u0443\u0434\u0430. \u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438 ||<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class CAT extends Binary&lt;String, Object, Object> {         @Override         public int prio() {             return 125;         }          @Override         public String name() {             return \"||\";         }          @Override         public String descr() {             return \"String concatenation\";         }          @Override         protected String op0(Deque&lt;Object> args) {             return args.stream().map(String::valueOf).collect(Collectors.joining());         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043d\u0435\u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u0430, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 NULL<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class NEQ extends Binary&lt;Boolean, Object, Object> {         @Override         public int prio() {             return 40;         }          @Override         public String name() {             return \"!=\";         }          @Override         public String descr() {             return \"Checks for inequality. String checks are case-sensitive\";         }          @Override         public boolean handleNull() {             return true;         }          @Override         protected Boolean op0(Deque&lt;Object> args) {             Object a = args.pop();             Object b = args.pop();             if ((a == null) || (b == null)) {                 return false;             }             if (a instanceof Number) {                 return ((Number) a).doubleValue() != Utils.parseNumber(String.valueOf(b)).doubleValue();             }             if (a instanceof Boolean) {                 return (boolean) a != Boolean.parseBoolean(String.valueOf(b));             }             return !Objects.equals(a, b);         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class DIGEST extends Binary&lt;String, Object, String> {         @Override         public int prio() {             return 40;         }          @Override         public boolean rightAssoc() {             return true;         }          @Override         public String name() {             return \"DIGEST\";         }          @Override         public String descr() {             return \"Right argument is treated as Java digest provider in the format of provider-whitespace-algorithm\" +                     \" or only algorithm, and left argument's hash is calculated and converted to hexadecimal string\";         }          @Override         protected String op0(Deque&lt;Object> args) {             String r = Evaluator.popString(args);              String digest = Evaluator.popString(args);              final String[] d = digest.split(\" \", 2);              MessageDigest md;             try {                 md = (d.length > 1) ? MessageDigest.getInstance(d[1], d[0]) : MessageDigest.getInstance(d[0]);             } catch (Exception e) {                 throw new InvalidConfigurationException(\"Unknown DIGEST algorithm '\" + digest + \"'\");             }             return Hex.encodeHexString(md.digest(r.getBytes()));         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f MAX \u043e\u0442 \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class MAX extends ArbitrAry&lt;Double, Double> {         @Override         public Double call(Deque&lt;Object> args) {             if (args.isEmpty()) {                 return null;             }              return args.stream().mapToDouble(o -> Utils.parseNumber(String.valueOf(o)).doubleValue()).max().getAsDouble();         }          @Override         public String name() {             return \"MAX\";         }          @Override         public String descr() {             return \"Returns a mathematical max value from given arguments\";         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0440\u0435\u0437\u043a\u0438 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class Slice extends Ternary&lt;Object[], Object[], Integer, Integer> {         @Override         public Object[] call(Deque&lt;Object> args) {             Object[] a = Evaluator.popArray(args);             return Arrays.copyOfRange(a, Evaluator.popInt(args), Evaluator.popInt(args));         }          @Override         public String name() {             return \"ARR_SLICE\";         }          @Override         public String descr() {             return \"Return a slice of ARRAY given as 1st argument starting with index from 2nd and to index in 3rd (exclusive)\";         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0445\u0435\u0448\u043a\u043e\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0438<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class HASHCODE extends RecordLevel&lt;Integer, Record&lt;?>> {         @Override         public Integer call(Deque&lt;Object> args) {             return Objects.hashCode(args.pop());         }          @Override         public String name() {             return \"REC_HASHCODE\";         }          @Override         public String descr() {             return \"Returns Java .hashCode() of DS Record\";         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0438\u043c\u0435\u0442\u0440\u0430 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u043d\u0430 \u043c\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u0438<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">    public static class PolyPerimeter extends RecordLevel&lt;Double, PolygonEx> {         @Override         public Double call(Deque&lt;Object> args) {             PolygonEx poly = (PolygonEx) args.pop();              PolygonArea pArea = new PolygonArea(Geodesic.WGS84, false);              for (Coordinate c : poly.getExteriorRing().getCoordinates()) {                 pArea.AddPoint(c.y, c.x);             }              PolygonResult pRes = pArea.Compute();             return pRes.perimeter;         }          @Override         public String name() {             return \"POLY_PERIMETER\";         }          @Override         public String descr() {             return \"The perimeter of the Polygon's outline in meters\";         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a, \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0432 \u043a\u043b\u0430\u0441\u0441, \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0433\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\/blob\/master\/datetime\/src\/main\/java\/io\/github\/pastorgl\/datacooker\/datetime\/DateTimeFunctions.java\" rel=\"nofollow noopener noreferrer\">\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u0442\u043e\u0439\/\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c<\/a> \u043c\u044b \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u0435\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c, \u2014 \u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e-\u0442\u0430\u043a\u0438 \u043c\u043d\u043e\u0433\u043e, \u2014 \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f\u0430\u043c\u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0430\u0439\u043c\u0437\u043e\u043d\u0430\u0445. \u0420\u0430\u043d\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u0442\u043e \u0435\u0441\u0442\u044c, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430), \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0447\u0451\u0441\u0430\u043d\u044b \u043f\u043e\u0434 \u043e\u0431\u0449\u0443\u044e \u0433\u0440\u0435\u0431\u0451\u043d\u043a\u0443. (\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0432 \u043d\u0438\u043c\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435, \u043f\u043e\u0440\u0442\u044f\u043d\u043e\u043a \u043a\u043e\u0434\u0430 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0443\u0436\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.)<\/p>\n<p>  <\/p>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0442\u0438\u043f \u2014 <code>DateTime-like Object<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438\u0431\u043e \u043a\u0430\u043a <code>Numeric<\/code> \u0441 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u043c\u0438\/\u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u043c\u0438 \u042d\u043f\u043e\u0445\u0438, \u043b\u0438\u0431\u043e \u043a\u0430\u043a \u0431\u043e\u0433\u043e\u043c\u0435\u0440\u0437\u0441\u043a\u0430\u044f \u0436\u0430\u0431\u044c\u044f ISO8601-\u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u043c\u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0443, \u043d\u043e \u0447\u0430\u0441\u0442\u0435\u043d\u044c\u043a\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u043e\u0432. \u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u0434\u0435\u043b\u043e \u0435\u0441\u0442\u044c \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435, \u043d\u0430\u043c \u0442\u043e\u0436\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0435\u0433\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0438, \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437 \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0430\u0436 55 \u0448\u0442\u0443\u043a. \u0418 33 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 (\u043f\u0440\u0430\u0432\u0434\u0430, \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u044b).<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0436. \u0414\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0441\u043b\u043e\u044f API \u043c\u044b \u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u044f\u043c \u043a\u0430\u043a-\u0442\u043e \u0441\u0440\u0430\u0437\u0443, \u0438 \u0432\u043e\u0442 \u043e\u043d\u043e \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043f\u043e\u043c\u0438\u043c\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0441\u043b\u043e\u044f \u0434\u0432\u0438\u0436\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0446\u0435\u043b\u043e\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u043b\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0438\u043d\u0442\u0438\u0444\u043b\u044e\u0448\u043a\u0430\u043c\u0438, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0435\u0434\u044c \u0435\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u0441\u043b\u043e\u0451\u0432 \u0444\u0440\u043e\u043d\u0442\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2014 REPL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435, \u0442\u0430\u043a \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 REST, \u2014 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0434\u043e\u043a\u0443 \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438\u0437 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0422\u043e \u0435\u0441\u0442\u044c, \u0438\u0437 \u0442\u0435\u0445 \u0436\u0435 generic \u0442\u0438\u043f\u043e\u0432 \u0432 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430\u0445 <code>Function.Binary&lt;R, T1, T2><\/code> \u0438 \u0438\u0436\u0435 \u0441 \u043d\u0438\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0432\u0441\u044f \u044d\u0442\u0430 \u043c\u0430\u0448\u0438\u043d\u0435\u0440\u0438\u044f \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043d\u0435\u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u0432\u0438\u0436\u043a\u0430, \u2014 \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u00ab\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438\u00bb, \u00ab\u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u044b\u00bb, \u00ab\u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u00bb, \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u2014 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u043e\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u0435\u0440\u0438\u0439 \u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439, \u043d\u0435 \u0441\u0442\u0430\u043d\u0443, \u0430 <a href=\"https:\/\/habr.com\/ru\/articles\/761760\/\">\u043e\u0442\u043e\u0448\u043b\u044e \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438<\/a>. \u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u0451\u0432 \u0444\u0440\u043e\u043d\u0442\u0430 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0443\u0436 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u043a\u043e\u0434 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u043a\u0430\u043a \u043f\u0430\u0440\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0437\u0430\u043c\u0435\u0442\u043e\u043a \u043f\u043e \u043d\u0435\u043c\u0443 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">Operators.java<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">public class Operators {     public final static Map&lt;String, Operator&lt;?>> OPERATORS;      static {         Map&lt;String, Operator&lt;?>> operators = new HashMap&lt;>();          for (Map.Entry&lt;String, String> pkg : RegisteredPackages.REGISTERED_PACKAGES.entrySet()) {             try (ScanResult scanResult = new ClassGraph().acceptPackages(pkg.getKey()).scan()) {                 ClassInfoList operatorClasses = scanResult.getSubclasses(Operator.class.getTypeName());                 List&lt;Class&lt;?>> operatorClassRefs = operatorClasses.loadClasses();                  for (Class&lt;?> operatorClass : operatorClassRefs) {                     try {                         if (!Modifier.isAbstract(operatorClass.getModifiers())) {                             Operator&lt;?> operator = (Operator&lt;?>) operatorClass.getDeclaredConstructor().newInstance();                             operators.put(operator.name(), operator);                         }                     } catch (Exception e) {                         System.err.println(\"Cannot instantiate Operator class '\" + operatorClass.getTypeName() + \"'\");                         e.printStackTrace(System.err);                     }                 }             }         }          OPERATORS = Collections.unmodifiableMap(operators.entrySet()                 .stream()                 .sorted(Comparator.comparingInt(o -> -o.getValue().prio()))                 .collect(Collectors.toMap(                         Map.Entry::getKey,                         Map.Entry::getValue,                         (oldValue, newValue) -> oldValue, LinkedHashMap::new)));     }      public static Map&lt;String, EvaluatorInfo> packageOperators(String pkgName) {         Map&lt;String, EvaluatorInfo> ret = new LinkedHashMap&lt;>();          for (Map.Entry&lt;String, Operator&lt;?>> e : OPERATORS.entrySet()) {             if (e.getValue().getClass().getPackage().getName().startsWith(pkgName)) {                 ret.put(e.getKey(), EvaluatorInfo.bySymbol(e.getValue().name()));             }         }          return ret;     }      static Operator&lt;?> get(String symbol) {         return OPERATORS.get(symbol);     }      \/\/ Those three are in fact peculiar language constructs, so we make sure they     \/\/ won't go into the list of real Expression Operators. Therefore, this class     \/\/ is not included in @RegisteredPackage, and we directly reference them in     \/\/ the interpreter instead.     public static Operator&lt;Boolean> IN = new IN();     public static Operator&lt;Boolean> IS = new IS();     public static Operator&lt;Boolean> BETWEEN = new BETWEEN();      public static class IN extends Binary&lt;Boolean, Object, Object[]> {         @Override         public int prio() {             return 35;         }          @Override         public boolean rightAssoc() {             return true;         }          @Override         public String name() {             return \"IN\";         }          @Override         public String descr() {             return \"TRUE if left argument is present in the right, casted to array, FALSE otherwise.\" +                     \" Vice versa for NOT variant\";         }          @Override         protected Boolean op0(Deque&lt;Object> args) {             throw new RuntimeException(\"Direct operator IN call\");         }     }      public static class IS extends Binary&lt;Boolean, Object, Void> {         @Override         public int prio() {             return 35;         }          @Override         public boolean rightAssoc() {             return true;         }          @Override         public String name() {             return \"IS\";         }          @Override         public String descr() {             return \"TRUE if left argument is NULL, FALSE otherwise. Vice versa for NOT variant\";         }          @Override         public boolean handleNull() {             return true;         }          @Override         protected Boolean op0(Deque&lt;Object> args) {             throw new RuntimeException(\"Direct operator IS call\");         }     }      public static class BETWEEN extends Ternary&lt;Boolean, Double, Double, Double> {         @Override         public int prio() {             return 35;         }          @Override         public boolean rightAssoc() {             return true;         }          @Override         public String name() {             return \"BETWEEN\";         }          @Override         public String descr() {             return \"TRUE if left argument is inclusively between min and max, casted to numerics, FALSE otherwise.\" +                     \" For NOT variant, TRUE if it is outside the range, excluding boundaries\";         }          @Override         protected Boolean op0(Deque&lt;Object> args) {             throw new RuntimeException(\"Direct operator BETWEEN call\");         }     } }<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0434\u0432\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043e\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432\u0435\u0449\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043b\u044f \u043f\u0443\u0449\u0435\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e-\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0432 classpath \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0435 \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443, \u0430 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u2014 \u043e\u0442 \u043d\u0430\u0438\u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043a \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u043c\u0443. \u0412 \u0442\u0430\u043a\u043e\u043c \u0432\u0438\u0434\u0435 \u0435\u0433\u043e \u043f\u0440\u043e\u0449\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0447\u0442\u043e \u0432 REPL, \u0447\u0442\u043e \u0432 \u0434\u043e\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0432 SQL \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0432\u0435\u0441\u044c\u043c\u0430, \u043a\u0433\u0445\u043c\u2026 <em>\u043f\u0435\u043a\u0443\u043b\u044f\u0440\u043d\u044b\u0445<\/em> \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 <code>IN<\/code>, <code>IS<\/code> \u0438 <code>BETWEEN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043f\u0440\u043e\u0449\u0435 \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435, \u043d\u0435\u0436\u0435\u043b\u0438 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e-\u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u043c\u0443. \u0423 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0441 <code>NOT<\/code>, \u0438 \u0432\u043e\u043e\u0431\u0449\u0435, \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u043d\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">is_op  : S_IS S_NOT? S_NULL  ;  between_op  : S_NOT? S_BETWEEN L_NUMERIC S_AND L_NUMERIC  ;  in_op  : S_NOT? S_IN array  | S_NOT? S_IN var_name  | S_NOT? S_IN attr  ;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 <code>IS<\/code> \u0432\u0442\u043e\u0440\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434 \u0432\u0441\u0435\u0433\u0434\u0430 <code>NULL<\/code>, \u0434\u043b\u044f <code>IN<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0430 \u0432 <code>BETWEEN<\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u044b <code>Numeric<\/code>-\u043e\u0432. \u041a\u043e\u0440\u043e\u0447\u0435, \u043a\u0430\u043a \u0441\u043f\u0435\u043b \u043a\u043b\u0430\u0441\u0441\u0438\u043a, \u00ab\u0434\u0443\u0445\u043e\u0432\u043d\u044b\u0435 \u043b\u044e\u0434\u0438 \u043e\u0441\u043e\u0431\u044b\u0435 \u043b\u044e\u0434\u0438, \u0438 \u0435\u0441\u043b\u0438 \u0442\u044b \u043d\u0435 \u043f\u0440\u0435\u043b\u044e\u0431\u043e\u0434\u0435\u0439, \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0439 \u0434\u0443\u0445\u043e\u0432\u043d\u044b\u0445 \u043b\u044e\u0434\u0435\u0439\u2026 \u0434\u0435\u0439-\u0434\u0435\u0439-\u0434\u0435\u0439&#8230;\u00bb \u0418 \u044f \u0441\u043a\u043b\u043e\u043d\u0435\u043d \u0441 \u043d\u0438\u043c \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0441\u043a\u043e\u0440\u0435\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u044f\u0437\u044b\u043a\u0430, \u0447\u0435\u043c \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u0438\u0449\u0438. \u0422\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0438\u0445 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u0430\u043a\u0438\u0435 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438, \u0441\u0434\u0435\u043b\u0430\u0432 \u0437\u0430\u043e\u0434\u043d\u043e \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u043c\u0438 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0442\u043e\u0440\u0430, \u0438 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0443\u043d\u043a\u0442\u043e\u043c <a href=\"https:\/\/pastorgl.github.io\/datacooker-etl\/TDL4.html\" rel=\"nofollow noopener noreferrer\">\u0432 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u044f\u0437\u044b\u043a\u0443<\/a>, \u0433\u0434\u0435 \u043e\u043f\u0438\u0448\u0435\u043c \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u0435\u0432\u0438\u0430\u043d\u0442\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c, \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e \u0447\u0442\u043e \u0431\u044b \u0447\u0442\u043e-\u0442\u043e \u0431\u044b\u043b\u043e.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c, \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0449\u0435\u0435\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0442\u044f\u043d\u0435\u0442 \u043d\u0430 <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\/pull\/15\/files\" rel=\"nofollow noopener noreferrer\">\u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0436\u043e\u0440\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437<\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430 SQL \u2014 \u044d\u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0445\u0443\u0445\u0440\u044b-\u043c\u0443\u0445\u0440\u044b. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0434\u043b\u044f \u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u0437 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439 \u0442\u0435\u043c\u0430 \u00ab\u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u044b\u00bb \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u0442\u043e\u043b\u044c \u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439, \u043a\u0430\u043a \u0438 \u0434\u043b\u044f \u043c\u0435\u043d\u044f. \u0418\u043b\u0438 \u0436\u0435, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043a\u043e\u043c\u0443-\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f ETL \u0441 SQL-\u043d\u044b\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c. \u041f\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448\u0438 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u043c\u043a\u0430: <a href=\"https:\/\/pastorgl.github.io\/datacooker-etl\" rel=\"nofollow noopener noreferrer\">https:\/\/pastorgl.github.io\/datacooker-etl<\/a><br \/>  \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438: <a href=\"https:\/\/github.com\/PastorGL\/datacooker-etl\" rel=\"nofollow noopener noreferrer\">https:\/\/github.com\/PastorGL\/datacooker-etl<\/a><br \/>  \u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0432 \u0442\u0435\u043b\u0435\u0433\u0435: <a href=\"https:\/\/t.me\/data_cooker_etl\" rel=\"nofollow noopener noreferrer\">https:\/\/t.me\/data_cooker_etl<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/808483\/\"> https:\/\/habr.com\/ru\/articles\/808483\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/x1\/lx\/17\/x1lx17qduwak6ilxb0z0y6y0srg.png\" alt=\"\u041d\u042c\u042e!\" data-src=\"https:\/\/habrastorage.org\/webt\/x1\/lx\/17\/x1lx17qduwak6ilxb0z0y6y0srg.png\"\/><\/p>\n<p>  <\/p>\n<blockquote><p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u0435\u0440\u0438\u044f\u0445 (<a href=\"https:\/\/habr.com\/ru\/articles\/762862\/\">FAQ<\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/760504\/\"> 1 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/760778\/\"> 2 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761094\/\"> 3 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761328\/\"> 4 <\/a> \u2022 <a href=\"https:\/\/habr.com\/ru\/articles\/761760\/\"> 5 <\/a>) \u043c\u044b \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 Java \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430 SQL \u043f\u043e\u0432\u0435\u0440\u0445 Spark RDD API, \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p><\/blockquote>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f SQL \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,<\/p>\n<p>  <\/p>\n<pre><code class=\"sql\">SELECT     MAX(score1, score2, score3, score4, score5) AS max_score,     MIN(score1, score2, score3, score4, score5) AS min_score,     MEDIAN(score1, score2, score3, score4, score5) AS median_score,     score1 + score2 + score3 + score4 + score5 AS score_sum FROM raw_scores INTO final_scores WHERE ABS(score1 + score2 + score3 + score4 + score5) > $score_margin;<\/code><\/pre>\n<p>  <\/p>\n<p>\u2014 \u0442\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>MAX<\/code>, <code>MIN<\/code> \u0438 <code>MEDIAN<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 \u043b\u044e\u0431\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u0438\u043f\u0430 <code>Double<\/code> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 <code>Double<\/code>, \u0430 <code>ABS<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0442\u0430\u043a\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435, \u043a\u0440\u043e\u043c\u0435 \u043e\u0431\u0449\u0435\u0439 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438, \u0432 \u043b\u044e\u0431\u043e\u043c \u0443\u0432\u0430\u0436\u0430\u044e\u0449\u0435\u043c \u0441\u0435\u0431\u044f \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0435 SQL \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0441 \u0434\u0430\u0442\u043e\u0439\/\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. \u0418\u0445 \u043c\u044b \u0442\u043e\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c. \u0412 classpath, \u0447\u0442\u043e\u0431\u044b \u0434\u0432\u0438\u0436\u043e\u043a \u043c\u043e\u0433 \u0438\u0445 \u043e\u0442\u0442\u0443\u0434\u0430 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c. \u0414\u043e \u043a\u0443\u0447\u0438, \u0435\u0449\u0451 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 <code>>=<\/code> \u0438\u043b\u0438 <code>LIKE<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b, \u043d\u043e \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u043e\u043c, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a\u0438\u043c\u0438 \u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p>\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u0432 \u0446\u0435\u043b\u043e\u043c \u0432\u044b\u0441\u043e\u043a\u0438\u0439. \u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u044e\u0442\u0441\u044f, \u0434\u0430 \u0438 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0449\u0435 \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0447\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435. \u041d\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u0435\u0451 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0433\u0447\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u0443\u0436\u0435 \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0438\u0441\u044c \u043f\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u043e \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u0438.<\/p>\n<\/div><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-373929","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/373929","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=373929"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/373929\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=373929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=373929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=373929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}