Commit b24b4f6d authored by Eugene Lu's avatar Eugene Lu
Browse files
parents f024f27a 12f8ca18
......@@ -6,8 +6,10 @@ import dotenv
import mysql.connector as mysql
def trim_string(name):
# Removes ( ) ' , characters from passed in string and returns it
# Removes ( ) ' , characters from passed in string and returns it
# Used to neatly format table list
def trim_string (name: str):
name = str(name)
name = name.replace('(','')
......@@ -17,14 +19,29 @@ def trim_string(name):
return name
# Removes leading/trailing whitespace from all elements in a list and returns updated list
def trim(old_list : list):
new_list = []
for element in old_list:
element = str(element)
element = element.strip()
element = trim_string(element)
new_list.append(element)
def cleanup_type(string):
return new_list
string = str(string)
string = string.replace('\'','') #removes quotation
string = string[1:] # removes b
return string
def cleanup_type(text):
text = str(text)
text = text.replace('\'','') #removes quotation
text = text[1:] # removes b
return text
# Hardcoded descriptions for when user runs help command
def generate_descriptions():
descriptions = (" A filtering query that returns the average from a specific column ",
......@@ -39,44 +56,53 @@ def generate_descriptions():
" A filtering query that only returns the minimum from the search",
" Exits the CLI",
" Removes rows from a Table based on criteria",
" Performs an SQL query without aggregate functions",
" Returns all results from an SQL Table",
" Returns the sum of all entries of a specific column",
" Returns all columns and their associated datatypes for a specific Table")
return descriptions
# Database class : Used for interacting with the Database and performing queries
class Database:
# Creates a blank table with attributes
def __init__(self):
# Initial list of tables to be defined
self.table_list = ["TeamInfo", "Game", "GameGoals", "GameOfficials", "GamePenalties", "GamePlays", "GamePlaysPlayers", "GameShifts", "PlayerInfo", "TeamInfo"] # List all tables in the database
# TODO: Update list with final Relational Model Tables
self.command_list = ("average", "clear", "count", "create", "delete", "help", "insert", "list", "max", "min", "quit", "remove", "search_filter", "sum", "view_column")
self.table_list = self.get_list_tables() # List of tables in Database
self.command_description = generate_descriptions()
self.command_list = ("average", "clear", "count", "create", "delete", "help", "insert", "list", "max", "min", "quit", "remove", "search_all", "sum", "view_column") # List of available user commands
self.command_description = generate_descriptions() # List of user command descriptions
def get_column_names(self, table_name):
# Returns column names and types for a given table (view_column)
def get_column_and_type(self, table_name: str):
cursor.execute("Show columns from {0}" .format(table_name))
results = cursor.fetchall()
fields = [] # field name
type = [] # type
null = [] # Yes->Can be Null or No->Can't be Null
key = []
for result in results:
fields.append(result[0])
type.append(result[1])
print(fields)
# print(fields)
return fields, type
def get_column(self, table_name: str):
cursor.execute("Show columns from {0}".format(table_name))
results = cursor.fetchall()
fields = [] # field name
for result in results:
fields.append(result[0])
# print(fields)
return fields
# Creates a Table based off user input
def create_table(self):
table_name = input("Enter name of new table : ")
......@@ -88,92 +114,105 @@ class Database:
else:
print("Creating table named {0}".format(table_name))
executing = True
attributes = []
type = []
max_length = []
num_floating = []
null = []
pk = []
while executing:
print ("Make sure the fields you entered below are seperated by commas (ex. \"first_name, last_name, age\")")
var = input("Continue inputting attributes (Y/N)")
input_string = input("Enter all fields that you want in table {0} seperated by"
" commas (each field can only be one word) : \n".format(table_name))
attributes = input_string.split(",")
if var == "N" and attributes.length <2: # Not enough attributes
attributes = trim(attributes) # Removes white space and unnecessary characters like , ' ( )
print("Only {0} attributes. Need at least 2 attributes to create table.".format(attributes.length))
for attribute in attributes: # Gets specific info on each attribute
elif var == "N": # Enough attributes leaving....
new_type = input("Enter the type of attribute {0} (Integer, Decimal, Date, Character, Boolean) : ".format(attribute))
new_type = new_type.lower() # No longer case sensitive
break
new_type, new_length, new_floating = self.handle_type_insert(new_type)
type.append(new_type)
max_length.append(new_length)
num_floating.append(new_floating)
elif var == "Y":
user = input("Do you want to add a Primary Key to the table (Y/N) : ")
new_attribute = input("Enter the name of the next attribute to add : ")
if user == "Y": # Adds primary key
new_type = input("Enter the type of attribute {0} (Integer, Decimal, Date, Character, Boolean".format(new_attribute))
new_type = new_type.lower() #No longer case sensitive
print("Attributes created are : {0}".format(attributes))
input_pk = input("Enter attributes that you wish to use as Primary Key (separate by commas) : \n")
new_type, new_length, new_floating = self.handle_type_insert(new_type)
pk = input_pk.split(",")
type.append(new_type)
max_length.append(new_length)
num_floating.append(new_floating)
query = self.generate_create_query(table_name, attributes, type, max_length, num_floating, pk)
new_null = input("Does this attribute always have to be defined (Y/N)")
print(query) # For debugging purposes
if new_null == "Y":
null.append("not null")
results = self.execute_query(query)
else:
null.append("")
print(results)
self.table_list.append(table_name) # Add to list of tables
# Generates create query based off user information provided
def generate_create_query(self, table_name: str, attributes: list, type: list, max_lengths: list, num_floating: list, pk: list):
else:
query = "create table {0} ( \n".format(table_name)
print("Invalid command. Make sure to enter either \"Y\" or \"N\"")
for attribute, type, max_length, num_floating, null in zip(attributes, type, max_lengths, num_floating, null):
query += "{0} ".format(attribute)
type_string = self.format_type(type, max_length, num_floating)
query += "{0} ".format(type_string)
no_pk = True
if attribute == attributes[-1]:
while no_pk:
if len(pk) != 0:
user = input("Do you want to add a Primary Key to the table (Y/N)")
query += ",\n"
pk_string = self.handle_pk_string(pk)
query += "PRIMARY KEY ({0})".format(pk_string)
if user == "Y":
else:
query += ",\n"
variable = input("Enter attribute to append to PK : ")
pk.append(variable)
query += ");"
return query
else:
break
# Given a type, produces output that will be used in create query clause
def format_type (self, type: str, max_length: str, num_floating: str):
if pk.length == 0: #If no Primary Key assigned just make first attribute PK
if type == "int":
pk.append(attributes[0])
return "int"
print(attributes)
print(type)
print(max_length)
print(num_floating)
print(null)
print(pk)
elif type == "decimal":
return "decimal({0},{1})".format(max_length, num_floating)
elif type == "dateTime":
return "dateTime"
elif type == "varchar":
return "varchar({0})".format(max_length)
elif type == "tinyint":
return "tinyint(1)"
# Given all relevant attributes, returns query to create table
# Supported types :
# Integer -> int
# Decimal -> decimal + ask user for length + ask user for number of decimal digits
# Date -> dateTime
# Character -> char + ask user for length
# Character -> varchar + ask user for length
# Boolean -> tinyint(1)
def handle_type_insert(self, type):
# Based off the attribute this function drives what to ask the user
def handle_type_insert(self, type: str):
if type == "integer":
......@@ -187,7 +226,6 @@ class Database:
return "decimal", num_digits, num_decimal
elif type == "date":
return "dateTime", 0, 0
......@@ -206,29 +244,178 @@ class Database:
return "error", -1, -1
# Formats the Primary Key clause in the Create Table command
def handle_pk_string(self, pk: list):
pk_string = ""
def handle_create_table(self, attributes, type, max_length, p_key, f_key,):
for element in pk:
attributes = []
type = []
if element == pk[-1]:
pk_string += element
else:
pk_string += "{0} ,".format(element)
return pk_string
#Adds rows to a table
def add_records(self):
pass
table_name = input("Enter the table you wish to insert data into : ")
if table_name not in self.table_list:
print("Table {0} does not exist".format(table_name))
return
else:
all = self.get_column(table_name)
print("Attributes are {0}".format(all))
choice = input("Inserting into all columns? (All/Partial) : ")
choice = choice.strip() # Remove whitespace
choice = choice.lower() # Case insensitive
columns = ""
column_names = ""
attributes = []
if choice == "all": # Do nothing
attributes = all
column_names += "\n" # No columns to include
elif choice == "partial": # Specify columns to insert into
names = input("Please enter names of all columns to insert into (seperated by commas) : \n")
columns += names
old_list = names.split(",") # Convert to list
attributes = trim(old_list)
for element in attributes:
if element == attributes[0]:
column_names+="({0},".format(element)
elif element == attributes[-1]:
column_names += "{0})".format(element)
else:
column_names += "{0},".format(element)
else: # Error
print("Error : Invalid input")
return
query = self.generate_insert_query(table_name, column_names, attributes)
results = self.execute_query(query)
print(results)
# From passed in parameters generates final query
def generate_insert_query(self, table_name: str, column_names: str, attributes: list):
query = "insert into {0}".format(table_name)
query += column_names
query += "values ("
for element in attributes:
value = input("Enter value to be entered into {0} : ".format(element))
if element == attributes[-1]:
query += "\'{0}\');".format(value)
else:
query += "\'{0}\',".format(value)
return query
# Get a number of results that meet criteria based off filtering
def select_count(self):
pass
table_name = input("Select the table that you wish to count results for : ")
if table_name not in self.table_list:
print("Table {0} does not exist".format(table_name))
else:
pass
def select_type(self):
pass
table_name = input("Select the table that you wish to query : ")
if table_name not in self.table_list:
print("Table {0} does not exist".format(table_name))
else:
query = "select * from {0}".format(table_name)
limit = input("Limit amount of search results (Y/N) : ")
if limit == "Y":
query += self.limit_results()
result = self.execute_query(query)
print(result)
# Creates constraints based off user inputs
def setup_constraints(self, table_name: str, column_names: list):
print("Columns in table {0} are : ".format(table_name))
number = input("Enter the number of requirements (each requirement will be anded with each other)")
for x in range(number):
print("Requirement {0}\n".format(x+1))
def limit_results(self):
num = input("Maximum results to be returned : ")
return "LIMIT {0}".format(num)
def delete_records(self):
pass
table_name = input("Select table to delete records from : ")
if table_name not in self.table_list:
print("Table {0} does not exist".format(table_name))
else:
columns = self.get_column(table_name)
query = "delete from {0}".format(table_name)
option = input("Delete entire table or partial? (All/Partial) : ")
option = option.strip()
option = option.lower()
if option == "all": # Do nothing
pass
elif option == "partial":
query += self.setup_constraints(table_name, columns)
else:
print("Invalid option")
return
# Deletes Table and all associated records
def delete_table(self):
......@@ -238,8 +425,8 @@ class Database:
if table_name in self.table_list:
cursor.execute("drop table {0}".format(table_name))
result = cursor.fetchall()
query = "drop table {0}".format(table_name)
result = self.execute_query(query)
print(result)
self.table_list.remove(table_name)
......@@ -267,6 +454,7 @@ class Database:
else:
print("Table name does not exist")
# Given a valid table name, prints out all atributes and associated types
def show_columns(self):
table_name = input("Please select table to view columns of : ")
......@@ -275,10 +463,12 @@ class Database:
if table_name in self.table_list:
field_names, types = self.get_column_names(table_name)
field_names, types = self.get_column_and_type(table_name)
else:
print("Table does not exist")
return
print("Field Name, Type")
for field_name, type in zip(field_names, types):
......@@ -286,15 +476,43 @@ class Database:
type = cleanup_type(type)
print("{0},{1}".format(field_name, type))
# Prints out the list of all commands for help
def display_command_list(self):
print ("Command Name - Command Description")
print("Command Name - Command Description")
for command, description in zip(self.command_list, self.command_description):
print ("{0} - {1}".format(command, description))
print("{0} - {1}".format(command, description))
# Runs show tables and trims, from result
def get_list_tables(self):
cursor.execute("Show tables")
result = cursor.fetchall()
return trim(result)
# Prints list of all tables
def print_tables(self):
tables = self.table_list
for table in tables:
print(table)
return
def execute_query(self, query: str):
try:
cursor.execute(query)
results = cursor.fetchall()
return results
except mysql.Error as err:
print("Something went wrong: {}".format(err))
if __name__ == "__main__":
......@@ -303,15 +521,7 @@ if __name__ == "__main__":
username = os.environ.get("DB_USER")
passphrase = os.environ.get("DB_PASS")
dbname = os.environ.get("DB_NAME")
keepExecuting = True
if username == "{Username}":
print ("looks like the username is still the default on the .env file.")
elif passphrase == "{Password}":
print ("Looks like the password is still the default on the .env file")
try:
db = mysql.connect(
......@@ -334,10 +544,10 @@ if __name__ == "__main__":
cursor = db.cursor()
client = Database()
while keepExecuting:
while True:
command = input("Please select a command : ")
command = command.lower() # No longer case sensitive
command = command.strip()
if command == "quit": # Done
......@@ -345,18 +555,13 @@ if __name__ == "__main__":
elif command == "list": # Done
# implement "SHOW TABLES"in SQL
cursor.execute("Show tables")
result = cursor.fetchall()
client.print_tables()
for table in result:
table = trim_string(table)
print(table)
elif command == "create": #TODO
elif command == "create": # Done
client.create_table()
elif command == "insert": # TODO
elif command == "insert": # Done
client.add_records()
......@@ -379,32 +584,16 @@ if __name__ == "__main__":
client.select_count()
elif command == "average": # TODO
pass
elif command == "sum": # TODO
pass
elif command == "min": # TODO
pass
elif command == "max": # TODO
pass
elif command == "search_filter": # TODO
elif command == "search_all": # TODO
client.select_type()
elif command == "help": #TODO
elif command == "help": # Done
client.display_command_list()
else:
print("Invalid command, please enter a valid command!")
db.close()
db.close()
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment