Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#george's,iraklis',nikos' repo
<p align=center>
<img width="550" alt="mdblogo" src="https://user-images.githubusercontent.com/15364873/146045747-5dbdce9c-a70a-494b-8fdd-52ba932cdd19.png">
</p>
Expand Down
133 changes: 75 additions & 58 deletions mdb.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from miniDB.table import Table
from miniDB.database import Database
import os
import re
from pprint import pprint
Expand All @@ -7,8 +9,6 @@
import shutil
sys.path.append('miniDB')

from database import Database
from table import Table
# art font is "big"
art = '''
_ _ _____ ____
Expand All @@ -17,25 +17,26 @@
| '_ ` _ \ | || '_ \ | || | | || _ <
| | | | | || || | | || || |__| || |_) |
|_| |_| |_||_||_| |_||_||_____/ |____/ 2022
'''
'''


def search_between(s, first, last):
'''
Search in 's' for the substring that is between 'first' and 'last'
'''
try:
start = s.index( first ) + len( first )
end = s.index( last, start )
start = s.index(first) + len(first)
end = s.index(last, start)
except:
return
return s[start:end].strip()


def in_paren(qsplit, ind):
'''
Split string on space and return whether the item in index 'ind' is inside a parentheses
'''
return qsplit[:ind].count('(')>qsplit[:ind].count(')')
return qsplit[:ind].count('(') > qsplit[:ind].count(')')


def create_query_plan(query, keywords, action):
Expand All @@ -45,37 +46,35 @@ def create_query_plan(query, keywords, action):
This can and will be used recursively
'''

dic = {val: None for val in keywords if val!=';'}
dic = {val: None for val in keywords if val != ';'}

ql = [val for val in query.split(' ') if val !='']
ql = [val for val in query.split(' ') if val != '']

kw_in_query = []
kw_positions = []
i=0
while i<len(ql):
if in_paren(ql, i):
i+=1
i = 0
while i < len(ql):
if in_paren(ql, i):
i += 1
continue
if ql[i] in keywords:
kw_in_query.append(ql[i])
kw_positions.append(i)
elif i!=len(ql)-1 and f'{ql[i]} {ql[i+1]}' in keywords:

elif i != len(ql)-1 and f'{ql[i]} {ql[i+1]}' in keywords:
kw_in_query.append(f'{ql[i]} {ql[i+1]}')
ql[i] = ql[i]+' '+ql[i+1]
ql.pop(i+1)
kw_positions.append(i)
i+=1


i += 1

for i in range(len(kw_in_query)-1):
dic[kw_in_query[i]] = ' '.join(ql[kw_positions[i]+1:kw_positions[i+1]])

if action == 'create view':
dic['as'] = interpret(dic['as'])

if action=='select':
if action == 'select':
dic = evaluate_from_clause(dic)

if dic['distinct'] is not None:
Expand All @@ -88,13 +87,15 @@ def create_query_plan(query, keywords, action):
dic['desc'] = True
else:
dic['desc'] = False
dic['order by'] = dic['order by'].removesuffix(' asc').removesuffix(' desc')

dic['order by'] = dic['order by'].removesuffix(
' asc').removesuffix(' desc')

else:
dic['desc'] = None

if action=='create table':
args = dic['create table'][dic['create table'].index('('):dic['create table'].index(')')+1]
if action == 'create table':
args = dic['create table'][dic['create table'].index(
'('):dic['create table'].index(')')+1]
dic['create table'] = dic['create table'].removesuffix(args).strip()
arg_nopk = args.replace('primary key', '')[1:-1]
arglist = [val.strip().split(' ') for val in arg_nopk.split(',')]
Expand All @@ -105,24 +106,34 @@ def create_query_plan(query, keywords, action):
dic['primary key'] = arglist[arglist.index('primary')-2]
else:
dic['primary key'] = None

if action=='import':
dic = {'import table' if key=='import' else key: val for key, val in dic.items()}

if action=='insert into':
if action == 'import':
dic = {'import table' if key ==
'import' else key: val for key, val in dic.items()}

if action == 'insert into':
if dic['values'][0] == '(' and dic['values'][-1] == ')':
dic['values'] = dic['values'][1:-1]
else:
raise ValueError('Your parens are not right m8')
if action=='unlock table':

if action == 'unlock table':
if dic['force'] is not None:
dic['force'] = True
else:
dic['force'] = False

return dic
# Δημιουργια index που απαιτει την υπαρξη dictionery το οποιο υλοποιουμε μεσω query plan
if action == 'create index':
con_split = dic[kw_in_query[1]].split()
con_split.remove("(")
con_split.remove(")")
dic['create index'] = dic[kw_in_query[0]]
dic['on'] = con_split[0]
dic['column'] = con_split[1]
dic['using'] = dic[kw_in_query[2]]

return dic


def evaluate_from_clause(dic):
Expand All @@ -135,8 +146,10 @@ def evaluate_from_clause(dic):
subquery = ' '.join(from_split[1:-1])
dic['from'] = interpret(subquery)

