-
Notifications
You must be signed in to change notification settings - Fork 1
/
cli.py
258 lines (224 loc) · 10.2 KB
/
cli.py
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
import cmd
import os
from queryparse import parse_query
class CLI(cmd.Cmd):
intro = """\nWelcome to Roma Jay Data Base (RJDB) :D\n\nMake sure to USEDB before you try MAKE, EDIT, FETCH, or DROP!\nType \'help\' or \'help [command]\' without quotes to learn more about the query language.\n"""
prompt = 'RJDB > '
def __init__(self, current_db=None):
super(CLI, self).__init__()
self.current_db = current_db
def onecmd(self, line):
"""Interpret the argument as though it had been typed in response
to the prompt.
This may be overridden, but should not normally need to be;
see the precmd() and postcmd() methods for useful execution hooks.
The return value is a flag indicating whether interpretation of
commands by the interpreter should stop.
"""
cmd, arg, line = self.parseline(line)
if not line:
return self.emptyline()
if cmd is None:
return self.default(line)
self.lastcmd = line
if line == 'EOF' :
self.lastcmd = ''
if cmd == '':
return self.default(line)
else:
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
try:
func = getattr(self, 'do_' + cmd.lower())
except AttributeError:
return self.default(line)
return func(arg)
def do_makedb(self, user_input_query):
'''
Use this keyword at the beginning of a query to
create a new database.
Syntax: MAKEDB REL/NOSQL dbname
'''
user_input_query = user_input_query.strip().split(" ")
if self.current_db is not None:
if user_input_query[0].upper() == "REL":
os.chdir("..")
os.chdir("../DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("..")
os.chdir("../DSCI-551-Final-Proj-NoSQL")
else:
if user_input_query[0].upper() == "REL":
os.chdir("../DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("../DSCI-551-Final-Proj-NoSQL")
if os.path.exists(user_input_query[1]):
print("DB name already exists! Please use the existing DB or make a DB with a different name.")
else:
os.mkdir("./" + user_input_query[1])
if user_input_query[0].upper() == "REL":
print("Created relational DB ", user_input_query[1])
elif user_input_query[0].upper() == "NOSQL":
print("Created non-relational DB ", user_input_query[1])
def do_usedb(self, user_input_query):
"""
Use this keyword at the beginning of a query to
use an existing database.
Syntax: USEDB REL/NOSQL dbname
"""
user_input_query = user_input_query.strip().split(" ")
if self.current_db is not None:
if user_input_query[0].upper() == "REL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-NoSQL")
if not os.path.exists(user_input_query[1]):
print("DB does not exist!")
else:
os.chdir("./" + user_input_query[1])
self.current_db = user_input_query[1]
print("Using DB " + user_input_query[1])
def do_dropdb(self, user_input_query):
"""
Use this keyword at the beginning of a query to
drop an existing database.
Syntax: DROPDB REL/NOSQL dbname
"""
user_input_query = user_input_query.strip().split(" ")
if user_input_query[1] == self.current_db:
self.current_db = None
if user_input_query[0].upper() == "REL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-NoSQL")
elif self.current_db is not None:
if user_input_query[0].upper() == "REL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-NoSQL")
else:
if user_input_query[0].upper() == "REL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-Rel")
elif user_input_query[0].upper() == "NOSQL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-NoSQL")
if user_input_query[1] not in os.listdir('.'):
print("DB does not exist!")
return
else:
for filename in os.listdir("./" + user_input_query[1]):
os.remove("./" + user_input_query[1] + filename)
os.rmdir("./" + user_input_query[1])
if user_input_query[0].upper() == "REL":
print("Dropped relational DB", user_input_query[1])
elif user_input_query[0].upper() == "NOSQL":
print("Dropped non-relational DB", user_input_query[1])
def do_showdb(self, user_input_query):
"""
Use this keyword at the beginning of a query to
show all databases in the DBMS. Do this BEFORE using
the USEDB command.
Syntax: SHOWDB REL/NOSQL
"""
if user_input_query.upper() == "REL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-Rel")
elif user_input_query.upper() == "NOSQL":
os.chdir("..")
os.chdir("./DSCI-551-Final-Proj-NoSQL")
for filename in os.listdir("."):
if os.path.isdir("./" + filename) and not filename.startswith("_") and not filename.startswith(".") and not filename=="table":
print(filename)
def do_make(self, user_input_query):
"""
Use this keyword at the beginning of a query
to make a new table/document within the current database.
Relational:
Syntax for MAKE (new table):
MAKE tablename COLUMNS col1=dtype1, col2=dtype2, col3=dtype3...
Syntax for MAKE COPY (existing table):
MAKE COPY tablename1 tablename2
NoSQL:
Syntax for MAKE (new document):
MAKE docname NODES node1=dtype1, node2=dtype2, node3=dtype3...
Syntax for MAKE COPY (existing document):
MAKE COPY docname1 docname2
* Supported datatypes are int, float, and str.
* Relational db also supports datetime64.
* You MUST type datatypes exactly as written here. No quotes.
* If using MAKE COPY, do not use COLUMNS/NODES.
* MAKE COPY will only copy the table/document's schema, not its contents.
"""
user_input_query = "MAKE " + user_input_query
return parse_query(user_input_query, self.current_db)
def do_edit(self, user_input_query):
"""
Use this keyword at the beginning of a query
to edit an existing table within the current database,
including insert, update, and delete operations.
General syntax:
EDIT tablename INSERT/UPDATE/DELETE record
Syntax for INSERT (one record at a time):
EDIT tablename/docname INSERT [nodename=newnode] col1/node1=x, col2/node2=y, col3/node3=z...
Syntax for INSERT (whole file):
EDIT tablename/docname INSERT FILE filepath
Syntax for UPDATE:
EDIT tablename/docname UPDATE id=rownum/nodename=node, col3=abc, col5=xyz...
Syntax for DELETE:
EDIT tablename/docname DELETE id=rownum/nodename=node...
* When using INSERT FILE, do not wrap the filepath in quotes.
* You must specify nodename when editing a non-relational document.
"""
user_input_query = "EDIT " + user_input_query
return parse_query(user_input_query, self.current_db)
def do_fetch(self, user_input_query):
"""
Use this keyword at the beginning of a query to
fetch existing table and perform aggregation, bunching,
filtering, sorting, or merging operations on specified columns.
Relational:
Syntax: FETCH tablename [COLUMNS] [column(s)] [AGGREGATION FUNCTION] [column] [BUNCH/SORT] [column] [MERGE] [tablename2] [INCOMMON] [mergingcol] [HAS] [column(s)]
NoSQL:
Syntax: FETCH docname [NODES] [node(s)] [AGGREGATION FUNCTION] [node] [BUNCH/SORT] [node] [MERGE] [docname2] [INCOMMON] [mergingnode] [HAS] [node(s)]
* Brackets indicate optional query parameters.
* Possible aggregation functions are TOTALNUM, SUM, MEAN, MIN, and MAX.
* Keywords should specifically be in the order of
COLUMNS/NODES --> TOTALNUM/SUM/MEAN/MIN/MAX --> BUNCH --> SORT --> MERGE --> HAS
"""
user_input_query = "FETCH " + user_input_query
return parse_query(user_input_query, self.current_db)
def do_drop(self, user_input_query):
"""
Use this keyword at the beginning of a query to
drop a table from the current database.
Syntax: DROP tablename
"""
user_input_query = "DROP " + user_input_query
return parse_query(user_input_query, self.current_db)
def do_show(self, user_input_query):
"""
Use this keyword to show all tables in the current DB.
* Make sure you're in a DB first, using USEDB.
"""
if "Rel" in os.getcwd():
for filename in os.listdir("./table"):
print(" ", filename[:-4])
elif "NoSQL" in os.getcwd():
for filename in os.listdir("./document"):
print(" ", filename[:-5])
def do_exit(self, *args):
"""
Use this keyword by itself to exit the command line interface.
"""
print("\nBye\n")
return True
if __name__ == "__main__":
CLI().cmdloop()