001/* 002 * Copyright (c) 2022-2025, 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.dialect; 017 018import com.mybatisflex.core.constant.SqlConsts; 019import com.mybatisflex.core.util.StringUtil; 020 021import java.util.Arrays; 022import java.util.Collections; 023import java.util.Set; 024import java.util.stream.Collectors; 025 026/** 027 * 用于对数据库的关键字包装 028 */ 029public class KeywordWrap { 030 031 /** 032 * 无反义处理, 适用于 db2, informix, clickhouse 等 033 */ 034 public static final KeywordWrap NONE = new KeywordWrap("", "") { 035 @Override 036 public String wrap(String keyword) { 037 return keyword; 038 } 039 }; 040 041 /** 042 * 无反义区分大小写处理, 适用于 db2, informix, clickhouse 等 043 */ 044 public static final KeywordWrap NONE_CASE_SENSITIVE = new KeywordWrap(true, "", "") { 045 @Override 046 public String wrap(String keyword) { 047 return keyword; 048 } 049 }; 050 051 /** 052 * 反引号反义处理, 适用于 mysql, h2 等 053 */ 054 public static final KeywordWrap BACK_QUOTE = new KeywordWrap("`", "`"); 055 056 /** 057 * 双引号反义处理, 适用于 postgresql, sqlite, derby, oracle, duckdb 等 058 */ 059 public static final KeywordWrap DOUBLE_QUOTATION = new KeywordWrap("\"", "\""); 060 061 /** 062 * 方括号反义处理, 适用于 sqlserver 063 */ 064 public static final KeywordWrap SQUARE_BRACKETS = new KeywordWrap("[", "]"); 065 /** 066 * 大小写敏感 067 */ 068 private boolean caseSensitive = false; 069 070 /** 071 * 自动把关键字转换为大写 072 */ 073 private boolean keywordsToUpperCase = false; 074 /** 075 * 数据库关键字 076 */ 077 private final Set<String> keywords; 078 /** 079 * 前缀 080 */ 081 private final String prefix; 082 /** 083 * 后缀 084 */ 085 private final String suffix; 086 087 088 public KeywordWrap(String prefix, String suffix) { 089 this(false, Collections.emptySet(), prefix, suffix); 090 } 091 092 093 public KeywordWrap(boolean caseSensitive, String prefix, String suffix) { 094 this(caseSensitive, Collections.emptySet(), prefix, suffix); 095 } 096 097 public KeywordWrap(Set<String> keywords, String prefix, String suffix) { 098 this(false, keywords, prefix, suffix); 099 } 100 101 public KeywordWrap(boolean caseSensitive, Set<String> keywords, String prefix, String suffix) { 102 this.caseSensitive = caseSensitive; 103 this.keywords = keywords.stream().map(String::toUpperCase).collect(Collectors.toSet()); 104 this.prefix = prefix; 105 this.suffix = suffix; 106 } 107 108 public KeywordWrap(boolean caseSensitive, boolean keywordsToUpperCase, Set<String> keywords, String prefix, 109 String suffix) { 110 this.caseSensitive = caseSensitive; 111 this.keywordsToUpperCase = keywordsToUpperCase; 112 this.keywords = keywords.stream().map(String::toUpperCase).collect(Collectors.toSet()); 113 this.prefix = prefix; 114 this.suffix = suffix; 115 } 116 117 public String wrap(String keyword) { 118 if (StringUtil.noText(keyword) || SqlConsts.ASTERISK.equals(keyword.trim())) { 119 return keyword; 120 } 121 122 if (caseSensitive || keywords.isEmpty()) { 123 return prefix + keyword + suffix; 124 } 125 126 if (keywordsToUpperCase) { 127 keyword = keyword.toUpperCase(); 128 return keywords.contains(keyword) ? (prefix + keyword + suffix) : keyword; 129 } else { 130 return keywords.contains(keyword.toUpperCase()) ? (prefix + keyword + suffix) : keyword; 131 } 132 } 133 134 //数据scheme table 包装 根据 . 分割后分别包装 135 public String wrapKeyword(String keyword) { 136 StringBuilder resultBuilder = new StringBuilder(); 137 String[] split = keyword.split("\\."); 138 if (split != null && split.length > 0) { 139 Arrays.asList(split) 140 .forEach(f -> resultBuilder.append(prefix).append(f).append(suffix).append(".")); 141 return resultBuilder.toString().substring(0, resultBuilder.length() - 1); 142 } else { 143 return prefix + keyword + suffix; 144 } 145 } 146 147 //sqlserver 转义 scheme table colums 包装 根据 . 分割后分别包装 148 public String wrap4Sqlserver(String keyword) { 149 if (StringUtil.noText(keyword) || SqlConsts.ASTERISK.equals(keyword.trim())) { 150 return keyword; 151 } 152 153 if (caseSensitive || keywords.isEmpty()) { 154 return wrapKeyword(keyword); 155 } 156 157 if (keywordsToUpperCase) { 158 keyword = keyword.toUpperCase(); 159 return keywords.contains(keyword) ? wrapKeyword(keyword) : keyword; 160 } else { 161 return keywords.contains(keyword.toUpperCase()) ? wrapKeyword(keyword) : keyword; 162 } 163 } 164 165 public boolean isCaseSensitive() { 166 return caseSensitive; 167 } 168 169 public void setCaseSensitive(boolean caseSensitive) { 170 this.caseSensitive = caseSensitive; 171 } 172 173 public boolean isKeywordsToUpperCase() { 174 return keywordsToUpperCase; 175 } 176 177 public void setKeywordsToUpperCase(boolean keywordsToUpperCase) { 178 this.keywordsToUpperCase = keywordsToUpperCase; 179 } 180 181 public Set<String> getKeywords() { 182 return keywords; 183 } 184 185 public String getPrefix() { 186 return prefix; 187 } 188 189 public String getSuffix() { 190 return suffix; 191 } 192}