join_idx = [i for i,word in enumerate(from_split) if word=='join' and not in_paren(from_split,i)]
on_idx = [i for i,word in enumerate(from_split) if word=='on' and not in_paren(from_split,i)]
join_idx = [i for i, word in enumerate(
from_split) if word == 'join' and not in_paren(from_split, i)]
on_idx = [i for i, word in enumerate(
from_split) if word == 'on' and not in_paren(from_split, i)]
if join_idx:
join_idx = join_idx[0]
on_idx = on_idx[0]
Expand All @@ -157,9 +170,10 @@ def evaluate_from_clause(dic):
join_dic['right'] = interpret(join_dic['right'][1:-1].strip())

dic['from'] = join_dic

return dic


def interpret(query):
'''
Interpret the query.
Expand All @@ -175,33 +189,36 @@ def interpret(query):
'unlock table': ['unlock table', 'force'],
'delete from': ['delete from', 'where'],
'update table': ['update table', 'set', 'where'],
'create index': ['create index', 'on', 'using'],
'create index': ['create index', 'on', 'column', 'using'],
'drop index': ['drop index'],
'create view' : ['create view', 'as']
'create view': ['create view', 'as']
}

if query[-1]!=';':
query+=';'

query = query.replace("(", " ( ").replace(")", " ) ").replace(";", " ;").strip()
if query[-1] != ';':
query += ';'

query = query.replace(
"(", " ( ").replace(")", " ) ").replace(";", " ;").strip()

for kw in kw_per_action.keys():
if query.startswith(kw):
action = kw

return create_query_plan(query, kw_per_action[action]+[';'], action)


def execute_dic(dic):
'''
Execute the given dictionary
'''
for key in dic.keys():
if isinstance(dic[key],dict):
if isinstance(dic[key], dict):
dic[key] = execute_dic(dic[key])
action = list(dic.keys())[0].replace(' ','_')

action = list(dic.keys())[0].replace(' ', '_')
return getattr(db, action)(*dic.values())


def interpret_meta(command):
"""
Interpret meta commands. These commands are used to handle DB stuff, something that can not be easily handled with mSQL given the current architecture.
Expand All @@ -215,24 +232,25 @@ def interpret_meta(command):
"""
action = command.split(' ')[0].removesuffix(';')

db_name = db._name if search_between(command, action,';')=='' else search_between(command, action,';')
db_name = db._name if search_between(
command, action, ';') == '' else search_between(command, action, ';')

verbose = True
if action == 'cdb' and ' -noverb' in db_name:
db_name = db_name.replace(' -noverb','')
db_name = db_name.replace(' -noverb', '')
verbose = False

def list_databases(db_name):
[print(fold.removesuffix('_db')) for fold in os.listdir('dbdata')]

def list_tables(db_name):
[print(pklf.removesuffix('.pkl')) for pklf in os.listdir(f'dbdata/{db_name}_db') if pklf.endswith('.pkl')\
[print(pklf.removesuffix('.pkl')) for pklf in os.listdir(f'dbdata/{db_name}_db') if pklf.endswith('.pkl')
and not pklf.startswith('meta')]

def change_db(db_name):
global db
db = Database(db_name, load=True, verbose=verbose)

def remove_db(db_name):
shutil.rmtree(f'dbdata/{db_name}_db')

Expand All @@ -252,20 +270,18 @@ def remove_db(db_name):

db = Database(dbname, load=True)



if fname is not None:
for line in open(fname, 'r').read().splitlines():
if line.startswith('--'): continue
if line.startswith('--'):
continue
if line.startswith('explain'):
dic = interpret(line.removeprefix('explain '))
pprint(dic, sort_dicts=False)
else :
else:
dic = interpret(line.lower())
result = execute_dic(dic)
if isinstance(result,Table):
if isinstance(result, Table):
result.show()


from prompt_toolkit import PromptSession
from prompt_toolkit.history import FileHistory
Expand All @@ -275,14 +291,15 @@ def remove_db(db_name):
session = PromptSession(history=FileHistory('.inp_history'))
while 1:
try:
line = session.prompt(f'({db._name})> ', auto_suggest=AutoSuggestFromHistory()).lower()
if line[-1]!=';':
line+=';'
line = session.prompt(
f'({db._name})> ', auto_suggest=AutoSuggestFromHistory()).lower()
if line[-1] != ';':
line += ';'
except (KeyboardInterrupt, EOFError):
print('\nbye!')
break
try:
if line=='exit':
if line == 'exit':
break
if line.split(' ')[0].removesuffix(';') in ['lsdb', 'lstb', 'cdb', 'rmdb']:
interpret_meta(line)
Expand All @@ -292,7 +309,7 @@ def remove_db(db_name):
else:
dic = interpret(line)
result = execute_dic(dic)
if isinstance(result,Table):
if isinstance(result, Table):
result.show()
except Exception:
print(traceback.format_exc())
Loading