Skip to content

Commit e0f9892

Browse files
authored
Merge pull request #61 from oslabs-beta/stephen-crud
Stephen crud
2 parents fa6a244 + 16e1fd4 commit e0f9892

File tree

15 files changed

+86
-444
lines changed

15 files changed

+86
-444
lines changed

Contributors.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22

33
Below is a list of features and improvements to which you can contribute. If you have any additional ideas, please raise an issue or implement them as well!
44

5-
- Delete Table
6-
- Add a command to delete a table from the canvas, making sure to implement checks to maintain data integrity
75
- Logging needs a default settings list and direct reimport into live database.
8-
- The SQL code to import has been placed into the DB_Schemas folder along with SQL Schema dumps. Also, log setting functionality is currently limited to Postgres databases and the code needs to be expanded to query and display log setting info from MySQL databases.
6+
- The SQL code to import has been placed into the DB_Schemas folder along with SQL Schema dumps. Also, log setting functionality is currently limited to Postgres databases and the code needs to be expanded to query and display log setting info from MySQL databases.
97
- Db-schemas
108
- The schemas are saved under db_schemas and is saved in the server. Have a way to delete the schemas on the server from the front end. It would also be convenient to add these schemas to a list of existing schemas and be able to pull these schemas to display for the user to avoid having to make a new connection to the same database multiple times.
11-
- Expand compatibility with other SQL database such as Oracle SQL, Microsoft SQL, IBM Db2, etc.
9+
- Complete the integration of SQLite as an optional database and expand compatibility with other SQL database such as IBM Db2, etc.
1210
- Add additional themes and graphical options to canvas and tables
1311
- Live query feedback so users can see what their changes to the canvas look like as queries.
12+
<<<<<<< HEAD
13+
- As the ability to manipulate data has been recently added, there are not as many safe guards to prevent users from performing actions that are not allowed for some databases.
14+
- Limiting the data types to only those possible for the the database the user is currently working on.
15+
- Adding Account specific functionality and the ability to save data to your account.
16+
- TypeORM has been implemented to connect to multiple databases but can be modified to further universal database functions
17+
=======
1418
- Create login feature to save multiple databases to user account and be able to load multiple past databases.
19+
>>>>>>> dev
1520
1621
Known bugs/issues
1722

1823
- Undo function will not revert the state of the canvas to the point where it is empty.
24+
- Attempting to change the name of a column while adding a foreign key will result in the page crashing and going all white. Changing the column name is currently disabled.
25+
- When creating a new foreign key on a column, if you click submit while there is no table selected, the display area will shrink to a very small square in the top left corner of the page.
26+
- Exporting your query has been affected in the course of adding additional databases and needs to be reorganized

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121

2222
- Enhanced support for SQL databases with expanded options.
2323
- Introduction of visualized DATA tables for improved data analysis.
24-
- Full CRUD functionality enabling the addition, modification, and deletion of rows in DATA tables within the database.
25-
- Capability to remove tables as needed.
24+
- Robust CRUD functionality enabling the addition, modification, and deletion of rows in DATA tables within the database.
25+
- Capability to remove and add tables as needed.
2626
- Implementation of Google and GitHub OAuth log-ins for streamlined user authentication.
2727

2828

2929
### Use Cases
3030

