
com.gitee.qdbp.jdbc.sql.SqlBuilder Maven / Gradle / Ivy
package com.gitee.qdbp.jdbc.sql;
import java.io.Serializable;
import com.gitee.qdbp.jdbc.plugins.DbPluginHelper;
import com.gitee.qdbp.jdbc.plugins.SqlDialect;
import com.gitee.qdbp.tools.utils.IndentTools;
import com.gitee.qdbp.tools.utils.StringTools;
/**
* SQL生成器, 会自动追加空格
* 这是SqlBuffer的快捷方式, 使用短名称作为方法名(名称太长不方便连写)
* ad=append, pd=prepend, var=addVariable
*
* @author zhaohuihua
* @version 20200713
*/
public class SqlBuilder implements Serializable {
/** SerialVersionUID **/
private static final long serialVersionUID = 1L;
private SqlBuffer buffer;
/** 构造函数 **/
public SqlBuilder(SqlDialect dialect, DbPluginHelper plugins) {
this.buffer = new SqlBuffer(dialect, plugins, this);
}
/** 构造函数 **/
public SqlBuilder(SqlDialect dialect, DbPluginHelper plugins, String sql) {
this.buffer = new SqlBuffer(dialect, plugins, this);
this.buffer.append(sql);
}
/** 构造函数 **/
public SqlBuilder(SqlBuffer buffer) {
this.buffer = buffer;
}
/** 返回SqlBuffer实例 **/
public SqlBuffer out() {
return this.buffer;
}
/**
* 如果容器不是空的, 就追加SQL片断
*
* @param part SQL片断
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder adIf(String part) {
if (!this.isBlank()) {
this.ad(part);
}
return this;
}
/**
* ad=append: 将指定SQL片段追加到SQL后面, 将会在前后及每项之间自动追加空格
*
* @param parts SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder ad(String... parts) {
if (parts != null) {
for (String part : parts) {
int lastIndent = SqlTools.Indent.findLastIndentSize(this.buffer);
if (lastIndent == 0 || IndentTools.countNewlineChars(part) == 0) {
// 不能自动处理, 因为有可能本意就是想简单的追加
this.buffer.autoAppendWhitespace(part).append(part);
} else { // 只有两个片段都有换行才自动处理
// minIndent<0表示未找到缩进, 只有leading=false才有可能<0
int minIndent = IndentTools.countMinIndentSize(part, true);
if (minIndent < 0 || lastIndent == minIndent) {
this.buffer.autoAppendWhitespace(part).append(part);
} else {
// 左侧以空行结尾, 右侧首行空白后面会清除(不用额外判断,加不加无所谓)
// 左侧是文字结尾, 右侧以空行开头, 则右侧首行不用加缩进
boolean leading = !IndentTools.startsWithBlankline(part);
String temp = IndentTools.tabs.tabAll(part, lastIndent - minIndent, leading);
if (SqlTools.Text.endsWithBlankline(this.buffer)) {
// 左侧以空行结束且最后有缩进(lastIndent>0), 则右侧首行缩进需要清除掉
temp = StringTools.trimLeft(temp, ' ', '\t');
}
this.buffer.autoAppendWhitespace(temp).append(temp);
}
}
}
}
return this;
}
/**
* ad=append: 将指定SQL片段追加到SQL后面, 将会在前后自动追加空格
* 注意: 每项之间不会追加空格, 这点与ad(String... parts)不同
*
* @param parts SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder ad(char... parts) {
if (parts != null) {
this.buffer.autoAppendWhitespace(new String(parts)).append(parts);
}
return this;
}
/**
* pd=prepend: 将指定SQL片段增加到SQL语句最前面, 将会在前后及每项之间自动追加空格
*
* @param parts SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder pd(String... parts) {
if (parts != null) {
for (int i = parts.length - 1; i >= 0; i--) {
String part = parts[i];
int lastIndent = IndentTools.findLastIndentSize(part);
if (lastIndent == 0 || SqlTools.Text.countNewlineChars(this.buffer) == 0) {
// 不能自动处理, 因为有可能本意就是想简单的追加
} else { // 只有两个片段都有换行才自动处理
// minIndent<0表示未找到缩进, 只有leading=false才有可能<0
int minIndent = SqlTools.Indent.countMinIndentSize(this.buffer, true);
if (minIndent >= 0 && lastIndent != minIndent) {
// 左侧以空行结尾, 右侧首行空白后面会清除(不用额外判断,加不加无所谓)
// 左侧是文字结尾, 右侧以空行开头, 则右侧首行不用加缩进
boolean leading = !SqlTools.Text.startsWithBlankline(this.buffer);
this.buffer.tabAll(lastIndent - minIndent, leading);
if (IndentTools.endsWithBlankline(part)) {
// 左侧以空行结束且最后有缩进(lastIndent>0), 则右侧首行缩进需要清除掉
this.buffer.clearLeadingIndentWhitespace();
}
}
}
this.buffer.autoPrependWhitespace(part).prepend(part);
}
}
return this;
}
/**
* pd=prepend: 将指定SQL片段增加到SQL语句最前面, 将会在前后自动追加空格
* 注意: 每项之间不会追加空格, 这点与pd(String... parts)不同
*
* @param parts SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder pd(char... parts) {
if (parts != null) {
this.buffer.autoPrependWhitespace(new String(parts)).prepend(parts);
}
return this;
}
/**
* ad=append: 将指定SQL片段追加到SQL语句后面, 将会自动追加空格
*
* @param buffer SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder ad(SqlBuffer buffer) {
if (buffer != null && !buffer.isEmpty()) {
int lastIndent = SqlTools.Indent.findLastIndentSize(this.buffer);
SqlBuffer temp = buffer;
if (lastIndent == 0 || SqlTools.Text.countNewlineChars(buffer) == 0) {
// 不能自动处理, 因为有可能本意就是想简单的追加
} else { // 只有两个片段都有换行才自动处理
// minIndent<0表示未找到缩进, 只有leading=false才有可能<0
int minIndent = SqlTools.Indent.countMinIndentSize(temp, true);
if (minIndent >= 0 && lastIndent != minIndent) {
// 左侧以空行结尾, 右侧首行空白后面会清除(不用额外判断,加不加无所谓)
// 左侧是文字结尾, 右侧以空行开头, 则右侧首行不用加缩进
boolean leading = !SqlTools.Text.startsWithBlankline(buffer);
temp = buffer.copy().tabAll(lastIndent - minIndent, leading);
if (SqlTools.Text.endsWithBlankline(this.buffer)) {
// 左侧以空行结束且最后有缩进(lastIndent>0), 则右侧首行缩进需要清除掉
temp.clearLeadingIndentWhitespace();
}
}
}
this.buffer.autoAppendWhitespace(temp).append(temp);
}
return this;
}
/**
* ad=append: 将指定SQL片段追加到SQL语句后面, 将会自动追加空格
*
* @param another SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder ad(SqlBuilder another) {
return this.ad(another.buffer);
}
/**
* pd=prepend: 将指定SQL片段增加到SQL语句最前面, 将会自动追加空格
*
* @param buffer SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder pd(SqlBuffer buffer) {
if (buffer != null && !buffer.isEmpty()) {
int indent = SqlTools.Indent.findLastIndentSize(buffer);
if (indent == 0 || SqlTools.Text.countNewlineChars(this.buffer) == 0) {
// 不能自动处理, 因为有可能本意就是想简单的追加
} else { // 只有两个片段都有换行才自动处理
// minIndent<0表示未找到缩进, 只有leading=false才有可能<0
int minIndent = SqlTools.Indent.countMinIndentSize(this.buffer, true);
if (minIndent >= 0 && indent != minIndent) {
// 左侧以空行结尾, 右侧首行空白后面会清除(不用额外判断,加不加无所谓)
// 左侧是文字结尾, 右侧以空行开头, 则右侧首行不用加缩进
boolean leading = !SqlTools.Text.startsWithBlankline(this.buffer);
this.buffer.tabAll(indent - minIndent, leading);
if (SqlTools.Text.endsWithBlankline(buffer)) {
// 左侧以空行结束且最后有缩进(lastIndent>0), 则右侧首行缩进需要清除掉
this.buffer.clearLeadingIndentWhitespace();
}
}
}
this.buffer.autoPrependWhitespace(buffer).prepend(buffer);
}
return this;
}
/**
* pd=prepend: 将指定SQL片段增加到SQL语句最前面, 将会自动追加空格
*
* @param another SQL片段
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder pd(SqlBuilder another) {
return this.pd(another.buffer);
}
/**
* var=addVariable: 增加变量, 同时将变量以占位符追加到SQL语句中
*
* @param value 变量
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder var(Object value) {
this.buffer.autoAppendWhitespace().addVariable(value);
return this;
}
/**
* 增加换行
*
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder br() {
this.buffer.append('\n');
return this;
}
/**
* 增加换行, 将会自动保持上一行的缩进量
*
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder newline() {
this.buffer.append('\n');
int size = SqlTools.Indent.findLastIndentSize(this.buffer);
if (size > 0) {
this.buffer.append(IndentTools.getIndentTabs(size));
}
return this;
}
/**
* 增加缩进
*
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder tab() {
return this.tab(1);
}
/**
* 在现有的基础上增加或减少缩进
*
* @param size 缩进量: 正数为增加, 负数为减少
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder tab(int size) {
if (size > 0) {
this.buffer.append(IndentTools.getIndentTabs(size));
} else if (size < 0) {
// 负数为减少缩进
// 先清除缩进, 再追加至减少后的数量
// 因为有可能存在\s\s\t这种不规范的缩进, 无法从后往前直接清除
int currSize = this.buffer.clearTrailingIndentWhitespace();
if (currSize > 0) {
this.buffer.append(IndentTools.getIndentTabs(currSize + size));
}
}
return this;
}
/**
* 设置缩进量
* indent()是设置缩进量
* tab()是在当前缩进量的基础上增加或减少缩进
*
* @param size 缩进量: 必须为正数或0, 负数视为0
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder indent(int size) {
this.buffer.clearTrailingIndentWhitespace();
if (size > 0) {
this.buffer.append(IndentTools.getIndentTabs(size));
}
return this;
}
/**
* 所有内容缩进n个TAB
*
* @param size 缩进量: 正数为增加, 负数为减少
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder tabAll(int size) {
this.buffer.tabAll(size, true);
return this;
}
/**
* 所有内容设置为缩进n个TAB, 以最小的缩进为准
*
* @param size 必须为正数或0, 负数视为0
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder indentAll(int size) {
this.buffer.indentAll(size, true);
return this;
}
public boolean isEmpty() {
return buffer.isEmpty();
}
public boolean isBlank() {
return buffer.isBlank();
}
/**
* 超级长的SQL在输出日志时可以省略掉一部分
* 省略哪一部分, 用startOmit()/endOmit()来标识起止位置
*
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder omit(boolean enabled) {
if (enabled) {
this.buffer.startOmit();
} else {
this.buffer.endOmit();
}
return this;
}
/**
* 传入size和当前index, 自动计算, 插入省略标记
* 日志只取前3行+后3行; 因此在第3行后面开始省略, 在后3行之前结束省略
* 注意: 如果有换行符, 最好放在换行符后面
*
* @param index 当前行数
* @param count 总行数
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder omit(int index, int count) {
this.buffer.tryOmit(index, count);
return this;
}
/**
* 传入size和当前index, 自动计算, 插入省略标记
* 日志只取前3行+后3行; 因此在第3行后面开始省略, 在后3行之前结束省略
* 注意: 如果有换行符, 最好放在换行符后面
*
* @param index 当前行数
* @param count 总行数
* @param limit 保留多少行(前后各保留limit行)
* @return 返回当前SQL容器用于连写
*/
public SqlBuilder omit(int index, int count, int limit) {
this.buffer.tryOmit(index, count, limit);
return this;
}
/**
* 复制
*
* @return 副本
*/
public SqlBuilder copy() {
SqlBuilder target = new SqlBuilder(this.buffer.sqlDialect(), this.buffer.plugins());
target.buffer = this.buffer.copy();
return target;
}
/**
* 复制到另一个缓存容器中
*
* @param target 目标容器
*/
public void copyTo(SqlBuilder target) {
target.buffer = this.buffer.copy();
}
@Override
public String toString() {
return this.buffer.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy