shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
package com.walker.dbmeta.util;
 
import com.walker.connector.Address;
import com.walker.connector.support.DatabaseConnector;
import com.walker.db.DatabaseException;
import com.walker.infrastructure.utils.SegmentReader;
import com.walker.infrastructure.utils.StringUtils;
 
public abstract class DatabaseUtils {
 
    public static final String DB_SEPARATOR = "_";
    public static final String MYSQL_TBL_REF = "`";
    
    /**
     * 克隆一个<code>Address</code>资源地址对象
     * @param addr
     * @param isUsing 是否正在使用
     * @param suffixIndex 命名的后缀,多库使用
     * @return
     */
    public static Address copyAddress(Address addr, boolean isUsing, int suffixIndex, String defineName){
        Address a = new Address();
        a.setUrl(addr.getUrl());
        a.setPort(addr.getPort());
        a.setService(defineName + DB_SEPARATOR + suffixIndex);
        a.setSuffixIndex(suffixIndex);
        a.setUsing(isUsing);
        a.setAuthentication(addr.getAuthentication());
        a.setCertification(addr.getCertification());
        return a;
    }
    
    /**
     * 把MySQL的服务名字中提取数据库,因为里面会有参数,如:walkersoft-share-marks?characterEncoding=UTF-8</p>
     * 提取之后结果为:walkersoft-share-marks
     * @param serviceName
     * @return
     */
    public static final String getMySQLSchemaName(String serviceName){
        if(StringUtils.isEmpty(serviceName)){
            return null;
        }
        int index = serviceName.indexOf("?");
        if(index >= 0){
            return serviceName.substring(0, index);
        } else {
            return serviceName;
        }
    }
    
    /**
     * 返回数据库名字后面的后缀,如果不存在返回-1</p>
     * 如:demo_1, test_u_2
     * @param dbName
     * @return
     */
    public static final int getDatabaseNameIndex(String dbName){
        if(StringUtils.isEmpty(dbName)){
            return -1;
        }
        String[] test = dbName.split(DB_SEPARATOR);
        if(test == null || test.length <= 1){
            return -1;
        }
        String index = test[test.length-1];
        try{
            return Integer.parseInt(index);
        } catch(NumberFormatException ex){
            return -1;
        }
    }
    
    private static final String KEY_START = "create table ";
    private static final String KEY_START_BACK = "create table if not exists ";
    private static final String KEY_END = "(";
    
    /**
     * 从创建表的SQL中找出表名
     * @param createTableSQL
     * @return
     * @throws DatabaseException
     */
    public static final String findTableNameInSQL(String createTableSQL) throws DatabaseException {
//        String _s = createTableSQL.trim().toLowerCase();
        String _s = createTableSQL;
        if(_s.startsWith(KEY_START_BACK)){
            String tname = getSingleSqlTable(_s, KEY_START_BACK);
            if(StringUtils.isNotEmpty(tname)){
                // MySQL会有这个字符,要去掉
                return tname.trim().replaceAll(MYSQL_TBL_REF, "");
            }
        } else if(_s.startsWith(KEY_START)){
            String tname = getSingleSqlTable(_s, KEY_START);
            if(StringUtils.isNotEmpty(tname)){
                // MySQL会有这个字符,要去掉
                return tname.trim().replaceAll(MYSQL_TBL_REF, "");
            }
        }
        throw new DatabaseException("SQL中未找到表名" + _s);
    }
    
    /**
     * 得到SQL中表的名字,如: create table table1(id varchar2 not null ...)
     * @param sql
     * @return
     */
    private static String getSingleSqlTable(String sql, String keyStart){
        SegmentReader reader = new SegmentReader();
        reader.setKeyCaseSensitive(true);
        reader.addKey(keyStart, KEY_END);
        reader.addRemoveKey("--", "\n");
        reader.read(sql);
        return reader.getSolvedContent(keyStart, KEY_END);
    }
    
    private static final String KEY_START_INX = "create index ";
    private static final String KEY_END_INX = " on";
    
    /**
     * 找到SQL语句中的索引名字,如果是创建索引语句的话
     * @param createTableSQL
     * @return
     * @throws DatabaseException
     */
    public static String findIndexNameInSQL(String createTableSQL) throws DatabaseException{
        if(createTableSQL.startsWith(KEY_START_INX)){
            String inxName = getSingleIndexName(createTableSQL);
            if(StringUtils.isNotEmpty(inxName)){
                // MySQL会有这个字符,要去掉
                return inxName.trim();
            }
        }
        throw new DatabaseException("SQL中未找到索引名称,sql = " + createTableSQL);
    }
    
    private static String getSingleIndexName(String sql){
        SegmentReader reader = new SegmentReader();
        reader.setKeyCaseSensitive(true);
        reader.addKey(KEY_START_INX, KEY_END_INX);
        reader.addRemoveKey("--", "\n");
        reader.read(sql);
        return reader.getSolvedContent(KEY_START_INX, KEY_END_INX);
    }
    
    private static final String KEY_TBL_START_INX = " on ";
    
    /**
     * 返回创建索引SQL中的表名称
     * @param sql
     * @return
     */
    public static final String findTableNameInIndex(String sql){
        SegmentReader reader = new SegmentReader();
        reader.setKeyCaseSensitive(true);
        reader.addKey(KEY_TBL_START_INX, KEY_END);
        reader.addRemoveKey("--", "\n");
        reader.read(sql);
        String result = reader.getSolvedContent(KEY_TBL_START_INX, KEY_END);
        if(StringUtils.isNotEmpty(result)){
            return result.trim();
        } else
            return null;
    }
    
    /**
     * 是个创建表结构的SQL语句
     * @param sql
     * @return
     */
    public static boolean isCreateTableSQL(String sql){
        if(sql.startsWith(KEY_START_BACK) || sql.startsWith(KEY_START)){
            return true;
        }
        return false;
    }
    
    /**
     * 是个创建索引的SQL语句
     * @param sql
     * @return
     */
    public static boolean isCreateIndexSQL(String sql){
        if(sql.startsWith(KEY_START_INX)){
            return true;
        }
        return false;
    }
    
    /**
     * 手动创建物理表数据,在存在元数据的情况下,物理表不存在,需要通过该方法创建。
     * @param connector
     * @param createSQL
     * @param tableName 缺失的表名,如:rec_main_consume_709
     * @param business 业务参数,如:customerCode
     * @return
     * @throws DatabaseException
     */
    public static boolean manualCreatePhysicalTable(DatabaseConnector connector
            , String createSQL, String tableName, String business) throws DatabaseException{
        // 找出sql中表名,如果与给定的目的表名不一致,要用目的表名替换
        if(StringUtils.isEmpty(createSQL)){
            throw new IllegalArgumentException("SQL语句中未找到表名,destTableName = " + tableName);
        }
        
        // 处理给定的SQL语句,因为里面可能会存在多个,包括:创建表结构和索引的!
        String[] sqlList = createSQL.split(StringUtils.SEPARATOR_SEMI_COLON);
        if(sqlList == null || sqlList.length == 0){
            throw new DatabaseException("存储引擎未发现任何创建表或者索引的SQL语句,无法继续执行写入数据任务。createSQL = " + createSQL + ", tableName = " + tableName);
        }
        for(String sql : sqlList){
            sql = sql.trim(); // 去掉回车、换行、空格等
            if(DatabaseUtils.isCreateTableSQL(sql)){
                String tname = DatabaseUtils.findTableNameInSQL(sql);
                if(!tname.equals(tableName)){
                    sql = sql.replace(tname, tableName);
//                                logger.debug("替换后的SQL = " + sql);
                }
                connector.exeCreateTable(sql);
                return true;
                
            } else if(DatabaseUtils.isCreateIndexSQL(sql)){
                String iname = DatabaseUtils.findIndexNameInSQL(sql);
                // 重用生成表名的策略来生成索引名字,它两个其实一样,不想再加入新接口了。
//                String indexName = ((DatabaseStoreStrategy)this.storeStrategy).getTableName(addr, iname, parameter);
                String indexName = iname + DatabaseUtils.DB_SEPARATOR + business;
                if(!iname.equals(indexName)){
                    // 替换索引名字
                    sql = sql.replace(iname, indexName);
                    // 替换索引中表名
                    sql = sql.replace(DatabaseUtils.findTableNameInIndex(sql), tableName);
//                                logger.debug("替换后的索引SQL = " + sql);
                }
                connector.exeCreateTable(sql);
                return true;
            }
        }
        return false;
    }
    
    public static void main(String[] args) throws Exception{
//        System.out.println("_test_-9: " + DatabaseUtils.getDatabaseNameIndex("_test_-9"));
//        System.out.println("_test: " + DatabaseUtils.getDatabaseNameIndex("_test"));
//        System.out.println("test-2_1: " + DatabaseUtils.getDatabaseNameIndex("test-2_1"));
//        System.out.println("test-2_: " + DatabaseUtils.getDatabaseNameIndex("test-2_"));
//        System.out.println("ABC2 _DSF_0: " + DatabaseUtils.getDatabaseNameIndex("ABC2 _DSF_0"));
        
//        String dest = "my_demo";
//        String test = "CREATE TABLE IF NOT EXISTS  `t_menu`   (`id` int(11) NOT NULL AUTO_INCREMENT,`pid` int(11) NOT NULL,`url` varchar(100) CHARACTER SET utf8 NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;";
//        String tname = findTableNameInSQL(test);
//        System.out.println("tname ==== " + tname);
//        System.out.println(test.replaceFirst(tname, dest));
        
//        System.out.println("获得表名:" + findTableNameInSQL("create table if not exists REC_MAIN_CONSUME(cstaccfc BIGINT"));
//        System.out.println("获得表名:" + findTableNameInSQL("create table REC_MAIN_CONSUME(cstaccfc BIGINT"));
        
////        String sql = "CREATE INDEX BASE_AREA_VER_INX ON BASE_AREA (ver)";
//        String sql = "CREATE INDEX  BASE_AREA_VER_INX  ON BASE_AREA (ver)";
//        sql = sql.trim().toLowerCase();
//        System.out.println("获得索引名:" + findIndexNameInSQL(sql));
        
//        System.out.println("数据库名字1 = " + getMySQLSchemaName("walkersoft-share-marks?characterEncoding=UTF-8"));
//        System.out.println("数据库名字2 = " + getMySQLSchemaName("test"));
//        System.out.println("数据库名字3 = " + getMySQLSchemaName("walkersoft-share-marks?characterEncoding=UTF-8&code=u"));
        
        System.out.println("" + (1025 % 1024));
        System.out.println(findTableNameInIndex("create index base_area_ver_inx_44 on base_area (ver) "));
    }
}