31-
- Connecting to an existing remote PostgreSQL, MySQL, MicroSoftSQL, OracleSQL, and SQLite3 database
31+
- Connecting to an existing remote PostgreSQL, MySQL, MicroSoftSQL, OracleSQL databases
3232
- Renders an ER diagram for SCHEMA and DATA of the existing database and provides an interface for users to both modify existing tables and create new tables. A log of changes is stored, and at any point, the user can generate a query containing the changes, such that they are reflected in the existing database.
3333
- Uploading your database's SQL file
3434
- Renders an ER diagram for the provided SQL file (db dump) and provides an interface for a user to both modify existing tables and create new tables. Changes are converted into the corresponding queries, which the user can view and execute on their own database outside of dbSpy.
@@ -158,6 +158,7 @@ npm run cert:linux
158158
2. Select the database type from the dropdown.
159159
3. Input your database URI information OR database connection credentials and click on "Connect".
160160
4. Once the connection to your database is established, the canvas will render and generate the tables and their relationships.
161+
* OracleSQL requires the download of the OCI - [here](https://www.oracle.com/cloud/free/)
161162

162163
<img src="images/withDataButton.png">
163164

@@ -173,18 +174,23 @@ npm run cert:linux
173174

174175
## Adding column(s) to a SCHEMA table or row(s) to a DATA table
175176

176-
1. To add a new column/row in a table, click on the add icon on the top right of the table node. This will render a new column/row in the table in edit mode. The changes made in DATA table will be updated in your database.
177+
1. To add a new column/row in a table, click on the add/plus icon on the top right of the table node.
178+
2. This will render a new column/row in the table in edit mode.
179+
3. Add in the data you would like in each column/row.
180+
4. Click on the confirm icon to save the column/row.
181+
5. The changes made in DATA table will be updated in your database.
182+
6. Click on the cancel icon to cancel the addition.
177183
<img src="images/Create%20tables.png">
178184
<img src="images/addRow.png">
179185

180-
### Editing an existing column to a SCHEMA table or row to a DATA table
186+
### Editing an existing row of a DATA table
181187

182188
1. Click on the edit icon of the specific column that you want to edit.
183189
2. You can make changes to column fields based on the selections provided.
184190
3. Click on the save icon to keep your changes.
185191
4. Click on the cancel icon to cancel your changes.
186192

187-
## Deleting an column to a SCHEMA table or row to a DATA table
193+
### Deleting a column to a SCHEMA table or row of a DATA table
188194

189195
1. Click on the delete icon of the specific column that you want to delete.
190196
2. Click on the confirm icon to delete the column.
@@ -197,6 +203,18 @@ npm run cert:linux
197203
3. Click save or cancel to proceed.
198204
4. Click on the save icon to keep your changes or click on the cancel icon to cancel your changes.
199205

206+
### Adding a table to a database
207+
208+
1. When on the display page, click the 'Add Table' icon after you have either connected to a database or clicked 'Build Database'.
209+
2. Fill in the required information about the first column of your table along with a name.
210+
3. If you would like to include additional columns, click the 'Add Column' button in the top right corner.
211+
3. Click confirm to create your table.
212+
213+
### Deleting a table from a database
214+
215+
1. After you have either connected to a database or started a new database, the 'Delete Table' icon will appear on the left side of the display page
216+
2. This will open a pop out with a list of tables from the database.
217+
3. Select which table that you would like to have removed, and confirm to have it deleted.
200218

201219
### Navigating the canvas
202220

@@ -218,9 +236,9 @@ npm run cert:linux
218236
---
219237

220238
### Credits/Contributors
221-
- Yichung Chiu • [LinkedIn][Github]
222-
- Joseph Tejeda • [LinkedIn][Github]
223-
- Stephen Havig • [LinkedIn][Github]
239+
- Yichung Chiu • [LinkedIn](https://www.linkedin.com/in/yichung-chiu-b14a94272/)[Github](https://github.com/ychiu5896)
240+
- Joseph Tejeda • [LinkedIn](https://www.linkedin.com/in/atxjtejeda/)[Github](https://github.com/JosephTejeda)
241+
- Stephen Havig • [LinkedIn](https://www.linkedin.com/in/stephen-havig-199340145/)[Github](https://github.com/Stephen-Havig)
224242
- Das Kang • [LinkedIn](https://www.linkedin.com/in/das-kang/)[Github](https://github.com/dahae0309)
225243
- Alexander Tu • [LinkedIn](https://www.linkedin.com/in/atu816/)[Github](http://github.com/atu816)
226244
- Michael Costello • [LinkedIn](https://www.linkedin.com/in/mcostello-swe/)[Github](https://github.com/neighbor-peace)

server/controllers/helperFunctions/universal.helpers.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { RequestHandler, Request, Response, NextFunction } from 'express';
22
import { DataSource } from 'typeorm';
33

44

5+
// HELPER FUNCTIONS FOR THE HELPER FUNCTIONS
56

67
const tableNameFormat = async (req: Request, dbDataSource: DataSource) => {
78
const { db_type, username } = req.session;
@@ -304,18 +305,19 @@ export const addNewDbColumn: RequestHandler = async (req: Request, _res: Respons
304305

305306
export const updateDbColumn: RequestHandler = async (req: Request, _res: Response, next: NextFunction,) => {
306307
const dbDataSource = await dbConnect(req);
307-
const { db_type, username } = req.session;
308-
const { tableName, columnName, schemaData, columnData } = req.body;
308+
const { db_type } = req.session;
309+
const { columnName, schemaData, columnData } = req.body;
309310

310311
try{
311312
const tableNameUpdateColumn = await Promise.resolve(tableNameFormat(req, dbDataSource));
312313
console.log('schemaData: ', schemaData)
313314
console.log('columnData: ', columnData)
314315

315-
// const updatedColumn: Promise<unknown> = await dbDataSource.query(`
316-
// ALTER TABLE ${tableNameUpdateColumn}
317-
// ${db_type === 'postgres' || db_type === 'microsoft' ? 'ALTER COLUMN' : 'MODIFY' } "${columnName}" ${db_type} ${db_type === 'postgres' ? updateColumnData.constraintName : null} ${updateColumnData.constraintExpression}
318-
// `);
316+
317+
await dbDataSource.query(`
318+
UPDATE ${tableNameUpdateColumn}
319+
${db_type === 'postgres' || db_type === 'microsoft' ? 'ALTER COLUMN' : 'MODIFY' } "${columnName}" ${db_type} ${ columnData.additional_constraint ? columnData.additional_constraint : ''};
320+
`);
319321

320322
dbDataSource.destroy();
321323
console.log('Database has been disconnected');

server/controllers/microsoftData.controller.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@ const microsoftController = {
2626
const references: {[key: string]: string | boolean}[] = []
2727
if (foreignKey){
2828
references.push({
29-
// isDestination: false,
30-
// PrimaryKeyName: foreignKey.column_name,
31-
// PrimaryKeyTableName: 'public.' + tableName,
32-
// ReferencesPropertyName: foreignKey.referenced_column_name,
33-
// ReferencesTableName: 'public.' + foreignKey.referenced_table_name,
34-
// constraintName: foreignKey.constraint_name,
29+
// These got a little mixed up but are in the right place
3530
isDestination: false,
3631
PrimaryKeyName: foreignKey.referenced_column_name,
3732
PrimaryKeyTableName: 'public.' + foreignKey.referenced_table_name,

server/controllers/mysqlData.controller.ts

Lines changed: 2 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,7 @@ const mysqlController = {
4040
const references: {[key: string]: string | boolean}[] = [];
4141
if (foreignKey){
4242
references.push({
43-
// isDestination: false,
44-
// PrimaryKeyName: foreignKey.COLUMN_NAME,
45-
// PrimaryKeyTableName: 'public.' + tableName,
46-
// ReferencesPropertyName: foreignKey.REFERENCED_COLUMN_NAME,
47-
// ReferencesTableName: 'public.' + foreignKey.REFERENCED_TABLE_NAME,
48-
// constraintName: foreignKey.CONSTRAINT_NAME,
43+
// These got a little mixed up but are in the right place
4944
isDestination: false,
5045
PrimaryKeyName: foreignKey.REFERENCED_COLUMN_NAME,
5146
PrimaryKeyTableName: 'public.' + foreignKey.REFERENCED_TABLE_NAME,
@@ -255,196 +250,4 @@ const mysqlController = {
255250
//---------------------------------------------------------------------------------------------------
256251

257252
};
258-
export default mysqlController;
259-
260-
// // SSL data stored as environment variable for GitHub Actions access
261-
// // Also stored in .cert file because Elastic Beanstalk has a ~4000 char limit for its environment variables
262-
// const SSL_KEY =
263-
// typeof process.env.SSL_KEY === 'string'
264-
// ? Buffer.from(process.env.SSL_KEY, 'base64').toString('ascii')
265-
// : fs.readFileSync('./.cert/key.pem').toString();
266-
// const SSL_CERT =
267-
// typeof process.env.SSL_CERT === 'string'
268-
// ? Buffer.from(process.env.SSL_CERT, 'base64').toString('ascii')
269-
// : fs.readFileSync('./.cert/cert.pem').toString();
270-
271-
// /**
272-
// // * mySQLdataController.getSchema
273-
// // * @param {string} hostname - A required string with database hostname
274-
// // * @param {string} password - A required string with database password
275-
// // * @param {string} port - A required string with database port
276-
// // * @param {string} username - A required string with database username
277-
// // * @param {string} databaseName - A required string with the database name
278-
// // **/
279-
280-
// export const getSchema = async (req: Request, res: Response, next: NextFunction) => {
281-
// // // Option 1 - Production
282-
// //use mysqldump to download mysql db schema
283-
// log.info('Connecting to mySQL database...');
284-
// const { hostname, password, port, username, database_name } = req.query;
285-
// try {
286-
// const result = await mysqldump({
287-
// connection: {
288-
// host: hostname,
289-
// password,
290-
// port,
291-
// user: username,
292-
// database: database_name,
293-
// ssl: {
294-
// key: SSL_KEY,
295-
// cert: SSL_CERT,
296-
// },
297-
// },
298-
// dumpToFile: '../db_schemas',
299-
// });
300-
// res.locals.data = result;
301-
// //const { tables } = result;
302-
// next();
303-
// } catch (error: unknown) {
304-
// log.info((error as Error).message);
305-
// next({ message: 'Error with getSchema middleware' });
306-
// }
307-
// };
308-
309-
// /**
310-
// * mySQLdataController.objSchema
311-
// * Iterates through data tables received from mySQL server
312-
// * Builds object to be returned to front-end
313-
// */
314-
// export const objSchema = (_req: Request, res: Response, next: NextFunction) => {
315-
// const db = res.locals.data;
316-
// const { tables } = db;
317-
// const results = {};
318-
319-
// //create Table class
320-
// class TableModel {
321-
// [key: string]: any;
322-
// constructor(public name: string) {}
323-
// }
324-
325-
// //create Properties class
326-
// class PropertyModel {
327-
// Name: string;
328-
// Value: any = null;
329-
// data_type: string = 'varchar';
330-
// TableName: string | null = null;
331-
// References: string[] = [];
332-
// IsPrimaryKey: boolean = false;
333-
// IsForeignKey: boolean = false;
334-
// additional_constraints: string = 'NA';
335-
// field_name: string;
336-
337-
// constructor(name: string) {
338-
// this.Name = name;
339-
// this.field_name = name;
340-
// }
341-
// }
342-
343-
// // create foreign key class
344-
// class ForeignKeyModel {
345-
// PrimaryKeyName: string | null = null; //key name at referenced table
346-
// PrimaryKeyTableName: string | null = null; // referenced table name
347-
// ReferencesPropertyName: string | null = null; //key name at current table
348-
// ReferencesTableName: string | null = null;//current table name
349-
// IsDestination: boolean = false;
350-
// constraintName: string | null = null; //constraint from SQL query
351-
// }
352-
353-
// //append tables and table properties to results
354-
// tables.forEach((table: any) => {
355-
// //check if table or view
356-
// if (!table.isView) {
357-
// //get unique keys
358-
// let uKeys = table.schema.slice(table.schema.indexOf('UNIQUE KEY'));
359-
// uKeys = uKeys.slice(uKeys.indexOf('(') + 1, uKeys.indexOf(')'));
360-
// if (uKeys.includes(',')) uKeys = uKeys.split(', ');
361-
// else uKeys = [uKeys];
362-
// const uniqueKeys = uKeys.map((key: string) => key.slice(1, -1));
363-
364-
// //get primary keys
365-
// let pKeys = table.schema.slice(table.schema.indexOf('PRIMARY KEY'));
366-
// pKeys = pKeys.slice(pKeys.indexOf('(') + 1, pKeys.indexOf(')'));
367-
// if (pKeys.includes(',')) pKeys = pKeys.split(', ');
368-
// else pKeys = [pKeys];
369-
// const primaryKeys = pKeys.map((key: string) => key.slice(1, -1));
370-
371-
// //create foreign key and reference object (foreign key: references)
372-
// const foreignKeyReferences: any = {};
373-
// //declare foreign keys/references helper function
374-
// type ForeignKeysFn = (string: string) => void;
375-
// const foreignKeys: ForeignKeysFn = function(string = '') {
376-
// if (string === '') return;
377-
// let constraint = null;
378-
// //find constraint name
379-
// if (string.slice(string.indexOf('CONSTRAINT'))) {
380-
// string = string.slice(string.indexOf('CONSTRAINT'));
381-
// string = string.slice(string.indexOf('`') + 1);
382-
// constraint = string.slice(0, string.indexOf('`'));
383-
// }
384-
// //find foreign key
385-
// string = string.slice(string.indexOf('FOREIGN KEY'));
386-
// string = string.slice(string.indexOf('(') + 2);
387-
// const fKey = string.slice(0, string.indexOf(')') - 1);
388-
// //find primary table name
389-
// string = string.slice(string.indexOf('REFERENCES'));
390-
// string = string.slice(string.indexOf('`') + 1);
391-
// const primaryTable = string.slice(0, string.indexOf('`'));
392-
// //find primary table name
393-
// const primaryKey = string.slice(string.indexOf('(') + 2, string.indexOf(')') - 1);
394-
// //create new ForeignKeyModel and assign properties
395-
// foreignKeyReferences[fKey] = new ForeignKeyModel();
396-
// foreignKeyReferences[fKey].ReferencesPropertyName = fKey;
397-
// foreignKeyReferences[fKey].ReferencesTableName = table.name;
398-
// foreignKeyReferences[fKey].PrimaryKeyName = primaryKey;
399-
// foreignKeyReferences[fKey].PrimaryKeyTableName = primaryTable;
400-
// foreignKeyReferences[fKey].constraintName = constraint;
401-
402-
// //find additional foreign keys and references
403-
// return foreignKeys(string);
404-
// };
405-
// //invoke foreignKeys function and pass table.schema string
406-
// foreignKeys(table.schema);
407-
408-
// //create and assign new table to results object
409-
// //const results: { [key: string]: TableModel } = {}; ---> We Don't need this? -Stephen
410-
411-
412-
// //create new table properties
413-
// table.columnsOrdered.forEach((propName: string) => {
414-
// const newProp = new PropertyModel(propName);
415-
// //assign table name
416-
// newProp.TableName = table.name;
417-
// //assign field name
418-
// newProp.field_name = newProp.Name;
419-
// //assign data type
420-
// newProp.data_type = table.columns[newProp.Name].type;
421-
// //assign additional_constraints (primary, unique or not null)
422-
// if (primaryKeys.includes(newProp.Name))
423-
// newProp.additional_constraints = 'PRIMARY KEY';
424-
// else if (uniqueKeys.includes(newProp.Name))
425-
// newProp.additional_constraints = 'UNIQUE';
426-
// else if (!table.columns[propName].nullable)
427-
// newProp.additional_constraints = 'NOT NULL';
428-
// //check if primary key
429-
// if (primaryKeys.includes(newProp.Name)) newProp.IsPrimaryKey = true;
430-
// // check if foreign key and assign references
431-
// if (foreignKeyReferences[newProp.Name]) {
432-
// newProp.IsForeignKey = true;
433-
// newProp.References = [foreignKeyReferences[newProp.Name]];
434-
// }
435-
436-
// //assign new property to table
437-
// const results: {[key: string]: TableModel & {[key: string]: PropertyModel}} = {};
438-
// if (!results[table.name]) {
439-
// results[table.name] = new TableModel(table.name);
440-
// }
441-
// results[table.name][newProp.Name] = newProp;
442-
// });
443-
// }
444-
// });
445-
446-
// res.locals.data = results;
447-
// return next();
448-
// };
449-
450-
// export default mySQLdataController;
253+
export default mysqlController;

0 commit comments

Comments
 (0)