diff --git a/students/KevinCavanaugh/final_project/.idea/encodings.xml b/students/KevinCavanaugh/final_project/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/final_project/.idea/final_project.iml b/students/KevinCavanaugh/final_project/.idea/final_project.iml new file mode 100644 index 0000000..85c7612 --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/final_project.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/final_project/.idea/misc.xml b/students/KevinCavanaugh/final_project/.idea/misc.xml new file mode 100644 index 0000000..8d0e8a5 --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/final_project/.idea/modules.xml b/students/KevinCavanaugh/final_project/.idea/modules.xml new file mode 100644 index 0000000..12b00a0 --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/final_project/.idea/vcs.xml b/students/KevinCavanaugh/final_project/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/final_project/.idea/workspace.xml b/students/KevinCavanaugh/final_project/.idea/workspace.xml new file mode 100644 index 0000000..98ef97b --- /dev/null +++ b/students/KevinCavanaugh/final_project/.idea/workspace.xml @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InventoryID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -247,7 +188,8 @@ - + + @@ -276,27 +218,24 @@ - + - - + + - + - - + + - - - - + - - + + @@ -307,24 +246,27 @@ - + + + + - - + + - + - - + + - + - - + + diff --git a/students/KevinCavanaugh/session5/.idea/encodings.xml b/students/KevinCavanaugh/session5/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session5/.idea/misc.xml b/students/KevinCavanaugh/session5/.idea/misc.xml new file mode 100644 index 0000000..4f2e687 --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session5/.idea/modules.xml b/students/KevinCavanaugh/session5/.idea/modules.xml new file mode 100644 index 0000000..27da7d6 --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session5/.idea/session5.iml b/students/KevinCavanaugh/session5/.idea/session5.iml new file mode 100644 index 0000000..85c7612 --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/session5.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session5/.idea/vcs.xml b/students/KevinCavanaugh/session5/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session5/.idea/workspace.xml b/students/KevinCavanaugh/session5/.idea/workspace.xml new file mode 100644 index 0000000..ce333da --- /dev/null +++ b/students/KevinCavanaugh/session5/.idea/workspace.xml @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1551652660205 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/Generating SQL Code.py b/students/KevinCavanaugh/session8/Generating SQL Code.py new file mode 100644 index 0000000..89144a8 --- /dev/null +++ b/students/KevinCavanaugh/session8/Generating SQL Code.py @@ -0,0 +1,171 @@ +import sqlite3 +from sqlite3 import Error as sqlErr + + +def create_connection(db_file): + try: + con = sqlite3.connect(db_file) + print('SQLite Version is: ', sqlite3.version) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + + +def execute_sql_code(db_con = None, sql_code=''): + try: + if db_con is not None and sql_code != '': + csr = db_con.cursor() + csr.execute(sql_code) + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return csr + + +def create_table_code(name_of_table, col_names=[None]): + """ create table code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column!') + else: + sql_str = 'CREATE TABLE ' + name_of_table + '\n(' + for col in col_names: + sql_str += str(col) + ' [text], ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_staging_table(): ' + e.__str__()) + return sql_str + + +def create_insert_code(name_of_table, col_names=[None], col_values=[None],): + """ create staging table insert code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'INSERT INTO ' + name_of_table + '\n(' + for col in col_names: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ')' # Strip off the last comma + if col_values is None: + raise Exception('You must provide at least one column value!') + else: + sql_str += '\nVALUES\n(' + for col in col_values: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_insert_code(): ' + e.__str__()) + return sql_str + + +def create_update_code(name_of_table, col_names=[None], col_values=[None], where_col = None, where_equals_value = None): + """ create staging table update code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + elif col_values is None: + raise Exception('You must provide at least one column value!') + elif len(col_names) != len(col_values): + raise Exception('You must provide one value for each column') + elif where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'UPDATE ' + name_of_table + '\nSET\n\t' + counter = 0 + while counter < len(col_names): + sql_str += str(col_names[counter]) + ' = ' + str(col_values[counter]) + ', \n\t' + counter += 1 + sql_str = (sql_str.strip())[0:-1] + '' # Strip off the last comma + sql_str += '\nWHERE ' + where_col + " = " + where_equals_value + except Exception as e: + raise Exception('Error in create_update_code(): ' + e.__str__()) + return sql_str + + +def create_delete_code(name_of_table, where_col = None, where_equals_value = None): + """ create staging table delete code """ + sql_str = '' + try: + if where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'DELETE FROM ' + name_of_table + sql_str += '\nWHERE ' + where_col + " = " + where_equals_value + except Exception as e: + raise Exception('Error in create_delete_code(): ' + e.__str__()) + return sql_str + + +def create_select_code(name_of_table, col_names=[None]): + """ create staging table select code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'SELECT \n\t' + for col in col_names: + sql_str += str(col) + ', \n\t' + sql_str = sql_str[0:-2] + '\n' # Strip off the last comma + sql_str += 'FROM ' + name_of_table + ';' + except Exception as e: + raise Exception('Error in create_select_code(): ' + e.__str__()) + return sql_str + +# SQL Validators +def check_for_extra_semicolon(SQLStr): + try: + if SQLStr.find(';') != -1: + raise Exception("Extra Semi-Colon Detected!") + except Exception as e: + raise e + + +def check_for_or(SQLStr): + try: + if SQLStr.find('or') != -1: + raise Exception("OR Detected!") + except Exception as e: + raise e + + +if __name__ == '__main__': + + try: + print('\ntest CREATE TABLE','-'*40, '\n') + print(create_table_code('StagingStudents', ['ID','Name','Email'])) + except Exception as e: + print(e) + + try: + print('\ntest SELECT','-'*40, '\n') + print(create_select_code('StagingStudents', ['ID','Name','Email'])) + except Exception as e: + print(e) + + try: + print('\ntest INSERT','-'*40, '\n') + print(create_insert_code('StagingStudents', ['ID','Name','Email'], [1,'Bob Smith', 'BSmith@gomail.com'])) + except Exception as e: + print(e) + + try: + print('\ntest UPDATE','-'*40, '\n') + print(create_update_code('StagingStudents', ['Name','Email'], ['Rob Smith', 'RSmith@gomail.com'], 'ID', '1')) + except Exception as e: + print(e) + + try: + print('\ntest DELETE','-'*40, '\n') + print(create_delete_code('StagingStudents', 'ID', '1')) + except Exception as e: + print(e) \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/Lab8-3 Create DB.py b/students/KevinCavanaugh/session8/Lab8-3 Create DB.py new file mode 100644 index 0000000..d380f2b --- /dev/null +++ b/students/KevinCavanaugh/session8/Lab8-3 Create DB.py @@ -0,0 +1,41 @@ +import sqlite3 +from sqlite3 import Error as sqlErr + +def create_connection(db_file): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + print('SQLite Version is: ', sqlite3.version) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + + +def main_menu(): + """ Present a menu to the user """ + print('\n', '='*50, sep='') + print("Choose an option by number: ") + print("\t 1 = Create or Connect to a new file database") + print("\t 2 = Create a new memory database") + print('Type exit to quit program!') + print('='*50, '\n', sep='') + +if __name__ == '__main__': + dbconnection = None + while True: + try: + main_menu() + choice = input("Option: ") + if choice == '1': + fn = input("Enter file name and path: ") + dbconnection = create_connection(fn) + elif choice == '2': + dbconnection = create_connection(':memory:') + elif choice.lower() == 'exit': + break + else: + print('Please enter a number for the option you want!') + except Exception as e: + print('Error ->\t', e.__str__()) \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/Lab8-4 Create Table.py b/students/KevinCavanaugh/session8/Lab8-4 Create Table.py new file mode 100644 index 0000000..dd84c32 --- /dev/null +++ b/students/KevinCavanaugh/session8/Lab8-4 Create Table.py @@ -0,0 +1,83 @@ +import sqlite3 +from sqlite3 import Error as sqlErr + +def create_connection(db_file): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + print('SQLite Version is: ', sqlite3.version) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + +def execute_sql_code(db_con = None, sql_code=''): + """ Execute SQL code on a open connection """ + try: + if db_con is not None and sql_code != '': + with db_con: + csr = db_con.cursor() + csr.execute(sql_code) + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return csr + +def create_table_code(name_of_table, col_names=[None]): + """ Create table code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column!') + else: + sql_str = 'create table ' + name_of_table + ' (' + for col in col_names: + sql_str += str(col) + ' [text], ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_table_code(): ' + e.__str__()) + return sql_str + + +def main_menu(): + print('\n', '='*50, sep='') + print("Choose an option by number: ") + print("\t 1 = Create or Connect to a new file database") + print("\t 2 = Create a new memory database") + print("\t 3 = Create a new table") + print('Type exit to quit program!') + print('='*50, '\n', sep='') + +if __name__ == '__main__': + dbconnection = None + while True: + try: + main_menu() + choice = input("Option: ") + if choice == '1': + fn = input("Enter file name and path: ") + dbconnection = create_connection(fn) + elif choice == '2': + dbconnection = create_connection(':memory:') + elif choice == '3': + name = input("Enter a name for the table: ") + cols = input("Enter a comma separated list of column names (col1,col2,etc...): ").strip() + sql = create_table_code(name, cols.split(',')) + opt = input('\nPreview:\n\n' + sql + '\n\nCreate the following table?(y/n):') + if opt.lower() == 'y': + csr = execute_sql_code(db_con=dbconnection, sql_code=sql) + csr.close() + else: + print('Info ->\tTable creation cancelled!') + elif choice.lower() == 'exit': + break + else: + print('Please enter a number for the option you want!') + except Exception as e: + print('Error ->\t', e.__str__()) + + dbconnection.close() diff --git a/students/KevinCavanaugh/session8/Lab8-6 Dynamic SQL Transactions.py b/students/KevinCavanaugh/session8/Lab8-6 Dynamic SQL Transactions.py new file mode 100644 index 0000000..a35e3e4 --- /dev/null +++ b/students/KevinCavanaugh/session8/Lab8-6 Dynamic SQL Transactions.py @@ -0,0 +1,200 @@ +import sqlite3 +from sqlite3 import Error as sqlErr + +def create_connection(db_file): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + print('SQLite Version is: ', sqlite3.version) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + +def execute_sql_code(db_con = None, sql_code=''): + """ Execute SQL code on a open connection """ + try: + if db_con is not None and sql_code != '': + csr = db_con.cursor() + csr.execute(sql_code) + db_con.commit() + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return csr + +def create_table_code(name_of_table, col_names=[None]): + """ Create table code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column!') + else: + sql_str = 'CREATE TABLE ' + name_of_table + '(' + for col in col_names: + sql_str += str(col) + ' [text], ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_table(): ' + e.__str__()) + return sql_str + +def create_select_code(name_of_table, col_names=[None]): + """ create table select code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'SELECT \n' + for col in col_names: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + '\n' # Strip off the last comma + sql_str += 'FROM ' + name_of_table + ';' + except Exception as e: + raise Exception('Error in create_select_code(): ' + e.__str__()) + return sql_str + +def create_insert_code(name_of_table, col_names=[None], col_values=[None],): + """ create table insert code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'INSERT INTO ' + str(name_of_table).strip() + '\n(' + for col in col_names: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ')' # Strip off the last comma + if col_values is None: + raise Exception('You must provide at least one column value!') + else: + sql_str += '\nVALUES\n(' + for col in col_values: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_insert_code(): ' + e.__str__()) + return sql_str + +def create_update_code(name_of_table, col_names=[None], col_values=[None], where_col = None, where_equals_value = None): + """ create table update code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + elif col_values is None: + raise Exception('You must provide at least one column value!') + elif len(col_names) != len(col_values): + raise Exception('You must provide one value for each column') + elif where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'UPDATE ' + str(name_of_table).strip() + '\nSET\n\t' + counter = 0 + while counter < len(col_names): + sql_str += str(col_names[counter]).strip() \ + + ' = ' + str(col_values[counter]).strip() + ', \n\t' + counter += 1 + sql_str = (sql_str.strip())[0:-1] + '' # Strip off the last comma + sql_str += '\nWHERE ' + where_col + " = " + where_equals_value + except Exception as e: + raise Exception('Error in create_update_code(): ' + e.__str__()) + return sql_str + +def create_delete_code(name_of_table, where_col = None, where_equals_value = None): + """ create table delete code """ + sql_str = '' + try: + if where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'DELETE FROM ' + str(name_of_table).strip() + sql_str += '\nWHERE ' + where_col + " = " + str(where_equals_value).strip() + except Exception as e: + raise Exception('Error in create_delete_code(): ' + e.__str__()) + return sql_str + + +def main_menu(): + print('\n', '='*50, sep='') + print("Choose an option by number: ") + print("\t 1 = Create or Connect to a new file database") + print("\t 2 = Create a new memory database") + print("\t 3 = Create a new table") + print("\t [s] = Select from table") + print("\t [i] = Insert into table") + print("\t [u] = Update in table") + print("\t [d] = Delete from table") + print('Type exit to quit program!') + print('='*50, '\n', sep='') + + +if __name__ == '__main__': + dbconnection = None + while True: + try: + main_menu() + choice = input("Option: ").strip() + if choice == '1': + fn = input("Enter file name and path: ").strip() + dbconnection = create_connection(fn) + elif choice == '2': + dbconnection = create_connection(':memory:') + elif choice == '3': + t = input("Enter a name for the table: ").strip() + cols = input("Enter a comma separated list of column names (col1,col2,etc...): ").strip() + sql = create_table_code(t, cols.split(',')) + opt = input('\nPreview:\n\n\t' + sql + '\n\nCreate the following table?(y/n):') + if opt.lower() == 'y': + execute_sql_code(db_con=dbconnection, sql_code=sql).close() # Close Cursor + else: + print('Info ->\tTable creation cancelled!') + elif choice == 's': + t = input("Enter a name for the table: ").strip() + cols = input("Enter a comma separated list of column names (col1,col2,etc...): ").strip() + sql = create_select_code(t, cols.split(',')) + print('\nCode Used : ' + sql + '\n') + csrData = execute_sql_code(db_con=dbconnection, sql_code=sql) # Don't close cursor + for row in csrData: + for col in row: + print(col, end=' | ') + print() + csrData.close() # Now close cursor! + elif choice == 'i': + t = input("Enter a name for the table: ").strip() + cols = input("Enter a comma separated list of column names (col1,col2,etc...): ").strip() + colvals = input("Enter a comma separated list of column VALUES (col1,col2,etc...): ").strip() + sql = create_insert_code(t, cols.split(','), colvals.split(',')) + opt = input('\nPreview:\n\n' + sql + '\n\nInsert this data?(y/n):') + if opt.lower() == 'y': + execute_sql_code(db_con=dbconnection, sql_code=sql).close() # Close Cursor + elif choice == 'u': + t = input("Enter a name for the table: ").strip() + cols = input("Enter a comma separated list of column names (col1,col2,etc...): ").strip() + colvals = input("Enter a comma separated list of column VALUES (col1,col2,etc...): ").strip() + wc = input("Enter one WHERE column Name: ").strip() + wv = input("Enter one WHERE column Equals Value: ").strip() + sql = create_update_code(t, cols.split(','), colvals.split(','),where_col=wc, where_equals_value=wv) + opt = input('\nPreview:\n\n' + sql + '\n\nUpdate this data?(y/n):') + if opt.lower() == 'y': + execute_sql_code(db_con=dbconnection, sql_code=sql).close() # Close Cursor + elif choice == 'd': + t = input("Enter a name for the table: ").strip() + wc = input("Enter one WHERE column Name: ").strip() + wv = input("Enter one WHERE column Equals Value: ").strip() + sql = create_delete_code(t, where_col=wc, where_equals_value=wv) + opt = input('\nPreview:\n\n' + sql + '\n\nDelete this data?(y/n):') + if opt.lower() == 'y': + execute_sql_code(db_con=dbconnection, sql_code=sql).close() # Close Cursor + elif choice.lower() == 'exit': + break + else: + print('Please enter a number for the option you want!') + except Exception as e: + print('Error ->\t', e.__str__()) + dbconnection() + diff --git a/students/KevinCavanaugh/session8/SQLValidators.py b/students/KevinCavanaugh/session8/SQLValidators.py new file mode 100644 index 0000000..4dd6753 --- /dev/null +++ b/students/KevinCavanaugh/session8/SQLValidators.py @@ -0,0 +1,14 @@ +# SQL Validators +def check_for_extra_semicolon(SQLStr): + try: + if SQLStr.find(';') != -1: + raise Exception("Extra Semi-Colon Detected!") + except Exception as e: + raise e + +def check_for_or(SQLStr): + try: + if SQLStr.find('or') != -1: + raise Exception("OR Detected!") + except Exception as e: + raise e \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/Simple SQL Transactions.py b/students/KevinCavanaugh/session8/Simple SQL Transactions.py new file mode 100644 index 0000000..625b683 --- /dev/null +++ b/students/KevinCavanaugh/session8/Simple SQL Transactions.py @@ -0,0 +1,51 @@ +import sqlite3 +from sqlite3 import Error as SqlErr + +def create_demo(con): + with db_con: + csr = db_con.cursor() + csr.execute("CREATE TABLE IF NOT EXISTS Demo (ID [integer], Name [text]);") + db_con.commit() + +def sel_demo(con): + with db_con: + csr = db_con.cursor() + csr.execute("SELECT * FROM DEMO;") + db_con.commit() + return csr + +def ins_demo(con, values=[None]): + if values is not None: + with db_con: + csr = db_con.cursor() + csr.execute("INSERT INTO Demo (ID, Name) values (?,?);", values) + db_con.commit() + +def upd_demo(con, values=[None]): + if values is not None: + with db_con: + csr = db_con.cursor() + csr.execute("UPDATE Demo SET ID = ?, Name = ? WHERE ID = ?;", values) + db_con.commit() + +def del_demo(con, values=[None]): + if values is not None: + with db_con: + csr = db_con.cursor() + csr.execute("DELETE FROM Demo WHERE ID = ?;", values) + db_con.commit() + +if __name__ == '__main__': + db_con = sqlite3.connect('Lab8-5.db') + create_demo(db_con) + + ins_demo(db_con, [1,'Bob']) # Must use single quotes + for row in sel_demo(db_con): print(row) + + upd_demo(db_con,[1,'Rob', 1]) + for row in sel_demo(db_con): print(row) + + del_demo(db_con, [1]) + for row in sel_demo(db_con): print(row) + + diff --git a/students/KevinCavanaugh/session8/SimpleDemo.db b/students/KevinCavanaugh/session8/SimpleDemo.db new file mode 100644 index 0000000..ee94ce6 Binary files /dev/null and b/students/KevinCavanaugh/session8/SimpleDemo.db differ diff --git a/students/KevinCavanaugh/session8/SimplePySQLiteDemo.py b/students/KevinCavanaugh/session8/SimplePySQLiteDemo.py new file mode 100644 index 0000000..6943bc0 --- /dev/null +++ b/students/KevinCavanaugh/session8/SimplePySQLiteDemo.py @@ -0,0 +1,24 @@ +import sqlite3 +from sqlite3 import Error as SqlErr + +try: + # Create or Connect to a DB + db_con = sqlite3.connect('SimpleDemo.db') + # Create a table in the DB + csr = db_con.cursor() + csr.execute("create table Demo (ID [integer], Name [text]);") # SQL requires a semi-colon! + # Insert some data + csr.execute("insert into Demo (ID, Name) values (1, 'A'), (2, 'B');") # SQL uses only Single quotes for strings! + # Select some data + csr.execute("select ID, Name from Demo;") # SQL can use the * symbol to indicate all columns! + rows = csr.fetchall() + csr.close() # Always close the cursor when your done + db_con.close() # Always close the connection when your done + for row in rows: + print(row, type(row)) +except SqlErr as se: + print(se) +except Exception as e: + print(e) + + diff --git a/students/KevinCavanaugh/session8/SimplePySQLiteWithParametersDemo.py b/students/KevinCavanaugh/session8/SimplePySQLiteWithParametersDemo.py new file mode 100644 index 0000000..f479adf --- /dev/null +++ b/students/KevinCavanaugh/session8/SimplePySQLiteWithParametersDemo.py @@ -0,0 +1,26 @@ +import sqlite3 +from sqlite3 import Error as SqlErr + +try: + # Create or Connect to a DB + db_con = sqlite3.connect(':memory:') + with db_con: + csr = db_con.cursor() + csr.execute("create table Demo (ID [integer], Name [text]);") # SQL requires a semi-colon! + # Insert some data + csr.execute("insert into Demo (ID, Name) values (?, ?);", (1, 'A')) # requires a Tuple + csr.execute("insert into Demo (ID, Name) values (?, ?);", (2, 'B')) # requires a Tuple + # Select some data + csr.execute("select ID, Name from Demo;") + rows = csr.fetchall() # for multiple rows + for row in rows: + print(row, type(row)) + csr.execute("select ID, Name from Demo where ID = ?;", (1, )) # remember the extra comma! + row = csr.fetchone() # for only one row! + print(row, type(row)) + csr.close() # Always close the cursor when your done + # db_con.close() # Not, needed since the "with" automatically closes the connection +except SqlErr as se: + print(se) +except Exception as e: + print(e) diff --git a/students/KevinCavanaugh/session8/base_class.py b/students/KevinCavanaugh/session8/base_class.py new file mode 100644 index 0000000..e5705f3 --- /dev/null +++ b/students/KevinCavanaugh/session8/base_class.py @@ -0,0 +1,133 @@ +import sqlite3 +from sqlite3 import Error as sqlErr +import re as rex + + +class DBProcessor(object): + + def __init__(self, db_name: str=":memory:"): # Handy for testing! + self.__db_name = db_name + self.__db_con = self.create_connection(self.db_name) + + @property + def db_name(self): # Get DB Name + return self.__db_name + + @property + def db_con(self): # Get Live Connection + return self.__db_con + + # SQL Validators + @staticmethod + def check_for_extra_semicolon(sql_str): + """Checks for an extra semicolon""" + # print(len("Select;Delete From T1; ID, Name FROM T1;".split(';')) > 2) + try: + if len(sql_str.split(';')) > 2: + raise sqlErr("Extra Semi-Colon Detected!") + except Exception as e: + raise e + + @staticmethod + def check_for_or(sql_str): + """Checks for an injected OR in tampered WHERE Clause""" + # print(rex.search("WHERE", "SELECT * FROM T1 WHERE", rex.IGNORECASE)) + # print(rex.search("or","FROM T1 WHERE ID = 1 or 1 = 1".split('WHERE')[1], rex.IGNORECASE)) + try: + if rex.search("WHERE", sql_str, rex.IGNORECASE): # If it has a Where clause + if rex.search(' or ', sql_str.split('WHERE')[1], rex.IGNORECASE) is not None: # injected OR? + raise sqlErr("OR Detected!") + except Exception as e: + raise e + + @staticmethod + def check_for_date(date_str): + """Checks for an valid date string""" + try: + if rex.match("\d\d\d\d-\d\d-\d\d", str(date_str)) is None: + raise sqlErr("Not a Date!") + except Exception as e: + raise e + + def create_connection(self, db_file: str): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + + def execute_sql_code(self, sql_code: str = ''): + """ Execute SQL code on a open connection """ + db_con = self.db_con + try: + if db_con is not None and sql_code != '': + # Validate + self.check_for_extra_semicolon(sql_code); + self.check_for_or(sql_code); + # Connect and Run + with db_con: + csr = db_con.cursor() + csr.execute(sql_code) + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in execute_sql_code(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in execute_sql_code(): ' + e.__str__()) + return csr + + def build_ins_code(self): # create (C/R/U/D) + # Validate Input + sql = str.format("INSERT Not Implemented Yet") + return sql + + def build_sel_code(self): # read + # Validate Input + sql = str.format("SELECT Not Implemented Yet") + return sql + + def build_upd_code(self): # update + # Validate Input + sql = str.format("UPDATE Not Implemented Yet") + return sql + + def build_del_code(self): # delete + # Validate Input + # Validate Input + sql = str.format("DELETE Not Implemented Yet") + return sql + + +class InventoryProcessor(DBProcessor): + + def build_ins_code(self, inventory_id: int, inventory_date: str): + DBProcessor.check_for_date(inventory_date) + sql = str.format("INSERT INTO Inventories (InventoryID, InventoryDate) " + "VALUES ({id},'{date}');", id=inventory_id, date=inventory_date) + return sql + + def build_upd_code(self, inventory_id: int, inventory_date: str ): + DBProcessor.check_for_date(inventory_date) + sql = str.format("UPDATE Inventories SET InventoryDate = '{date}' " + "WHERE InventoryID = {id};", id=inventory_id, date=inventory_date) + return sql + + def build_del_code(self, inventory_id: int): + sql = str.format("DELETE FROM Inventories " + "WHERE InventoryID = {id};", id=inventory_id) + return sql + + def build_sel_code(self, inventory_id: int = None): + if inventory_id is not None: + w = ' WHERE InventoryID = ' + str(inventory_id) + else: + w = '' + sql = str.format("SELECT InventoryID, InventoryDate " + "FROM Inventories{WHERE};", WHERE=w) + return sql + + + diff --git a/students/KevinCavanaugh/session8/circle_classes_assignment.py b/students/KevinCavanaugh/session8/circle_classes_assignment.py new file mode 100644 index 0000000..e4ddf82 --- /dev/null +++ b/students/KevinCavanaugh/session8/circle_classes_assignment.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# ----------------------------------------------------------------------- # +# Title: html_render +# Author: Kevin Cavanaugh +# Change Log: (Who,What,When) +# kcavanau, started assignment, 03/03/2019 +# ----------------------------------------------------------------------- # + +''' +The purpose of this assignment is to create a nifty Circle class that will +demonstrate properties and Python's magic methods +''' + +from math import pi + +########## +# STEP 1 # +########## + +class Circle(object): + ''' + This is a simple class utilzed to represent a circle + ''' + + def __init__(self, radius): + self.radius = float(radius) + + ########## + # STEP 2 # + ########## + + @property + def diameter(self): + return self.radius * 2 + + ########## + # STEP 3 # + ########## + + @diameter.setter + def diameter(self, value): + self.radius = value / 2 + + ########## + # STEP 4 # + ########## + + @property + def area(self): + return self.radius ** 2 * pi + + ########## + # STEP 5 # + ########## + + @classmethod + def from_diameter(cls, diameter): + return cls(diameter/2) + + ########## + # STEP 6 # + ########## + + def __str__(self): + return f'Circle with radius: {self.radius:6f}' + + def __repr__(self): + return f'Circle({self.radius})' + +c = Circle(4) +d = eval(repr(c)) + +print(d) + + diff --git a/students/KevinCavanaugh/session8/demo.py b/students/KevinCavanaugh/session8/demo.py new file mode 100644 index 0000000..fbdfacd --- /dev/null +++ b/students/KevinCavanaugh/session8/demo.py @@ -0,0 +1,146 @@ +import sqlite3 +from sqlite3 import Error as sqlErr + +def create_connection(db_file): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + print('SQLite Version is: ', sqlite3.version) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + +def execute_sql_code(db_con = None, sql_code=''): + """ Execute SQL code on a open connection """ + try: + if db_con is not None and sql_code != '': + csr = db_con.cursor() + csr.execute(sql_code) + db_con.commit() + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return csr + +def create_table_code(name_of_table, col_names=[None]): + """ Create staging table code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column!') + else: + sql_str = 'CREATE TABLE ' + name_of_table + '(' + for col in col_names: + sql_str += str(col) + ' [text], ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_table(): ' + e.__str__()) + return sql_str + +def create_select_code(name_of_table, col_names=[None]): + """ create staging table select code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'SELECT \n' + for col in col_names: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + '\n' # Strip off the last comma + sql_str += 'FROM ' + name_of_table + ';' + except Exception as e: + raise Exception('Error in create_select_code(): ' + e.__str__()) + return sql_str + +def create_insert_code(name_of_table, col_names=[None], col_values=[None],): + """ create staging table insert code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + else: + sql_str = 'INSERT INTO ' + str(name_of_table).strip() + '\n(' + for col in col_names: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ')' # Strip off the last comma + if col_values is None: + raise Exception('You must provide at least one column value!') + else: + sql_str += '\nVALUES\n(' + for col in col_values: + sql_str += str(col) + ', ' + sql_str = sql_str[0:-2] + ');' # Strip off the last comma + except Exception as e: + raise Exception('Error in create_insert_code(): ' + e.__str__()) + return sql_str + +def create_update_code(name_of_table, col_names=[None], col_values=[None], where_col = None, where_equals_value = None): + """ create staging table update code """ + sql_str = '' + try: + if col_names is None: + raise Exception('You must provide at least one column name!') + elif col_values is None: + raise Exception('You must provide at least one column value!') + elif len(col_names) != len(col_values): + raise Exception('You must provide one value for each column') + elif where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'UPDATE ' + str(name_of_table).strip() + '\nSET\n\t' + counter = 0 + while counter < len(col_names): + sql_str += str(col_names[counter]).strip() \ + + ' = ' + str(col_values[counter]).strip() + ', \n\t' + counter += 1 + sql_str = (sql_str.strip())[0:-1] + '' # Strip off the last comma + sql_str += '\nWHERE ' + where_col + " = " + where_equals_value + except Exception as e: + raise Exception('Error in create_update_code(): ' + e.__str__()) + return sql_str + +def create_delete_code(name_of_table, where_col = None, where_equals_value = None): + """ create staging table delete code """ + sql_str = '' + try: + if where_col is None or where_equals_value is None: + raise Exception('You must provide a where column and an equals value') + else: + sql_str = 'DELETE FROM ' + str(name_of_table).strip() + sql_str += '\nWHERE ' + where_col + " = " + str(where_equals_value).strip() + except Exception as e: + raise Exception('Error in create_delete_code(): ' + e.__str__()) + return sql_str + + +if __name__ == '__main__': + + try: + print('\ntest SELECT','-'*40, '\n') + print(create_select_code('StagingStudents', ['ID,Name,Email'])) + except Exception as e: + print(e) + + try: + print('\ntest INSERT','-'*40, '\n') + print(create_insert_code('StagingStudents', ['ID,Name,Email'], [1,'Bob Smith', 'BSmith@gomail.com'])) + except Exception as e: + print(e) + + try: + print('\ntest UPDATE','-'*40, '\n') + print(create_update_code('StagingStudents', ['Name','Email'], ['Rob Smith', 'RSmith@gomail.com'], 'ID', '1')) + except Exception as e: + print(e) + + try: + print('\ntest DELETE','-'*40, '\n') + print(create_delete_code('StagingStudents', 'ID', '1')) + except Exception as e: + print(e) \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/demo_2.py b/students/KevinCavanaugh/session8/demo_2.py new file mode 100644 index 0000000..d152a30 --- /dev/null +++ b/students/KevinCavanaugh/session8/demo_2.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +from tkinter import * +fields = ('Annual Rate', 'Number of Payments', 'Loan Principle', 'Monthly Payment', 'Remaining Loan') + +def monthly_payment(entries): + # period rate: + r = (float(entries['Annual Rate'].get()) / 100) / 12 + print("r", r) + # principal loan: + loan = float(entries['Loan Principle'].get()) + n = float(entries['Number of Payments'].get()) + remaining_loan = float(entries['Remaining Loan'].get()) + q = (1 + r)** n + monthly = r * ( (q * loan - remaining_loan) / ( q - 1 )) + monthly = ("%8.2f" % monthly).strip() + entries['Monthly Payment'].delete(0,END) + entries['Monthly Payment'].insert(0, monthly ) + print("Monthly Payment: %f" % float(monthly)) + +def final_balance(entries): + # period rate: + r = (float(entries['Annual Rate'].get()) / 100) / 12 + print("r", r) + # principal loan: + loan = float(entries['Loan Principle'].get()) + n = float(entries['Number of Payments'].get()) + q = (1 + r)** n + monthly = float(entries['Monthly Payment'].get()) + q = (1 + r)** n + remaining = q * loan - ( (q - 1) / r) * monthly + remaining = ("%8.2f" % remaining).strip() + entries['Remaining Loan'].delete(0,END) + entries['Remaining Loan'].insert(0, remaining ) + print("Remaining Loan: %f" % float(remaining)) + +def makeform(root, fields): + entries = {} + for field in fields: + row = Frame(root) + lab = Label(row, width=22, text=field+": ", anchor='w') + ent = Entry(row) + ent.insert(0,"0") + row.pack(side=TOP, fill=X, padx=5, pady=5) + lab.pack(side=LEFT) + ent.pack(side=RIGHT, expand=YES, fill=X) + entries[field] = ent + return entries + +if __name__ == '__main__': + root = Tk() + ents = makeform(root, fields) + root.bind('', (lambda event, e=ents: fetch(e))) + b1 = Button(root, text='Final Balance', + command=(lambda e=ents: final_balance(e))) + b1.pack(side=LEFT, padx=5, pady=5) + b2 = Button(root, text='Monthly Payment', + command=(lambda e=ents: monthly_payment(e))) + b2.pack(side=LEFT, padx=5, pady=5) + b3 = Button(root, text='Quit', command=root.quit) + b3.pack(side=LEFT, padx=5, pady=5) + root.mainloop() \ No newline at end of file diff --git a/students/KevinCavanaugh/session8/inventory_processor.py b/students/KevinCavanaugh/session8/inventory_processor.py new file mode 100644 index 0000000..75ee129 --- /dev/null +++ b/students/KevinCavanaugh/session8/inventory_processor.py @@ -0,0 +1,30 @@ +from base_class import DBProcessor + + +class InventoryProcessor(DBProcessor): + + def build_ins_code(self, inventory_id: int, inventory_date: str): + DBProcessor.check_for_date(inventory_date) + sql = str.format("INSERT INTO Inventories (InventoryID, InventoryDate) " + "VALUES ({id},'{date}');", id=inventory_id, date=inventory_date) + return sql + + def build_upd_code(self, inventory_id: int, inventory_date: str ): + DBProcessor.check_for_date(inventory_date) + sql = str.format("UPDATE Inventories SET InventoryDate = '{date}' " + "WHERE InventoryID = {id};", id=inventory_id, date=inventory_date) + return sql + + def build_del_code(self, inventory_id: int): + sql = str.format("DELETE FROM Inventories " + "WHERE InventoryID = {id};", id=inventory_id) + return sql + + def build_sel_code(self, inventory_id: int = None): + if inventory_id is not None: + w = ' WHERE InventoryID = ' + str(inventory_id) + else: + w = '' + sql = str.format("SELECT InventoryID, InventoryDate " + "FROM Inventories{WHERE};", WHERE=w) + return sql diff --git a/students/KevinCavanaugh/session8/lesson_08.db b/students/KevinCavanaugh/session8/lesson_08.db new file mode 100644 index 0000000..e8e37e4 Binary files /dev/null and b/students/KevinCavanaugh/session8/lesson_08.db differ diff --git a/students/KevinCavanaugh/session8/run_inventory_processor.py b/students/KevinCavanaugh/session8/run_inventory_processor.py new file mode 100644 index 0000000..503b160 --- /dev/null +++ b/students/KevinCavanaugh/session8/run_inventory_processor.py @@ -0,0 +1,29 @@ +import base_class as dp + +if debugIP == True: + ip = dp.InventoryProcessor(':memory:') + print(ip.build_ins_code(inventory_id=1, inventory_date='2000-01-01')) + print(ip.build_upd_code(inventory_id=1, inventory_date='2000-02-02')) + print(ip.build_del_code(inventory_id=1)) + print(ip.build_sel_code()) + + # Create a table for testing + crs = ip.db_con.cursor() + crs.execute("CREATE TABLE Inventories (InventoryID int, InventoryDate date);") + ip.db_con.commit() + for row in crs.execute("Select name, sql From sqlite_master Where type='table;'"): + print(row) + ip.db_con.commit() + + # Test SQL Transactions + ip.execute_sql_code(ip.build_ins_code(inventory_id=1, inventory_date='2000-01-01')).close() + for row in ip.execute_sql_code(ip.build_sel_code()): + print(row) + + ip.execute_sql_code(ip.build_upd_code(inventory_id=1, inventory_date='2000-02-02')).close() + for row in ip.execute_sql_code(ip.build_sel_code(inventory_id=1)): + print(row) + + ip.execute_sql_code(ip.build_del_code(inventory_id=1)).close() + for row in ip.execute_sql_code(ip.build_sel_code()): + print(row) diff --git a/students/KevinCavanaugh/session8/sqlite3_project.py b/students/KevinCavanaugh/session8/sqlite3_project.py new file mode 100644 index 0000000..83ea655 --- /dev/null +++ b/students/KevinCavanaugh/session8/sqlite3_project.py @@ -0,0 +1,141 @@ +import sqlite3 +from sqlite3 import Error as sqlErr +import re as rex + +from sqlite3 import Error as sql_err + +#!/usr/bin/env python3 + +# ----------------------------------------------------------------------- # +# Title: sqlite3_project +# Author: Kevin Cavanaugh +# Change Log: (Who,What,When) +# kcavanau, started assignment, 03/05/2019 +# ----------------------------------------------------------------------- # +def create_connection(db_file: str = 'C:\sqlite\databases\Python210FinalDB.db'): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + + +# SQL Validators +def check_for_extra_semicolon(sql_str): + """Checks for an extra semicolon""" + # print(len("Select;Delete From T1; ID, Name FROM T1;".split(';')) > 2) + try: + if len(sql_str.split(';')) > 2: + raise sqlErr("Extra Semi-Colon Detected!") + except Exception as e: + raise e + + +def check_for_or(sql_str): + """Checks for an injected OR in tampered WHERE Clause""" + # print(rex.search("WHERE", "SELECT * FROM T1 WHERE", rex.IGNORECASE)) + # print(rex.search("or","FROM T1 WHERE ID = 1 or 1 = 1".split('WHERE')[1], rex.IGNORECASE)) + try: + if rex.search("WHERE", sql_str, rex.IGNORECASE): # If it has a Where clause + if rex.search(' or ', sql_str.split('WHERE')[1], rex.IGNORECASE) is not None: # check injected OR + raise sqlErr("OR Detected!") + except Exception as e: + raise e + + +def check_for_date(date_str): + try: + if rex.match("\d\d\d\d-\d\d-\d\d", str(date_str)) is None: # Returns None if not matched + raise sqlErr("Not a Date!") + except Exception as e: + raise e + + +def execute_sql_code(db_con: object = None, sql_code: str = ''): + """ Execute SQL code on a open connection """ + try: + if db_con is not None and sql_code != '': + # Validate + check_for_extra_semicolon(sql_code); + check_for_or(sql_code); + # Connect and Run + with db_con: + csr = db_con.cursor() + csr.execute(sql_code) + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in execute_sql_code(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in execute_sql_code(): ' + e.__str__()) + return csr + + +# Inventory +def ins_inventory(inventory_id: int, inventory_date: str): + check_for_date(inventory_date) + sql = str.format("INSERT INTO Inventories (InventoryID, InventoryDate) " + "VALUES ({id},'{date}');", id=inventory_id, date=inventory_date) + return sql + + +def upd_inventory(inventory_id: int, inventory_date: str): + check_for_date(inventory_date) + sql = str.format("UPDATE Inventories SET InventoryDate = '{date}' " + "WHERE InventoryID = {id};", id=inventory_id, date=inventory_date) + return sql + + +def del_inventory(inventory_id: int): + sql = str.format("DELETE FROM Inventories WHERE InventoryID = {id};", id=inventory_id) + return sql + + +def sel_inventory(inventory_id: int = None): + if inventory_id is not None: + inventory_id = ' WHERE inventory_id = ' + str(inventory_id) # Will be validated at execution! + else: + inventory_id = '' + sql = str.format("SELECT InventoryID, InventoryDate FROM Inventories{id};", id=inventory_id) + return sql + + +if __name__ == '__main__': + try: + db = create_connection() + except Exception as e: + print('Connection failed!', e) + + # Test SQL creation + sql_str = ins_inventory(inventory_id=3, inventory_date='2000-03-01') + print(sql_str) + sql_str = upd_inventory(inventory_id=3, inventory_date='2000-03-02') + print(sql_str) + sql_str = del_inventory(inventory_id=3) + print(sql_str) + sql_str = sel_inventory() + print(sql_str) + sql_str = sel_inventory(inventory_id=3) + print(sql_str) + + # Test SQL validation + try: + check_for_or(sel_inventory(inventory_id="2 OR 1 = 1")) # SQL Injection + except Exception as e: + print(e) + try: + check_for_extra_semicolon(sel_inventory(inventory_id="1;Delete From T1;")) # SQL Injection + except Exception as e: + print(e) + try: + check_for_date(ins_inventory(inventory_id=3, inventory_date='03/03/2000')) # Date Format Error + except Exception as e: + print(e) + + # Test SQL execution + csr = execute_sql_code(db_con=db, sql_code=sel_inventory()) + for row in csr: + print(row) diff --git a/students/KevinCavanaugh/session8/test final.py b/students/KevinCavanaugh/session8/test final.py new file mode 100644 index 0000000..b702e19 --- /dev/null +++ b/students/KevinCavanaugh/session8/test final.py @@ -0,0 +1,143 @@ +import sqlite3 +from sqlite3 import Error as sqlErr +import re as rex + +from sqlite3 import Error as sql_err + +#!/usr/bin/env python3 + +# ----------------------------------------------------------------------- # +# Title: sqlite3_project +# Author: Kevin Cavanaugh +# Change Log: (Who,What,When) +# kcavanau, started assignment, 03/05/2019 +# ----------------------------------------------------------------------- # +def create_connection(db_file: str = ':memory:'): + """ Create or connect to a SQLite database """ + try: + con = sqlite3.connect(db_file) + except sqlErr as se: + raise Exception('SQL Error in create_connection(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in create_connection(): ' + e.__str__()) + return con + + +# SQL Validators +def check_for_extra_semicolon(sql_str): + """Checks for an extra semicolon""" + # print(len("Select;Delete From T1; ID, Name FROM T1;".split(';')) > 2) + try: + if len(sql_str.split(';')) > 2: + raise sqlErr("Extra Semi-Colon Detected!") + except Exception as e: + raise e + + +def check_for_or(sql_str): + """Checks for an injected OR in tampered WHERE Clause""" + # print(rex.search("WHERE", "SELECT * FROM T1 WHERE", rex.IGNORECASE)) + # print(rex.search("or","FROM T1 WHERE ID = 1 or 1 = 1".split('WHERE')[1], rex.IGNORECASE)) + try: + if rex.search("WHERE", sql_str, rex.IGNORECASE): # If it has a Where clause + if rex.search(' or ', sql_str.split('WHERE')[1], rex.IGNORECASE) is not None: # check injected OR + raise sqlErr("OR Detected!") + except Exception as e: + raise e + + +def check_for_date(date_str): + try: + if rex.match("\d\d\d\d-\d\d-\d\d", str(date_str)) is None: # Returns None if not matched + raise sqlErr("Not a Date!") + except Exception as e: + raise e + + +def execute_sql_code(db_con: object = None, sql_code: str = ''): + """ Execute SQL code on a open connection """ + try: + if db_con is not None and sql_code != '': + # Validate + check_for_extra_semicolon(sql_code); + check_for_or(sql_code); + # Connect and Run + with db_con: + csr = db_con.cursor() + csr.execute(sql_code) + else: + raise Exception('SQL Code or Connection is missing!') + except sqlErr as se: + raise Exception('SQL Error in execute_sql_code(): ' + se.__str__()) + except Exception as e: + raise Exception('General Error in execute_sql_code(): ' + e.__str__()) + return csr + + +# Inventory +def ins_inventory(inventory_id: int, inventory_date: str): + check_for_date(inventory_date) + sql = str.format("INSERT INTO Inventories (InventoryID, InventoryDate) " + "VALUES ({id},'{date}');", id=inventory_id, date=inventory_date) + return sql + + +def upd_inventory(inventory_id: int, inventory_date: str): + check_for_date(inventory_date) + sql = str.format("UPDATE Inventories SET InventoryDate = '{date}' " + "WHERE InventoryID = {id};", id=inventory_id, date=inventory_date) + return sql + + +def del_inventory(inventory_id: int): + sql = str.format("DELETE FROM Inventories WHERE InventoryID = {id};", id=inventory_id) + return sql + + +def sel_inventory(inventory_id: int = None): + if inventory_id is not None: + inventory_id = ' WHERE inventory_id = ' + str(inventory_id) # Will be validated at execution! + else: + inventory_id = '' + sql = str.format("SELECT InventoryID, InventoryDate FROM Inventories{id};", id=inventory_id) + return sql + + +if __name__ == '__main__': + try: + db = create_connection() + except Exception as e: + print('Connection failed!', e) + + # Test SQL creation + str_create_table = """CREATE TABLE Inventories (InventoryID int Primary Key, InventoryDate date);""" + sql_str = ins_inventory(inventory_id=3, inventory_date='2000-03-01') + print(sql_str) + sql_str = upd_inventory(inventory_id=3, inventory_date='2000-03-02') + print(sql_str) + sql_str = del_inventory(inventory_id=3) + print(sql_str) + sql_str = sel_inventory() + print(sql_str) + sql_str = sel_inventory(inventory_id=3) + print(sql_str) + + # Test SQL validation + try: + check_for_or(sel_inventory(inventory_id="2 OR 1 = 1")) # SQL Injection + except Exception as e: + print(e) + try: + check_for_extra_semicolon(sel_inventory(inventory_id="1;Delete From T1;")) # SQL Injection + except Exception as e: + print(e) + try: + check_for_date(ins_inventory(inventory_id=3, inventory_date='03/03/2000')) # Date Format Error + except Exception as e: + print(e) + + + # Test SQL execution + csr = execute_sql_code(db_con=db, sql_code=sel_inventory()) + for row in csr: + print(row) diff --git a/students/KevinCavanaugh/session8/test_base.py b/students/KevinCavanaugh/session8/test_base.py new file mode 100644 index 0000000..376bacb --- /dev/null +++ b/students/KevinCavanaugh/session8/test_base.py @@ -0,0 +1,56 @@ + +import base_class as dp + +debugDP = False +debugIP = True + +if __name__ == '__main__': + # Test DataProcessor methods + if debugDP == True: + try: dp.DBProcessor.check_for_or("SELECT * FROM T1 WHERE ID = 1 or 1 = 1") + except Exception as e: print(e) + try: dp.DBProcessor.check_for_extra_semicolon("SELECT * ;Delete From T1; FROM T1;") + except Exception as e: print(e) + try: dp.DBProcessor.check_for_date('01/01/2000') + except Exception as e: print(e) + + dbp = dp.DBProcessor(':memory:') + print(dbp.build_ins_code()) + print(dbp.build_upd_code()) + print(dbp.build_del_code()) + print(dbp.build_sel_code()) + print(dbp.build_sel_code()) + csr = dbp.execute_sql_code("Select 5 + 5;") + for e in csr: + print(e) + print(dbp.execute_sql_code("Select 5 + 5;")) + dbp.db_con.close() + + if debugIP == True: + ip = dp.InventoryProcessor(':memory:') + print(ip.build_ins_code(inventory_id=1, inventory_date='2000-01-01')) + print(ip.build_upd_code(inventory_id=1, inventory_date='2000-02-02')) + print(ip.build_del_code(inventory_id=1)) + print(ip.build_sel_code()) + + # Create a table for testing + crs = ip.db_con.cursor() + crs.execute("CREATE TABLE Inventories (InventoryID int, InventoryDate date);") + ip.db_con.commit() + for row in crs.execute("Select name, sql From sqlite_master Where type='table;'"): + print(row) + ip.db_con.commit() + + # Test SQL Transactions + ip.execute_sql_code(ip.build_ins_code(inventory_id=1, inventory_date='2000-01-01')).close() + for row in ip.execute_sql_code(ip.build_sel_code()): + print(row) + + ip.execute_sql_code(ip.build_upd_code(inventory_id=1, inventory_date='2000-02-02')).close() + for row in ip.execute_sql_code(ip.build_sel_code(inventory_id=1)): + print(row) + + ip.execute_sql_code(ip.build_del_code(inventory_id=1)).close() + for row in ip.execute_sql_code(ip.build_sel_code()): + print(row) +