├── .idea
├── markdown-navigator-enh.xml
├── markdown-navigator.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── CHANGELOG.md
├── MyDatabase.iml
├── README.md
├── out
└── production
│ └── MyDatabase
│ ├── META-INF
│ └── MyDatabase.kotlin_module
│ └── sdnu
│ └── machi
│ ├── Create.class
│ ├── Describe.class
│ ├── Drop.class
│ ├── Format.class
│ ├── Help.class
│ ├── Input.class
│ ├── Insert.class
│ ├── Quit.class
│ ├── SQLConstant.class
│ ├── Select.class
│ ├── Show.class
│ ├── SqlAnalysis.class
│ ├── Start.class
│ ├── TableGenerator.class
│ ├── Use.class
│ └── Utils.class
└── src
└── sdnu
└── machi
├── Create.java
├── Describe.java
├── Drop.java
├── Format.java
├── Help.java
├── Input.java
├── Insert.java
├── Quit.java
├── SQLConstant.java
├── Select.java
├── Show.java
├── SqlAnalysis.java
├── Start.java
├── TableGenerator.java
├── Use.java
└── Utils.java
/.idea/markdown-navigator-enh.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
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 | C:\Users\DELL\AppData\Roaming\Subversion
141 |
142 |
143 |
144 |
145 | 1576905016659
146 |
147 |
148 | 1576905016659
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 | 1578727760631
176 |
177 |
178 |
179 | 1578727760631
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 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 更新日志
2 |
3 | ### 1.1
4 |
5 | 实现了仿照MySQL命令行的输入形式,在控制台输入命令后以";"作为命令的结束,并且实现了获取命令后将命令格式化,如去掉多余空格等.
6 |
7 | ### 1.2
8 |
9 | 实现了create database 数据库名称;命令.
10 |
11 | ### 1.3
12 |
13 | 实现了show databases;命令.
14 |
15 | ### 1.4
16 |
17 | 实现了show table;命令以及create table的部分命令,修复了指令识别的一个bug.
18 |
19 | ### 1.5
20 |
21 | 实现了create table 表名(.......);指令.
22 |
23 | 在该数据库中,默认使用文本文件存储表,文本文件的前三行存放表的控制信息,之后的行用来存储数据信息(这部分还未实现,之后会慢慢实现),其中第一行存放列名,第二行存放列的数据类型,第三行用来存放其余控制信息(像not null之类的).实现该部分时,比较麻烦的是对输入命令的解析,需要提取出需要的各个部分,这里主要使用正则表达式和String类的相关方法.
24 |
25 | ### 1.6
26 |
27 | 实现了describe 表名;指令.
28 |
29 | 打印表的相关控制信息,这部分自己实现的并不好,主要是没有把一些控制信息详细的分类而都放在了打印出来的最后一列.之后可能还会改进.
30 |
31 | 其实进行到这的时候,自己对于数据库最基本的存储方面有了一定的理解,知道在实际写一个DBMS时那部分是最难实现的,但是由于这些都是自己摸索这些的,当然也有一位大佬的帮助(站在巨人的肩膀上),所以在实现的过程中没有考虑到效率的问题,只是做出来能用.
32 |
33 | ### 1.7
34 |
35 | 实现了insert into 表名 (字段) values (值);
36 | 这部分基本对应存储方面实现了,但是对于各个字段的类型检查没有实现.
37 |
38 | ### 1.8
39 |
40 | 实现了select * from 表名;
41 | 对于select语句只实现了这一种查询方式,之后可能会再加上where子句的查询方式.查询是数据库操作中最复杂的一部分,所以感觉自己还是太菜,对于其他查询方式没有好的实现方法.
42 |
43 | ### 1.9
44 |
45 | 实现了drop database 数据库名; 和 drop table 表名;
46 |
47 | ### 最后
48 |
49 | 写到这里最基本的东西已经写完了,这个控制台DBMS也就告一段落了,之后打算写一篇博文来总结一下写这个程序的整个过程.
50 | 算是尊重作者劳动吧,希望大家在Fork前先点star.对这个程序有什么问题或者想要讨论更好的实现的,可以通过我GitHub上的邮箱来联系我,希望大家互相学习.
--------------------------------------------------------------------------------
/MyDatabase.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MyDatabase
2 | 使用Java实现一个简单的数据库管理系统.
3 |
4 | ## 配置及总结
5 |
6 | 见博客园: [博文]()
7 |
8 | ## 更新日志
9 |
10 | [CHANGELOG](CHANGELOG.md)
11 |
12 | ## 最后
13 |
14 | 如果感觉不错,就点个star吧!
15 |
16 |
--------------------------------------------------------------------------------
/out/production/MyDatabase/META-INF/MyDatabase.kotlin_module:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Create.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Create.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Describe.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Describe.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Drop.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Drop.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Format.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Format.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Help.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Help.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Input.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Input.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Insert.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Insert.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Quit.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Quit.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/SQLConstant.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/SQLConstant.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Select.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Select.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Show.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Show.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/SqlAnalysis.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/SqlAnalysis.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Start.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Start.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/TableGenerator.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/TableGenerator.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Use.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Use.class
--------------------------------------------------------------------------------
/out/production/MyDatabase/sdnu/machi/Utils.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/machi12/MyDatabase/986cd1ae4d84a31b113fdfbae6effa226f392fe3/out/production/MyDatabase/sdnu/machi/Utils.class
--------------------------------------------------------------------------------
/src/sdnu/machi/Create.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.*;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | /**
10 | * @ Description : 以create开头的sql命令
11 | * @ Author : 马驰
12 | * @ CreateDate : 2019/12/27 10:25
13 | */
14 | public class Create {
15 |
16 | private static final String path = SQLConstant.getPath();
17 |
18 | private static String tName = "";
19 |
20 | /**
21 | * 创建数据库,一个文件夹代表一个数据库
22 | * @param sql
23 | */
24 | public static void createSql(String sql){
25 | //System.out.println("create语句识别成功");
26 | //判断是否为数据库创建方法
27 | boolean b = sql.contains(" database ");
28 | if(b){
29 | String dbName = sql.substring(16, sql.length()-1);
30 | //System.out.println(dbName);
31 | createDir(dbName);
32 | //System.out.println("Query OK");
33 | }
34 | //判断是否为创建表格的方法
35 | else{
36 | boolean c = sql.contains(" table ");
37 | if(c){
38 | //System.out.println(tName);
39 | //判断输入语句的括号是否匹配
40 | if(Utils.bracketMatch(sql)) {
41 | createTable(sql);
42 | //System.out.println("Query OK");
43 | }
44 | else{
45 | System.out.println("ERROR: 语句有错误");
46 | Input.get();
47 | }
48 | }
49 | }
50 | }
51 |
52 | /**
53 | * 创建文件夹的方法
54 | * @param dbName
55 | */
56 | private static void createDir(String dbName){
57 | File file = new File(SQLConstant.getPath() + "\\" + dbName);
58 | if(!file.exists()){
59 | file.mkdir();
60 | System.out.println("Query OK");
61 | Input.get();
62 | }
63 | else{
64 | System.out.println("ERROR: database exists");
65 | Input.get();
66 | }
67 | }
68 |
69 | /**
70 | * @Description :创建表格的方法,使用txt文件存储表
71 | * @author : 马驰
72 | * @param : sql 输入的sql语句
73 | * @return : 无
74 | */
75 | private static void createTable(String sql){
76 | //获取当前数据库所在路径
77 | String tablePath = SQLConstant.getNowPath();
78 |
79 | //得到表名
80 | int index = sql.indexOf("(");
81 | if(index != -1){
82 | //System.out.println(index);
83 | tName = sql.substring(13, index) + ".txt";
84 | tName.trim();
85 | //System.out.println("创建表格方法已经执行");
86 |
87 | //创建表
88 | File table = new File(tablePath, tName);
89 | if (!table.exists()) {
90 |
91 | //创建表,以一个文本文件表示一个表
92 | try {
93 | table.createNewFile();
94 | } catch (IOException e) {
95 | e.printStackTrace();
96 | }
97 |
98 | //提取sql语句中关于表中字段的信息
99 | //获取分隔符
100 | String sep = SQLConstant.getSeparate();
101 | //System.out.println(sql);
102 | //遍历整个sql语句,如果原文本中存在分隔符,则在分隔符前再加一个分隔符,相当于转义
103 | String str = sql.replaceAll(sep + "", sep + sep);
104 | //System.out.println(str);
105 | //提取出两个括号之间的内容
106 | Pattern pattern = Pattern.compile("\\(.*\\)");
107 | Matcher matcher = pattern.matcher(sql);
108 | String s = "";
109 | if (matcher.find()) {
110 | s = matcher.group(0);
111 | //System.out.println(s);
112 | }
113 | //分别提取每个字段的内容
114 | String s1 = s.substring(1, s.length() - 1);
115 | //System.out.println(s1);
116 | String[] strings = s1.split(",");
117 | //分别存放三行的信息
118 | //String[] strings1 = new String[strings.length];
119 | //String[] strings2 = new String[strings.length];
120 | //String[] strings3 = new String[strings.length];
121 | List list1 = new ArrayList<>();
122 | List list2 = new ArrayList<>();
123 | List list3 = new ArrayList<>();
124 | //第一行存取列名,第二行存取类型,第三行存取剩余的说明信息
125 | for(String s2: strings){
126 | String s3 = s2.trim();
127 | String[] strings1 = s3.split(" ");
128 | list1.add(strings1[0]);
129 | list2.add(strings1[1]);
130 | for(int i = 2; i < strings1.length; i++){
131 | //list3.add(strings1[i]);
132 | if(strings1[i].equals("not") && strings1[i+1].equals("null")){
133 | list3.add("not null");
134 | i++;
135 | }
136 | else{
137 | list3.add(strings1[i]);
138 | }
139 | }
140 | //System.out.println(s3);
141 | }
142 | // System.out.println("------------");
143 | // for(String a:list1){
144 | // System.out.println(a);
145 | // }
146 | // System.out.println("-----------------");
147 | // for(String a:list2){
148 | // System.out.println(a);
149 | // }
150 | // System.out.println("-----------------");
151 | // for(String a:list3){
152 | // System.out.println(a);
153 | // }
154 |
155 |
156 |
157 | //向表中写入字段信息
158 | writeFile(list1);
159 | writeFile(list2);
160 | writeFile(list3);
161 | System.out.println("Query OK");
162 | }
163 | else{
164 | System.out.println("ERROR: 该表已经存在");
165 | }
166 |
167 |
168 | //sdnu.machi.Input.get();
169 | }
170 | else{
171 | System.out.println("ERROR: 语句有错误");
172 | //sdnu.machi.Input.get();
173 | }
174 |
175 | Input.get();
176 | }
177 |
178 | /**
179 | * @Description : 将字符串数组写入文件
180 | * @author : 马驰
181 | * @param : list 需要写入的字符串列表
182 | * @return : 无
183 | */
184 | private static void writeFile(List list){
185 | //将字符串数组连接成一个字符串
186 | String str = "";
187 | //System.out.println(str);
188 | //获取分隔符
189 | String sep = SQLConstant.getSeparate();
190 | //获取当前表的路径
191 | String path = SQLConstant.getNowPath();
192 | String nowPath = path + "\\" + tName;
193 | //拼接字符串
194 | for(String s1: list){
195 | //System.out.print(s1 + "");
196 | str += s1 + sep;
197 | }
198 | //System.out.println();
199 | //System.out.println(str);
200 | //System.out.println(str);
201 |
202 |
203 | try{
204 | FileOutputStream fos = new FileOutputStream(
205 | new File(nowPath), true);
206 | str += "\r\n";
207 | fos.write(str.getBytes());
208 | fos.close();
209 | }catch (IOException e){
210 | e.printStackTrace();
211 | }
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Describe.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | /**
11 | * @ Description : 实现describe命令
12 | * @ Author : 马驰
13 | * @ CreateDate : 2019/12/31 17:24
14 | */
15 | public class Describe {
16 |
17 | public static void describeSql(String sql){
18 |
19 | //得到分隔符
20 | String sep = SQLConstant.getSeparate();
21 |
22 | //获得当前路径,到数据库文件夹
23 | String path = SQLConstant.getNowPath();
24 | String tableName = sql.substring(9, sql.length()-1);
25 |
26 | //当前表的完整路径
27 | String nowPath = path + "\\" + tableName + ".txt";
28 | List list = getTableDescribe(nowPath);
29 |
30 | //对获取的list进行处理并打印
31 | List> lists = new ArrayList<>();
32 | String[] s1 = list.get(0).split(sep);
33 | String[] s2 = list.get(1).split(sep);
34 | String[] s3 = list.get(2).split(sep);
35 | for(int i = 0; i < s1.length; i++){
36 | List list1 = new ArrayList<>();
37 | list1.add(s1[i]);
38 | list1.add(s2[i]);
39 | list1.add(s3[i]);
40 | lists.add(list1);
41 | }
42 | List list4 = new ArrayList<>();
43 | list4.add("Filed");
44 | list4.add("Type");
45 | list4.add("Extra");
46 |
47 | System.out.println(TableGenerator.generateTable(list4, lists));
48 |
49 |
50 | Input.get();
51 | }
52 |
53 | /**
54 | * @Description : 从文本文件(表)的前三行读取表的描述信息
55 | * @author : 马驰
56 | * @param : path 当前表的路径
57 | * @return : List 将表的描述信息封装到List中
58 | */
59 | private static List getTableDescribe(String path){
60 |
61 | List list = new ArrayList<>();
62 |
63 | //对文件进行读取
64 | try {
65 | File file = new File(path);
66 | FileReader reader = new FileReader(file);
67 | BufferedReader bufferedReader = new BufferedReader(reader);
68 | //StringBuilder sb = new StringBuilder(); //定义一个字符串缓存
69 | String s = "";
70 | int index = 1;
71 | while((s = bufferedReader.readLine()) != null && index < 4){
72 | index++;
73 | list.add(s);
74 | //System.out.println(s);
75 | }
76 | bufferedReader.close();
77 | }catch(IOException e){
78 | e.printStackTrace();
79 | }
80 |
81 | return list;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Drop.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.File;
4 | import java.util.List;
5 | import java.util.Scanner;
6 |
7 | /**
8 | * @ Description : 实现drop指令,目前只实现了drop database 数据库名; 和 drop table 表名;
9 | * @ Author : 马驰
10 | * @ CreateDate : 2020/1/13 9:01
11 | */
12 | public class Drop {
13 |
14 | private static String sep; //分隔符
15 | private static String dbName; //数据库名称
16 | private static String tableName; //表名
17 |
18 | /**
19 | * @Description : 在该方法中对drop命令进行分类,并执行特定的子命令
20 | * @author : 马驰
21 | * @param : sql 输入的sql语句
22 | * @return : void
23 | */
24 | public static void dropSql(String sql){
25 | //得到分隔符
26 | sep = SQLConstant.getSeparate();
27 |
28 | //System.out.println("machi");
29 | //如果是删除数据库的操作
30 | if(sql.contains(" database ")){
31 | dbName = sql.substring(14, sql.length()-1);
32 | //删除该数据库
33 | dropDatabase();
34 | }
35 | else if(sql.contains(" table ")){
36 | tableName = sql.substring(11, sql.length()-1);
37 | //删除该表
38 | dropTable();
39 | }
40 | else{
41 | System.out.println("ERROR: 无法识别该指令");
42 | }
43 |
44 | }
45 |
46 | /**
47 | * @Description : 对数据库的删除操作
48 | * @author : 马驰
49 | * @param :
50 | * @return :
51 | */
52 | private static void dropDatabase(){
53 | //获得当前路径
54 | String path = SQLConstant.getNowPath();
55 | //判断是否有该数据库
56 | List dbList = Utils.getAllDatabase(path);
57 |
58 | boolean a = dbList.contains(dbName);
59 | if(a) {
60 |
61 | boolean b = confirm();
62 | if (b) {
63 | String nowPath = path + "\\" + dbName;
64 | deleteFile(new File(nowPath));
65 | System.out.println("Query OK");
66 | }
67 | else{
68 | System.out.println("撤回成功,数据库未被删除");
69 | }
70 | }
71 | else{
72 | System.out.println("ERROR: 该数据库不存在");
73 | }
74 |
75 | Input.get();
76 | }
77 |
78 | /**
79 | * 先根遍历序递归删除文件夹
80 | *
81 | * @param dirFile 要被删除的文件或者目录
82 | * @return 删除成功返回true, 否则返回false
83 | */
84 | public static boolean deleteFile(File dirFile) {
85 | // 如果dir对应的文件不存在,则退出
86 | if (!dirFile.exists()) {
87 | return false;
88 | }
89 |
90 | if (dirFile.isFile()) {
91 | return dirFile.delete();
92 | } else {
93 |
94 | for (File file : dirFile.listFiles()) {
95 | deleteFile(file);
96 | }
97 | }
98 |
99 | return dirFile.delete();
100 | }
101 |
102 | /**
103 | * @Description : 确认是否删除
104 | * @author : 马驰
105 | * @param :
106 | * @return : 确认为Yes则返回true,否则返回false
107 | */
108 | private static boolean confirm(){
109 | System.out.println("确认删除: \"Yes\" or \"No\"");
110 | System.out.print("请输入: ");
111 | Scanner scanner = new Scanner(System.in);
112 | String input = scanner.nextLine().trim().toLowerCase();
113 | if("yes".equals(input)){
114 | return true;
115 | }
116 | else if("no".equals(input)){
117 | return false;
118 | }
119 | else{
120 | System.out.println("输入的单词无法识别");
121 | return false;
122 | }
123 | }
124 |
125 | /**
126 | * @Description : 删除数据表
127 | * @author : 马驰
128 | * @param :
129 | * @return :
130 | */
131 | private static void dropTable(){
132 | //获得当前路径
133 | String path = SQLConstant.getNowPath();
134 | //判断是否有该数据表
135 | List tableList = Utils.getAllTables(path);
136 |
137 | boolean a = tableList.contains(tableName);
138 | if(a) {
139 |
140 | boolean b = confirm();
141 | if (b) {
142 | String nowPath = path + "\\" + tableName + ".txt";
143 | File file = new File(nowPath);
144 | file.delete();
145 | System.out.println("Query OK");
146 | }
147 | else{
148 | System.out.println("撤回成功,数据库未被删除");
149 | }
150 | }
151 | else{
152 | System.out.println("ERROR: 该数据库不存在");
153 | }
154 |
155 | Input.get();
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Format.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | /**
4 | * @ Description : 格式化输入,去掉输入中多余的空格以及别的与内容无关的符号
5 | * @ Author : 马驰
6 | * @ CreateDate : 2019/12/26 16:10
7 | */
8 | public class Format {
9 |
10 | public static String sqlFromat(String input){
11 | String sql = "";
12 | //去掉最后的;和空格
13 | //sql = input.replaceAll(";", "");
14 | //去掉字符串前后两端的空格
15 | sql = input.trim();
16 | //将字符串都转化为小写
17 | String string = sql.toLowerCase();
18 | //通过正则表达式将多个空格转换为一个空格
19 | String str = string.replaceAll("\\s{2,}", " ");
20 | //去掉;前的空格
21 | String s = str.replaceFirst("( ;)$", ";");
22 | //System.out.println(s);
23 | return s;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Help.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | /**
4 | * @ Description : Help帮助
5 | * @ Author : 马驰
6 | * @ CreateDate : 2019/12/27 10:32
7 | */
8 | public class Help {
9 |
10 | /**
11 | * 帮助方法,列出当前支持的sql语句
12 | */
13 | public static void help(){
14 | System.out.println("1.create database 数据库名: 用于创建数据库");
15 | System.out.println("2.show databases: 列出目前已经创建的数据库");
16 | Input.get();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Input.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.util.Scanner;
4 |
5 | /**
6 | * @ Description : 获取输入的命令
7 | * @ Author : 马驰
8 | * @ CreateDate : 2019/12/26 23:34
9 | */
10 | public class Input {
11 |
12 | public static void get(){
13 | Scanner scanner = new Scanner(System.in);
14 | String input = "";
15 | //一个完整的语句输入默认以;结尾
16 | do{
17 | System.out.print(">>");
18 | input += " " + scanner.nextLine();
19 | //解决;后有多个空格不能结束的问题
20 | input = input.replaceFirst("(\\s+)$", "");
21 | //System.out.println(input);
22 | }while(!input.endsWith(";"));
23 |
24 | //System.out.println(input);
25 | //格式化字符串
26 | String sql = Format.sqlFromat(input);
27 | //System.out.println(sql);
28 | //System.out.println("----------");
29 | SqlAnalysis.analysis(sql);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Insert.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.*;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | /**
10 | * @ Description : 实现insert命令
11 | * @ Author : 马驰
12 | * @ CreateDate : 2019/12/31 22:19
13 | */
14 | public class Insert {
15 |
16 | private static String tableName;
17 |
18 | public static void insertSql(String sql){
19 | int index = sql.indexOf("(");
20 | String name = sql.substring(12, index);
21 | tableName = name.trim();
22 | //System.out.println(tableName);
23 |
24 | //判断是否有该表
25 | String path = SQLConstant.getNowPath();
26 | List list = Utils.getAllTables(path);
27 | boolean b = list.contains(tableName);
28 | if(b) {
29 |
30 | //得到当前路径
31 | String nowPath = path + "\\" + tableName + ".txt";
32 |
33 |
34 | //获取insert命令中两个括号中的内容
35 | List list1 = new ArrayList<>();
36 | Pattern pattern = Pattern.compile("\\(.*?\\)");
37 | Matcher matcher = pattern.matcher(sql);
38 | while (matcher.find()) {
39 | list1.add(matcher.group());
40 | //System.out.println(matcher.group());
41 | }
42 | // System.out.println(list1.size());
43 | // for(String s:list1){
44 | // System.out.println(s);
45 | // }
46 |
47 | //判断语句是否正确,根据()的数目
48 | //System.out.println(list.size());
49 | if (list1.size() != 2) {
50 | System.out.println("ERROR: 语句有错误");
51 | Input.get();
52 | } else {
53 | List columnName = getColumnName(nowPath, 1);
54 | List type = getColumnName(nowPath, 2);
55 | // for(String s: columnName){
56 | // System.out.println(s);
57 | // }
58 |
59 | String s1 = list1.get(0).substring(1, list1.get(0).length()-1).trim(); //第一个括号,字段
60 | String s2 = list1.get(1).substring(1, list1.get(1).length()-1).trim(); //第二个括号,值
61 |
62 | //对字符串进行转义
63 | //String s11 = transMean(s1);
64 | String s22 = transMean(s2);
65 |
66 | String[] key = s1.split(",");
67 | String[] value = s22.split(",");
68 |
69 | for(int i = 0; i < key.length; i++){
70 | key[i] = key[i].trim();
71 | }
72 |
73 | for(int i = 0; i < value.length; i++){
74 | value[i] = value[i].trim();
75 | }
76 |
77 | //String s = ""; //最终要存储的字符串对象
78 |
79 | // System.out.println(s1);
80 | // System.out.println(s2);
81 |
82 | // for(String k: key){
83 | // System.out.println(k);
84 | // }
85 | //
86 | // for(String k: value){
87 | // System.out.println(k);
88 | // }
89 |
90 |
91 | String sep = SQLConstant.getSeparate();
92 | int len = columnName.size();
93 | String s = ""; //最终要存储的字符串对象
94 | int flag1 = 0;
95 | for(int i = 0; i < len; i++){
96 | String s3 = columnName.get(i);
97 | int flag = 0;
98 | for(int j = 0; j < key.length; j++){
99 | if(key[j].equals(s3)){
100 | //System.out.println(type.get(i) + " " + value[j]);
101 | String s4 = check(type.get(i), value[j]);
102 | if(s4 == null){
103 | flag1 = 1;
104 | break;
105 | }
106 | else if(s4 == "machi"){
107 | s += value[j] + sep;
108 | flag = 1;
109 | }
110 | else {
111 | s += s4 + sep;
112 | flag = 1;
113 | }
114 | }
115 | }
116 | if(flag == 0){
117 | s += "null" + sep;
118 | }
119 | if(flag1 == 1){
120 | break;
121 | }
122 | }
123 | //System.out.println(s);
124 | //System.out.println(flag1);
125 | if(flag1 == 0) {
126 | writeFile(s);
127 | System.out.println("Query OK");
128 | }
129 | Input.get();
130 | }
131 | }
132 | else{
133 | System.out.println("ERROR: 该表不存在");
134 | Input.get();
135 | }
136 |
137 | }
138 |
139 | /**
140 | * @Description : 获取该表的所有列名
141 | * @author : 马驰
142 | * @param : path 表的路径; i 需要读出第i行
143 | * @return : List 所有列名组成的列表
144 | */
145 | public static List getColumnName(String path, int i){
146 | List list = new ArrayList<>();
147 |
148 | //对文件进行读取
149 | try {
150 | File file = new File(path);
151 | FileReader reader = new FileReader(file);
152 | BufferedReader bufferedReader = new BufferedReader(reader);
153 | //StringBuilder sb = new StringBuilder(); //定义一个字符串缓存
154 | String s = "";
155 |
156 | int index = 0;
157 |
158 | //读取第i行
159 | while((s = bufferedReader.readLine()) != null){
160 | index++;
161 | if(index == i) {
162 | String sep = SQLConstant.getSeparate(); //获取分隔符
163 | String[] strings = s.split(sep);
164 | for(String s1:strings){
165 | list.add(s1);
166 | }
167 | return list;
168 | //System.out.println(s);
169 | }
170 | }
171 |
172 | // //只读取第一行,第一行存放的是列名
173 | // if((s = bufferedReader.readLine()) != null){
174 | // String sep = SQLConstant.getSeparate(); //获取分隔符
175 | // String[] strings = s.split(sep);
176 | // for(String s1:strings){
177 | // list.add(s1);
178 | // }
179 | // }
180 |
181 | bufferedReader.close();
182 | }catch(IOException e){
183 | e.printStackTrace();
184 | }
185 |
186 |
187 | return list;
188 | }
189 |
190 | /**
191 | * @Description : 对传入的字符串进行转义,如果字符串中有分隔符,则需要在分隔符前再加一个分隔符
192 | * @author : 马驰
193 | * @param : str 需要转义的字符串
194 | * @return : String 转义后的字符串
195 | */
196 | private static String transMean(String str){
197 | String sep = SQLConstant.getSeparate(); //分隔符
198 | String s = str.replaceAll(sep, sep + sep);
199 |
200 | return s;
201 | }
202 |
203 | /**
204 | * @Description : 将字符串写入数据库文件中
205 | * @author : 马驰
206 | * @param : s 需要写入的字符串,代表数据中的一行
207 | * @return : 无
208 | */
209 | private static void writeFile(String s){
210 | //获取分隔符
211 | String sep = SQLConstant.getSeparate();
212 | //获取当前表的路径
213 | String path = SQLConstant.getNowPath();
214 | String nowPath = path + "\\" + tableName + ".txt";
215 |
216 | //System.out.println();
217 | //System.out.println(str);
218 | //System.out.println(str);
219 |
220 |
221 | try{
222 | FileOutputStream fos = new FileOutputStream(
223 | new File(nowPath), true);
224 | s += "\r\n";
225 | fos.write(s.getBytes());
226 | fos.close();
227 | }catch (IOException e){
228 | e.printStackTrace();
229 | }
230 | }
231 |
232 | /**
233 | * @Description : 检查输入值的类型与之前定义字段的类型是否匹配
234 | * @author : 马驰
235 | * @param : type 该字段的数据类型; str 需要检查的字符串
236 | * @return : String 检查完后要返回的字符串,例如char类型的要去掉""
237 | */
238 | private static String check(String type, String str){
239 | boolean b = type.contains("char");
240 | //boolean c = type.contains("varchar");
241 | //System.out.println(b);
242 |
243 | if(b){
244 | Pattern pattern = Pattern.compile("\".*\"");
245 | Matcher matcher = pattern.matcher(str);
246 | if(matcher.find()){
247 | //System.out.println("this is machi");
248 | String s = str.replaceAll("\"", "");
249 | //System.out.println(s);
250 | return s;
251 | }
252 | else{
253 | System.out.println("ERROR: 输入值的格式错误");
254 | return null;
255 | }
256 | }
257 | else{
258 | return "machi";
259 | }
260 |
261 | }
262 |
263 | }
264 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Quit.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | /**
4 | * @ Description : quit命令,退出数据库管理系统
5 | * @ Author : 马驰
6 | * @ CreateDate : 2019/12/27 15:59
7 | */
8 | public class Quit {
9 |
10 | public static void quitSql(){
11 | System.out.println("Bye");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/sdnu/machi/SQLConstant.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | /**
4 | * @ Description : 与数据库相关的常量
5 | * @ Author : 马驰
6 | * @ CreateDate : 2019/12/27 10:27
7 | */
8 | public class SQLConstant {
9 |
10 | //数据库的根路径
11 | private static final String path = "E:\\MyDatabase";
12 |
13 | //数据库的当前路径
14 | private static String nowPath = path;
15 |
16 | //自定义的分隔符
17 | private static final String separate = "~";
18 |
19 | public static String getPath(){
20 | return path;
21 | }
22 |
23 | /**
24 | * @Description : 返回当前路径
25 | * @author : 马驰
26 | * @param : 无
27 | * @return : 无
28 | */
29 | public static String getNowPath(){
30 | return nowPath;
31 | }
32 |
33 | /**
34 | * @Description : 设置当前路径
35 | * @author : 马驰
36 | * @param : name 数据库名
37 | * @return : 无
38 | */
39 | public static void setNowPath(String name){
40 | nowPath = nowPath + "\\" + name;
41 | }
42 |
43 | public static String getSeparate(){
44 | return separate;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Select.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | /**
11 | * @ Description : 实现select语句
12 | * @ Author : 马驰
13 | * @ CreateDate : 2020/1/11 19:25
14 | */
15 | public class Select {
16 |
17 | /**
18 | * @Description : 实现select查询的主函数,目前只实现了select * from 表名;
19 | * @author : 马驰
20 | * @param : sql 输入的sql语句
21 | * @return : void
22 | */
23 | public static void selectSql(String sql){
24 |
25 | //得到分隔符
26 | String sep = SQLConstant.getSeparate();
27 |
28 | //获得当前路径,到数据库文件夹
29 | String path = SQLConstant.getNowPath();
30 | String tableName = sql.substring(14, sql.length()-1);
31 |
32 | //当前表的完整路径
33 | String nowPath = path + "\\" + tableName + ".txt";
34 |
35 | //获得表中的数据
36 | List list = getTableDescribe(nowPath);
37 |
38 | String restrict1 = sql.substring(7, 8);
39 |
40 | boolean b = tableName.contains(" ");
41 |
42 |
43 | if(!b && restrict1.equals("*")) {
44 |
45 |
46 | List columnName = Insert.getColumnName(nowPath, 1); //获得列名
47 |
48 | //处理表格中的数据,转化为List>
49 | List> lists = new ArrayList<>();
50 | int i = 0;
51 | for (String s : list) {
52 | List list1 = new ArrayList<>();
53 | String[] strings = list.get(i++).split(sep);
54 | for (String s1 : strings) {
55 | list1.add(s1);
56 | }
57 | lists.add(list1);
58 | }
59 |
60 | System.out.println(TableGenerator.generateTable(columnName, lists));
61 |
62 | System.out.println("Query OK");
63 |
64 | }
65 | else{
66 | System.out.println("ERROR: 目前的select命令不支持这种方式的查询");
67 | }
68 |
69 |
70 | Input.get();
71 |
72 | // for(String s:list){
73 | // System.out.println(s);
74 | // }
75 | }
76 |
77 | /**
78 | * @Description : 读出数据库中表中第3行中的数据,因为前三行存放的是表的控制信息,三行之后存放的是表的控制信息
79 | * @author : 马驰
80 | * @param : path 数据表的路径
81 | * @return : List 由数据行组成的列表
82 | */
83 | private static List getTableDescribe(String path){
84 |
85 | List list = new ArrayList<>();
86 |
87 | //对文件进行读取
88 | try {
89 | File file = new File(path);
90 | FileReader reader = new FileReader(file);
91 | BufferedReader bufferedReader = new BufferedReader(reader);
92 | //StringBuilder sb = new StringBuilder(); //定义一个字符串缓存
93 | String s = "";
94 | int index = 1;
95 | while((s = bufferedReader.readLine()) != null){
96 | index++;
97 | if(index > 4){
98 | list.add(s);
99 | }
100 | //System.out.println(s);
101 | }
102 | bufferedReader.close();
103 | }catch(IOException e){
104 | e.printStackTrace();
105 | }
106 |
107 | return list;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Show.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @ Description : 以show为开头的命令
8 | * @ Author : 马驰
9 | * @ CreateDate : 2019/12/27 10:36
10 | */
11 | public class Show {
12 |
13 | public static void showSql(String sql){
14 |
15 | //列出所有数据库
16 | boolean b = sql.endsWith(" databases;");
17 | if(b){
18 | String path = SQLConstant.getPath();
19 | List dbList = Utils.getAllDatabase(path);
20 | // for(int i = 0; i < dbList.size(); i++){
21 | // System.out.println(dbList.get(i));
22 | // }
23 | List db = new ArrayList<>();
24 | db.add("Database");
25 | List> list = new ArrayList<>();
26 | for(int i = 0; i < dbList.size(); i++){
27 | List ls = new ArrayList<>();
28 | ls.add(dbList.get(i));
29 | list.add(ls);
30 | }
31 | System.out.println(TableGenerator.generateTable(db, list));
32 | Input.get();
33 | }
34 |
35 | //列出所有该数据库下所有的表格
36 | else{
37 | boolean c = sql.endsWith(" tables;");
38 | if(c){
39 | String nowPath = SQLConstant.getNowPath();
40 | List tableList = Utils.getAllTables(nowPath);
41 | List list = new ArrayList<>();
42 |
43 | //获取数据库名
44 | int index = nowPath.lastIndexOf("\\");
45 | // System.out.println(nowPath);
46 | // System.out.println(index);
47 | // System.out.println(nowPath.length());
48 | String dbName = nowPath.substring(index+1, nowPath.length());
49 | //System.out.println(dbName);
50 | list.add(dbName);
51 |
52 | List> tList = new ArrayList<>();
53 | for(String t:tableList){
54 | List list1 = new ArrayList<>();
55 | list1.add(t);
56 | tList.add(list1);
57 | }
58 |
59 | System.out.println(TableGenerator.generateTable(list, tList));
60 | Input.get();
61 | }
62 | }
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/sdnu/machi/SqlAnalysis.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | /**
7 | * @ Description : 实现一个sql解析器,目前支持create, show, use, quit
8 | * @ Author : 马驰
9 | * @ CreateDate : 2019/12/26 17:03
10 | */
11 | public class SqlAnalysis {
12 |
13 | //private static String[] str;
14 | //private static final String path = "E:\\MyDatabase";
15 | //下面是目前支持的sql语句类型
16 | private static final String create = "create";
17 | private static final String help = "help";
18 | private static final String show = "show";
19 | private static final String use = "use";
20 | private static final String quit = "quit";
21 | private static final String describe = "describe";
22 | private static final String insert = "insert";
23 | private static final String select = "select";
24 | private static final String drop = "drop";
25 |
26 |
27 | public static void analysis(String sql){
28 | //str = sql.split(" ");
29 | String start = "";
30 | //正则表达式的匹配规则
31 | String regex = "^[a-z]+";
32 | Pattern pattern = Pattern.compile(regex);
33 | Matcher matcher = pattern.matcher(sql);
34 | //获取匹配值
35 | while(matcher.find()){
36 | start = matcher.group();
37 | }
38 |
39 | //根据第一个单词判断该语句的作用
40 | switch (start){
41 | case create:
42 | Create.createSql(sql);
43 | break;
44 | case help:
45 | Help.help();
46 | break;
47 | case show:
48 | Show.showSql(sql);
49 | break;
50 | case use:
51 | Use.useSql(sql);
52 | break;
53 | case quit:
54 | Quit.quitSql();
55 | break;
56 | case describe:
57 | Describe.describeSql(sql);
58 | break;
59 | case insert:
60 | Insert.insertSql(sql);
61 | break;
62 | case select:
63 | Select.selectSql(sql);
64 | break;
65 | case drop:
66 | Drop.dropSql(sql);
67 | break;
68 | default:
69 | System.out.println("输入的命令无法识别,可以输入help查看目前支持的sql语句");
70 | Input.get();
71 | break;
72 | }
73 | //System.out.println(start);
74 | }
75 |
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Start.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | /**
4 | * @ Description : 自定义数据库的主类
5 | * @ Author : 马驰
6 | * @ CreateDate : 2019/12/21 13:17
7 | */
8 | public class Start {
9 |
10 | public static void main(String[] args){
11 | Input.get();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/sdnu/machi/TableGenerator.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 生成表格的类, 仅对英文的表格有效
7 | *
8 | * @author Master_Joe
9 | *
10 | */
11 | public class TableGenerator {
12 |
13 | private static int PADDING_SIZE = 2;
14 | private static String NEW_LINE = "\n";
15 | private static String TABLE_JOINT_SYMBOL = "+";
16 | private static String TABLE_V_SPLIT_SYMBOL = "|";
17 | private static String TABLE_H_SPLIT_SYMBOL = "-";
18 |
19 | /**
20 | * 根据内容创建表格
21 | *
22 | * @param headersList
23 | * @param rowsList
24 | * @param overRiddenHeaderHeight
25 | * @return
26 | */
27 | public static String generateTable(List headersList, List> rowsList,
28 | int... overRiddenHeaderHeight) {
29 | StringBuilder stringBuilder = new StringBuilder();
30 |
31 | int rowHeight = overRiddenHeaderHeight.length > 0 ? overRiddenHeaderHeight[0] : 1;
32 |
33 | Map columnMaxWidthMapping = getMaximumWidhtofTable(headersList, rowsList);
34 |
35 | createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
36 | stringBuilder.append(NEW_LINE);
37 |
38 | for (int headerIndex = 0; headerIndex < headersList.size(); headerIndex++) {
39 | fillCell(stringBuilder, headersList.get(headerIndex), headerIndex, columnMaxWidthMapping);
40 | }
41 | stringBuilder.append(NEW_LINE);
42 | createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
43 |
44 | for (List row : rowsList) {
45 | for (int i = 0; i < rowHeight; i++) {
46 | stringBuilder.append(NEW_LINE);
47 | }
48 |
49 | for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) {
50 | fillCell(stringBuilder, row.get(cellIndex), cellIndex, columnMaxWidthMapping);
51 | }
52 | }
53 |
54 | stringBuilder.append(NEW_LINE);
55 | createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
56 | return stringBuilder.toString();
57 | }
58 |
59 | private static void fillSpace(StringBuilder stringBuilder, int length) {
60 | for (int i = 0; i < length - 1; i++) {
61 | stringBuilder.append(" ");
62 | }
63 | }
64 |
65 | private static void createRowLine(StringBuilder stringBuilder, int headersListSize,
66 | Map columnMaxWidthMapping) {
67 | for (int i = 0; i < headersListSize; i++) {
68 | if (i == 0) {
69 | stringBuilder.append(TABLE_JOINT_SYMBOL);
70 | }
71 |
72 | for (int j = 0; j < columnMaxWidthMapping.get(i) + PADDING_SIZE * 2; j++) {
73 | stringBuilder.append(TABLE_H_SPLIT_SYMBOL);
74 | }
75 | stringBuilder.append(TABLE_JOINT_SYMBOL);
76 | }
77 | }
78 |
79 | private static Map getMaximumWidhtofTable(List headersList, List> rowsList) {
80 | Map columnMaxWidthMapping = new HashMap<>();
81 |
82 | for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {
83 | columnMaxWidthMapping.put(columnIndex, 0);
84 | }
85 |
86 | for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {
87 |
88 | if (headersList.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex)) {
89 | columnMaxWidthMapping.put(columnIndex, headersList.get(columnIndex).length());
90 | }
91 | }
92 |
93 | for (List row : rowsList) {
94 |
95 | for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) {
96 |
97 | if (row.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex)) {
98 | columnMaxWidthMapping.put(columnIndex, row.get(columnIndex).length());
99 | }
100 | }
101 | }
102 |
103 | for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {
104 |
105 | if (columnMaxWidthMapping.get(columnIndex) % 2 != 0) {
106 | columnMaxWidthMapping.put(columnIndex, columnMaxWidthMapping.get(columnIndex) + 1);
107 | }
108 | }
109 |
110 | return columnMaxWidthMapping;
111 | }
112 |
113 | private static int getOptimumCellPadding(int cellIndex, int datalength, Map columnMaxWidthMapping,
114 | int cellPaddingSize) {
115 | if (datalength % 2 != 0) {
116 | datalength++;
117 | }
118 |
119 | if (datalength < columnMaxWidthMapping.get(cellIndex)) {
120 | cellPaddingSize = cellPaddingSize + (columnMaxWidthMapping.get(cellIndex) - datalength) / 2;
121 | }
122 |
123 | return cellPaddingSize;
124 | }
125 |
126 | private static void fillCell(StringBuilder stringBuilder, String cell, int cellIndex,
127 | Map columnMaxWidthMapping) {
128 |
129 | int cellPaddingSize = getOptimumCellPadding(cellIndex, cell.length(), columnMaxWidthMapping, PADDING_SIZE);
130 |
131 | if (cellIndex == 0) {
132 | stringBuilder.append(TABLE_V_SPLIT_SYMBOL);
133 | }
134 |
135 | fillSpace(stringBuilder, 2);
136 | stringBuilder.append(cell);
137 | if (cell.length() % 2 != 0) {
138 | stringBuilder.append(" ");
139 | }
140 |
141 | fillSpace(stringBuilder, cellPaddingSize);
142 | fillSpace(stringBuilder, cellPaddingSize);
143 | fillSpace(stringBuilder, 2);
144 |
145 | stringBuilder.append(TABLE_V_SPLIT_SYMBOL);
146 | }
147 | }
--------------------------------------------------------------------------------
/src/sdnu/machi/Use.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @ Description : 对use命令进行解析
7 | * @ Author : 马驰
8 | * @ CreateDate : 2019/12/27 15:44
9 | */
10 | public class Use {
11 |
12 | public static void useSql(String sql){
13 | String dbName = sql.substring(4, sql.length()-1);
14 | //System.out.println(dbName);
15 | String path = SQLConstant.getPath();
16 |
17 | List dbList = Utils.getAllDatabase(path);
18 |
19 | //判断使用的数据库是否存在
20 | boolean b = dbList.contains(dbName);
21 | if(b){
22 | SQLConstant.setNowPath(dbName);
23 | System.out.println("Database changed");
24 | Input.get();
25 | }
26 | else{
27 | System.out.println("ERROR: 数据库不存在");
28 | Input.get();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/sdnu/machi/Utils.java:
--------------------------------------------------------------------------------
1 | package sdnu.machi;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Stack;
7 |
8 | /**
9 | * @ Description : 数据库中的工具类
10 | * @ Author : 马驰
11 | * @ CreateDate : 2019/12/27 10:48
12 | */
13 | public class Utils {
14 |
15 | /**
16 | * @Description : 获取所有数据库名称,查看路径下所有文件夹
17 | * @author : 马驰
18 | * @param : path 路径
19 | * @return :
20 | * @date : 2019/12/27 10:52
21 | */
22 | public static List getAllDatabase(String path){
23 | List list = new ArrayList<>();
24 | File file = new File(path);
25 | File[] fileList = file.listFiles();
26 | for(int i = 0; i < fileList.length; i++){
27 | if(fileList[i].isDirectory()){
28 | list.add(fileList[i].getName());
29 | }
30 | }
31 | return list;
32 | }
33 |
34 | // public static void showPrint(String name){
35 | // System.out.println();
36 | // }
37 |
38 | /**
39 | * @Description : 判断输入语句的括号是否匹配
40 | * @author : 马驰
41 | * @param : sql 输入的sql语句
42 | * @return : 是否匹配
43 | */
44 | public static boolean bracketMatch(String sql){
45 | //建立堆栈
46 | Stack stack = new Stack<>();
47 |
48 | //将语句转为char,方便匹配
49 | char[] chars = sql.toCharArray();
50 | for(int i = 0; i < chars.length; i++){
51 | if(chars[i] == '('){
52 | stack.push("(");
53 | }
54 | else if(chars[i] == ')'){
55 | if(stack.empty()){
56 | return false;
57 | }
58 | else{
59 | stack.pop();
60 | }
61 | }
62 | }
63 | return true;
64 | }
65 |
66 | /**
67 | * @Description : 获取当前数据库下的所有表
68 | * @author : 马驰
69 | * @param : nowPath 当前路径
70 | * @return : 所有表名组成的列表
71 | */
72 | public static List getAllTables(String nowPath){
73 | List list = new ArrayList<>();
74 | File file = new File(nowPath);
75 | File[] fileList = file.listFiles();
76 | if(fileList != null){
77 | for(int i = 0; i < fileList.length; i++) {
78 | if (fileList[i].isFile()) {
79 | String name = fileList[i].getName();
80 | int index = name.lastIndexOf(".");
81 | String tableName = name.substring(0, index);
82 | list.add(tableName);
83 | }
84 | }
85 | }
86 | else{
87 |
88 | }
89 | return list;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------