001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.util; 017 018import java.time.LocalDateTime; 019import java.util.Date; 020import java.util.regex.Matcher; 021 022public class SqlUtil { 023 024 private SqlUtil() { 025 } 026 027 public static void keepColumnSafely(String column) { 028 if (StringUtil.isBlank(column)) { 029 throw new IllegalArgumentException("Column must not be empty"); 030 } else { 031 column = column.trim(); 032 } 033 034 int strLen = column.length(); 035 for (int i = 0; i < strLen; ++i) { 036 char ch = column.charAt(i); 037 if (Character.isWhitespace(ch)) { 038 throw new IllegalArgumentException("Column must not has space char."); 039 } 040 if (isUnSafeChar(ch)) { 041 throw new IllegalArgumentException("Column has unsafe char: [" + ch + "]."); 042 } 043 } 044 } 045 046 047 /** 048 * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) 049 */ 050 private static String SQL_ORDER_BY_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; 051 052 public static void keepOrderBySqlSafely(String value) { 053 if (!value.matches(SQL_ORDER_BY_PATTERN)) { 054 throw new IllegalArgumentException("Order By sql not safe, order by string: " + value); 055 } 056 } 057 058 059 private static final char[] UN_SAFE_CHARS = "'`\"<>&+=#-;".toCharArray(); 060 061 private static boolean isUnSafeChar(char ch) { 062 for (char c : UN_SAFE_CHARS) { 063 if (c == ch) { 064 return true; 065 } 066 } 067 return false; 068 } 069 070 071 /** 072 * 根据数据库响应结果判断数据库操作是否成功。 073 * 074 * @param result 数据库操作返回影响条数 075 * @return {@code true} 操作成功,{@code false} 操作失败。 076 */ 077 public static boolean toBool(Number result) { 078 return result != null && result.longValue() > 0; 079 } 080 081 082 /** 083 * 替换 sql 中的问号 ? 084 * @param sql sql 内容 085 * @param params 参数 086 * @return 完整的 sql 087 */ 088 public static String replaceSqlParams(String sql, Object[] params) { 089 if (params != null && params.length > 0) { 090 for (Object value : params) { 091 // null 092 if (value == null) { 093 sql = sql.replaceFirst("\\?", "null"); 094 } 095 // number 096 else if (value instanceof Number || value instanceof Boolean) { 097 sql = sql.replaceFirst("\\?", value.toString()); 098 } 099 // other 100 else { 101 StringBuilder sb = new StringBuilder(); 102 sb.append("'"); 103 if (value instanceof Date) { 104 sb.append(DateUtil.toDateTimeString((Date) value)); 105 } else if (value instanceof LocalDateTime) { 106 sb.append(DateUtil.toDateTimeString(DateUtil.toDate((LocalDateTime) value))); 107 } else { 108 sb.append(value); 109 } 110 sb.append("'"); 111 sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(sb.toString())); 112 } 113 } 114 } 115 return sql; 116 } 117 118 119 120}