@@ -430,6 +430,7 @@ public abstract class AbstractSQLConfig implements SQLConfig {
430430 SQL_FUNCTION_MAP .put ("nullif" , "" ); // NULLIF(expr1, expr2) 比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1
431431 SQL_FUNCTION_MAP .put ("group_concat" , "" ); // GROUP_CONCAT([DISTINCT], s1, s2...) 聚合拼接字符串
432432 SQL_FUNCTION_MAP .put ("match" , "" ); // MATCH (name,tag) AGAINST ('a b' IN NATURAL LANGUAGE MODE) 全文检索
433+ SQL_FUNCTION_MAP .put ("any_value" , "" ); // any_value(userId) 解决 ONLY_FULL_GROUP_BY 报错
433434
434435
435436
@@ -3439,7 +3440,7 @@ else if (isOracle()) {
34393440 condition += (condition + "has(JSONExtractArrayRaw(assumeNotNull(" + getKey (column ) + "))" + ", " + getValue (key , column , v ) + (StringUtil .isEmpty (path , true ) ? "" : ", " + getValue (key , column , path )) + ")" );
34403441 }
34413442 else {
3442- condition += ("json_contains(" + getKey (column ) + ", " + getValue (key , column , v ) + (StringUtil .isEmpty (path , true ) ? "" : ", " + getValue (key , column , path )) + ")" );
3443+ condition += ("json_contains(" + getKey (column ) + ", " + getValue (key , column , v ) + (StringUtil .isEmpty (path , true ) ? "" : ", " + getValue (key , column , path )) + ")" );
34433444 }
34443445 }
34453446 }
@@ -3490,7 +3491,17 @@ public String getSubqueryString(Subquery subquery) throws Exception {
34903491 * @return
34913492 */
34923493 public static String getCondition (boolean not , String condition ) {
3493- return not ? NOT + "(" + condition + ")" : condition ;
3494+ return getCondition (not , condition , false );
3495+ }
3496+ /**拼接条件
3497+ * @param not
3498+ * @param condition
3499+ * @param outerBreaket
3500+ * @return
3501+ */
3502+ public static String getCondition (boolean not , String condition , boolean addOuterBracket ) {
3503+ String s = not ? NOT + "(" + condition + ")" : condition ;
3504+ return addOuterBracket ? "( " + s + " )" : s ;
34943505 }
34953506
34963507
@@ -3800,32 +3811,7 @@ public String getJoinString() throws Exception {
38003811 jc .setMain (true ).setKeyPrefix (false );
38013812 sql = ( "<" .equals (type ) ? " LEFT" : (">" .equals (type ) ? " RIGHT" : " CROSS" ) )
38023813 + " JOIN ( " + jc .getSQL (isPrepared ()) + " ) AS " + quote + jt + quote ;
3803-
3804- if (onList != null ) {
3805- boolean first = true ;
3806- for (On on : onList ) {
3807- String rt = on .getRelateType ();
3808- if (StringUtil .isEmpty (rt , false )) {
3809- sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + " = "
3810- + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3811- }
3812- else if ("{}" .equals (rt )) {
3813- sql += (first ? ON : AND ) + "json_contains(" + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote
3814- // + ", concat('\\'', " + quote + jt + quote + "." + quote + on.getKey() + quote + ", '\\''), '$')";
3815- + ", cast(" + quote + jt + quote + "." + quote + on .getKey () + quote + " AS CHAR), '$')" ;
3816- }
3817- else if ("<>" .equals (rt )) {
3818- sql += (first ? ON : AND ) + "json_contains(" + quote + jt + quote + "." + quote + on .getKey () + quote
3819- // + ", concat('\\'', " + quote + on.getTargetTable() + quote + "." + quote + on.getTargetKey() + quote + ", '\\''), '$')";
3820- + ", cast(" + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + " AS CHAR), '$')" ;
3821- }
3822- else {
3823- throw new IllegalArgumentException ("join:value 中 value 里的 " + jt + "/" + j .getPath ()
3824- + " 中 JOIN ON 条件关联类型 " + rt + " 不合法!只支持 =, {}, <> 这几种!" );
3825- }
3826- first = false ;
3827- }
3828- }
3814+ sql = concatJoinOn (sql , quote , j , jt , onList );
38293815
38303816 jc .setMain (false ).setKeyPrefix (true );
38313817
@@ -3841,32 +3827,7 @@ else if ("<>".equals(rt)) {
38413827 case "(" : // ANTI JOIN: A & ! B
38423828 case ")" : // FOREIGN JOIN: B & ! A
38433829 sql = " INNER JOIN " + jc .getTablePath ();
3844- if (onList != null ) {
3845- boolean first = true ;
3846- for (On on : onList ) {
3847- String rt = on .getRelateType ();
3848- if (StringUtil .isEmpty (rt , false )) {
3849- sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + " = "
3850- + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3851- }
3852- else if ("{}" .equals (rt )) {
3853- sql += (first ? ON : AND ) + "json_contains(" + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote
3854- // + ", concat('\\'', " + quote + jt + quote + "." + quote + on.getKey() + quote + ", '\\''), '$')";
3855- + ", cast(" + quote + jt + quote + "." + quote + on .getKey () + quote + " AS CHAR), '$')" ;
3856- }
3857- else if ("<>" .equals (rt )) {
3858- sql += (first ? ON : AND ) + "json_contains(" + quote + jt + quote + "." + quote + on .getKey () + quote
3859- // + ", concat('\\'', " + quote + on.getTargetTable() + quote + "." + quote + on.getTargetKey() + quote + ", '\\''), '$')";
3860- + ", cast(" + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + " AS CHAR), '$')" ;
3861- }
3862- else {
3863- throw new IllegalArgumentException ("join:value 中 value 里的 " + jt + "/" + j .getPath ()
3864- + " 中 JOIN ON 条件关联类型 " + rt + " 不合法!只支持 =, {}, <> 这几种!" );
3865- }
3866-
3867- first = false ;
3868- }
3869- }
3830+ sql = concatJoinOn (sql , quote , j , jt , onList );
38703831 break ;
38713832 default :
38723833 throw new UnsupportedOperationException (
@@ -3902,6 +3863,140 @@ else if ("<>".equals(rt)) {
39023863 return StringUtil .isEmpty (joinOns , true ) ? "" : joinOns + " \n " ;
39033864 }
39043865
3866+
3867+ protected String concatJoinOn (@ NotNull String sql , @ NotNull String quote , @ NotNull Join j , @ NotNull String jt , List <On > onList ) {
3868+ if (onList != null ) {
3869+ boolean first = true ;
3870+ for (On on : onList ) {
3871+ Logic logic = on .getLogic ();
3872+ boolean isNot = logic == null ? false : logic .isNot ();
3873+ if (isNot ) {
3874+ onJoinNotRelation (sql , quote , j , jt , onList , on );
3875+ }
3876+
3877+ String rt = on .getRelateType ();
3878+ if (StringUtil .isEmpty (rt , false )) {
3879+ sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + (isNot ? " != " : " = " )
3880+ + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3881+ }
3882+ else {
3883+ onJoinComplextRelation (sql , quote , j , jt , onList , on );
3884+
3885+ if (">=" .equals (rt ) || "<=" .equals (rt ) || ">" .equals (rt ) || "<" .equals (rt )) {
3886+ if (isNot ) {
3887+ throw new IllegalArgumentException ("join:value 中 value 里的 " + jt + "/" + j .getPath ()
3888+ + " 中 JOIN ON 条件关联逻辑符 " + rt + " 不合法! >, <, >=, <= 不支持与或非逻辑符 & | ! !" );
3889+ }
3890+
3891+ sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + " " + rt + " "
3892+ + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3893+ }
3894+ else if ("$" .equals (rt )) {
3895+ sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + (isNot ? NOT : "" )
3896+ + " LIKE concat('%', " + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + ", '%')" ;
3897+ }
3898+ else if (rt .endsWith ("~" )) {
3899+ boolean ignoreCase = "*~" .equals (rt );
3900+ if (isPostgreSQL ()) {
3901+ sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + (isNot ? NOT : "" )
3902+ + " ~" + (ignoreCase ? "* " : " " ) + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3903+ }
3904+ else if (isOracle ()) {
3905+ sql += (first ? ON : AND ) + "regexp_like(" + quote + jt + quote + "." + quote + on .getKey () + quote
3906+ + ", " + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + (ignoreCase ? ", 'i'" : ", 'c'" ) + ")" ;
3907+ }
3908+ else if (isClickHouse ()) {
3909+ sql += (first ? ON : AND ) + "match(" + (ignoreCase ? "lower(" : "" ) + quote + jt + quote + "." + quote + on .getKey () + quote + (ignoreCase ? ")" : "" )
3910+ + ", " + (ignoreCase ? "lower(" : "" ) + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + (ignoreCase ? ")" : "" ) + ")" ;
3911+ }
3912+ else if (isHive ()) {
3913+ sql += (first ? ON : AND ) + (ignoreCase ? "lower(" : "" ) + quote + jt + quote + "." + quote + on .getKey () + quote + (ignoreCase ? ")" : "" )
3914+ + " REGEXP " + (ignoreCase ? "lower(" : "" ) + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote + (ignoreCase ? ")" : "" );
3915+ }
3916+ else {
3917+ sql += (first ? ON : AND ) + quote + jt + quote + "." + quote + on .getKey () + quote + (isNot ? NOT : "" )
3918+ + " REGEXP " + (ignoreCase ? "" : "BINARY " ) + quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3919+ }
3920+ }
3921+ else if ("{}" .equals (rt ) || "<>" .equals (rt )) {
3922+ String tt = on .getTargetTable ();
3923+ String ta = on .getTargetAlias ();
3924+
3925+ Map <String , String > cast = null ;
3926+ if (tt .equals (getTable ()) && ((ta == null && getAlias () == null ) || ta .equals (getAlias ()))) {
3927+ cast = getCast ();
3928+ }
3929+ else {
3930+ boolean find = false ;
3931+ for (Join jn : joinList ) {
3932+ if (tt .equals (jn .getTable ()) && ((ta == null && jn .getAlias () == null ) || ta .equals (jn .getAlias ()))) {
3933+ cast = getCast ();
3934+ find = true ;
3935+ break ;
3936+ }
3937+ }
3938+
3939+ if (find == false ) {
3940+ throw new IllegalArgumentException ("join:value 中 value 里的 " + jt + "/" + j .getPath ()
3941+ + " 中 JOIN ON 条件中找不到对应的 " + rt + " 不合法!只支持 =, {}, <> 这几种!" );
3942+ }
3943+ }
3944+
3945+ boolean isBoolOrNum = SQL .isBooleanOrNumber (cast == null ? null : cast .get (on .getTargetKey ()));
3946+
3947+ String arrKeyPath ;
3948+ String itemKeyPath ;
3949+ if ("{}" .equals (rt )) {
3950+ arrKeyPath = quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3951+ itemKeyPath = quote + jt + quote + "." + quote + on .getKey () + quote ;
3952+ }
3953+ else {
3954+ arrKeyPath = quote + jt + quote + "." + quote + on .getKey () + quote ;
3955+ itemKeyPath = quote + on .getTargetTable () + quote + "." + quote + on .getTargetKey () + quote ;
3956+ }
3957+
3958+ if (isPostgreSQL ()) { //operator does not exist: jsonb @> character varying "[" + c + "]");
3959+ sql += (first ? ON : AND ) + (isNot ? "( " : "" ) + getCondition (isNot , arrKeyPath
3960+ + " IS NOT NULL AND " + arrKeyPath + " @> " + itemKeyPath ) + (isNot ? ") " : "" );
3961+ }
3962+ else if (isOracle ()) {
3963+ sql += (first ? ON : AND ) + (isNot ? "( " : "" ) + getCondition (isNot , arrKeyPath
3964+ + " IS NOT NULL AND json_textcontains(" + arrKeyPath
3965+ + ", '$', " + itemKeyPath + ")" ) + (isNot ? ") " : "" );
3966+ }
3967+ else if (isClickHouse ()) {
3968+ sql += (first ? ON : AND ) + (isNot ? "( " : "" ) + getCondition (isNot , arrKeyPath
3969+ + " IS NOT NULL AND has(JSONExtractArrayRaw(assumeNotNull(" + arrKeyPath + "))"
3970+ + ", " + itemKeyPath + ")" ) + (isNot ? ") " : "" );
3971+ }
3972+ else {
3973+ sql += (first ? ON : AND ) + (isNot ? "( " : "" ) + getCondition (isNot , arrKeyPath
3974+ + " IS NOT NULL AND json_contains(" + arrKeyPath
3975+ + (isBoolOrNum ? ", cast(" + itemKeyPath + " AS CHAR), '$')"
3976+ : ", concat('\" ', " + itemKeyPath + ", '\" '), '$')"
3977+ )
3978+ ) + (isNot ? ") " : "" );
3979+ }
3980+ }
3981+ else {
3982+ throw new IllegalArgumentException ("join:value 中 value 里的 " + jt + "/" + j .getPath ()
3983+ + " 中 JOIN ON 条件关联类型 " + rt + " 不合法!只支持 =, >, <, >=, <=, !=, $, ~, {}, <> 这几种!" );
3984+ }
3985+ }
3986+
3987+ first = false ;
3988+ }
3989+ }
3990+
3991+ return sql ;
3992+ }
3993+
3994+ protected void onJoinNotRelation (String sql , String quote , Join j , String jt , List <On > onList , On on ) {
3995+ // throw new UnsupportedOperationException("JOIN 已禁用 '!' 非逻辑连接符 !性能很差、需求极少,如要取消禁用可在后端重写相关方法!");
3996+ }
3997+ protected void onJoinComplextRelation (String sql , String quote , Join j , String jt , List <On > onList , On on ) {
3998+ // throw new UnsupportedOperationException("JOIN 已禁用 {} 和 <> 等复杂关联 !性能很差、需求极少,默认只允许等价关联,如要取消禁用可在后端重写相关方法!");
3999+ }
39054000 protected void onGetCrossJoinString (Join j ) throws UnsupportedOperationException {
39064001 throw new UnsupportedOperationException ("已禁用 * CROSS JOIN !性能很差、需求极少,如要取消禁用可在后端重写相关方法!" );
39074002 }
0 commit comments