2021SC@SDUSC
#SQLConfig接口–配置SQL
首先就是对各个不同的数据库进行全部划分,以便于后面对于不同数据库的匹配
String DATABASE_MYSQL = "MYSQL";
String DATABASE_POSTGRESQL = "POSTGRESQL";
String DATABASE_SQLSERVER = "SQLSERVER";
String DATABASE_ORACLE = "ORACLE";
String DATABASE_DB2 = "DB2";
String DATABASE_CLICKHOUSE = "CLICKHOUSE";
String SCHEMA_INFORMATION = "information_schema"; //MySQL, PostgreSQL, SQL Server 都有的系统模式
String SCHEMA_SYS = "sys"; //SQL Server 系统模式
String TABLE_SCHEMA = "table_schema";
String TABLE_NAME = "table_name";
然后就是给出的接口方法:
boolean isMySQL();
boolean isPostgreSQL();
boolean isSQLServer();
boolean isOracle();
boolean isDb2();
boolean isClickHouse();
作用就是去判断当前使用的数据库是什么类型,以便于进行后续操作
boolean limitSQLCount();
下面是一些限制:
最大单个数据库大小 不限
最大数据单表大小 32 TB
单条记录最大 1.6 TB
单字段最大允许 1 GB
单表允许最大记录数 不限
单表最大字段数 250 - 1600 (取决于字段类型)
单表最大索引数 不限
当然,实际上没有真正的无限制,还是要受系统可用磁盘空间、可用内存/交换区的制约。 事实上,当上述这些数值变得异常地大时,系统性能也会受很大影响。而我们的这个limitSQLCount方法就是用来给 Table, Column 等系统属性表来绕过 MAX_SQL_COUNT 等限制
然后就是具体的一些操作
String getDBVersion();
String getDBUri();
String getDBAccount();
String getDBPassword();
String getSQL(boolean prepared) throws Exception;
首先就是获取数据库版本号,可通过判断版本号解决一些 JDBC 驱动连接数据库的兼容问题比如 MYSQL: 8.0, 5.7, 5.6 等; PostgreSQL: 11, 10, 9.6 等
然后就是获取数据库地址
在之后获取数据库账号
获取数据库密码
获取SQL语句
接下来是一些get/set方法,这些都是作者设置的一些规则,设置的时候的类型为SQLConfig类型,get的时候就是他们本身各自的属性类型
boolean isTest();
SQLConfig setTest(boolean test);
int getType();
SQLConfig setType(int type);
int getCount();
SQLConfig setCount(int count);
int getPage();
SQLConfig setPage(int page);
int getQuery();
SQLConfig setQuery(int query);
int getPosition();
SQLConfig setPosition(int position);
int getCache();
SQLConfig setCache(int cache);
boolean isExplain();
SQLConfig setExplain(boolean explain);
List<Join> getJoinList();
SQLConfig setJoinList(List<Join> joinList);
比如其中的setJoinList方法的作用:
在分析过的AbstractSQLConfig类里面有它的具体应用:
首先看一下JOIN类型的具体数据
private String path;
private String originKey;
private String originValue;
private String joinType; // "@" - APP, "<" - LEFT, ">" - RIGHT, "*" - CROSS, "&" - INNER, "|" - FULL, "!" - OUTER, "^" - SIDE, "(" - ANTI, ")" - FOREIGN
private String relateType; // "" - 一对一, "{}" - 一对多, "<>" - 多对一
private JSONObject request; // { "id@":"/Moment/userId" }
private String table; //User
private String alias; //owner
private String key; //id
private String targetTable; // Moment
private String targetAlias; //main
private String targetKey; // userId
private JSONObject outter;
private SQLConfig joinConfig;
private SQLConfig cacheConfig;
private SQLConfig outterConfig;
这个是JOIN类型具体含有的各项属性。
然后看一下它的具体:
public static SQLConfig parseJoin(RequestMethod method, SQLConfig config, List<Join> joinList, Callback callback) throws Exception {
boolean isQuery = RequestMethod.isQueryMethod(method);
config.setKeyPrefix(isQuery && config.isMain() == false);
//TODO 解析出 SQLConfig 再合并 column, order, group 等
if (joinList == null || joinList.isEmpty() || RequestMethod.isQueryMethod(method) == false) {
return config;
}
String table;
String alias;
for (Join j : joinList) {
table = j.getTable();
alias = j.getAlias();
//JOIN子查询不能设置LIMIT,因为ON关系是在子查询后处理的,会导致结果会错误
SQLConfig joinConfig = newSQLConfig(method, table, alias, j.getRequest(), null, false, callback);
SQLConfig cacheConfig = j.canCacheViceTable() == false ? null : newSQLConfig(method, table, alias, j.getRequest(), null, false, callback).setCount(1);
if (j.isAppJoin() == false) { //除了 @ APP JOIN,其它都是 SQL JOIN,则副表要这样配置
if (joinConfig.getDatabase() == null) {
joinConfig.setDatabase(config.getDatabase()); //解决主表 JOIN 副表,引号不一致
}
else if (joinConfig.getDatabase().equals(config.getDatabase()) == false) {
throw new IllegalArgumentException("主表 " + config.getTable() + " 的 @database:" + config.getDatabase() + " 和它 SQL JOIN 的副表 " + table + " 的 @database:" + joinConfig.getDatabase() + " 不一致!");
}
if (joinConfig.getSchema() == null) {
joinConfig.setSchema(config.getSchema()); //主表 JOIN 副表,默认 schema 一致
}
if (cacheConfig != null) {
cacheConfig.setDatabase(joinConfig.getDatabase()).setSchema(joinConfig.getSchema()); //解决主表 JOIN 副表,引号不一致
}
if (isQuery) {
config.setKeyPrefix(true);
}
joinConfig.setMain(false).setKeyPrefix(true);
if (j.isLeftOrRightJoin()) {
SQLConfig outterConfig = newSQLConfig(method, table, alias, j.getOuter(), null, false, callback);
outterConfig.setMain(false).setKeyPrefix(true).setDatabase(joinConfig.getDatabase()).setSchema(joinConfig.getSchema()); //解决主表 JOIN 副表,引号不一致
j.setOuterConfig(outterConfig);
}
}
//解决 query: 1/2 查数量时报错
/* SELECT count(*) AS count FROM sys.Moment AS Moment
LEFT JOIN ( SELECT count(*) AS count FROM sys.Comment ) AS Comment ON Comment.momentId = Moment.id LIMIT 1 OFFSET 0 */
if (RequestMethod.isHeadMethod(method, true)) {
joinConfig.setMethod(GET); //子查询不能为 SELECT count(*) ,而应该是 SELECT momentId
joinConfig.setColumn(Arrays.asList(j.getKey())); //优化性能,不取非必要的字段
if (cacheConfig != null) {
cacheConfig.setMethod(GET); //子查询不能为 SELECT count(*) ,而应该是 SELECT momentId
cacheConfig.setColumn(Arrays.asList(j.getKey())); //优化性能,不取非必要的字段
}
}
j.setJoinConfig(joinConfig);
j.setCacheConfig(cacheConfig);
}
config.setJoinList(joinList);
return config;
}
在这里先是对JOInList进行判断后,再对JOINList进行一顿循环遍历后,将其中的每个join都进行分别的处理,然后获取到每个join里面的数据,并加入到我们的SQLConfig里面,之后讲config的JOINList设置为此JOINList然后返回config