Skip to content

Commit

Permalink
define sqldatabase prototype
Browse files Browse the repository at this point in the history
This will allow us to define a sqllite module later, which we'll
want to transition to in order to do away with document data storage
as well as using a full blown mysql database for a simple scanner
frontend.
  • Loading branch information
juanvallejo committed Jul 16, 2021
1 parent a9581aa commit bc597b2
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 53 deletions.
2 changes: 1 addition & 1 deletion js/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ var api = {
handle_attendance_req: function(mysql, api, data) {

console.log('API', 'SYNC', 'ATTENDANCE', 'Attendance data requested by API server. Sending...');
mysql.connect().query('SELECT * FROM `attendance`', function(err, rows) {
mysql.query('SELECT * FROM `attendance`', function(err, rows) {

if(err) {
return console.log('MYSQL', 'SYNC', 'ATTENDANCE', 'ERR', err);
Expand Down
59 changes: 32 additions & 27 deletions js/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

var consts = require('./constants.js');
var date = require('./date.js');
var sqldatabase = require('./prototypes/sqldatabase.js');

const SqlServerExportStrategyName = 'mysql';
const ExcelExportStrategyName = 'excel';


var database = {

Expand Down Expand Up @@ -362,10 +367,7 @@ var database = {
console.log('MYSQL', 'Initializing event data...');

// create mysql entry for current event if it doesn't exist
mysql.connect()

// insert new entry into `events` table
.query('INSERT IGNORE INTO `events` (table_name, event_name, semester, year) VALUES ("' + scanner.getEventId() + '", "' + scanner.getEventName() + '", "' + date.get_semester() + '", "' + date.get_year() + '")', function(err) {
mysql.query('INSERT IGNORE INTO `events` (table_name, event_name, semester, year) VALUES ("' + scanner.getEventId() + '", "' + scanner.getEventName() + '", "' + date.get_semester() + '", "' + date.get_year() + '")', function(err) {

// tell program request has been parsed
mysql.isBusy = false;
Expand All @@ -380,8 +382,7 @@ var database = {

// index event's table and see which entries from database exist on it (done in case application is restarted more than once in the same event)
// update local database's entries with data from mysql table's entries
mysql.connect()
.query('SELECT * FROM `attendance` WHERE event_id="' + scanner.getEventId() + '"', function(err, evtRows, evtCols) {
mysql.query('SELECT * FROM `attendance` WHERE event_id="' + scanner.getEventId() + '"', function(err, evtRows, evtCols) {

if(err) {
return console.log('MYSQL', 'QUERY', 'An error occurred attempting to check previously stored data in mysql event table -> ' + err);
Expand Down Expand Up @@ -463,70 +464,74 @@ var database = {
});
},

init: function(scanner, mysql, api, output) {
init: function(scanner, sqlServer, api, output) {
// quick sanity check to make sure our sqlDatabase object has "sqldatabase" as its prototype
if(!sqlServer.isPrototypeOf(sqldatabase)) {
throw "provided sqlServer does not implement sqldatabase " + sqlServer.getPrototypeOf();
}

// before we try to populate internal database object, check to see if mysql server has any data in it
mysql.connect().query('SELECT * FROM `students` ORDER BY last ASC', function(err, rows, fields) {
// before we try to populate internal database object, check to see if SQL server has any data in it
sqlServer.query('SELECT * FROM `students` ORDER BY last ASC', function(err, rows, fields) {

if(err) {

// if error, assume mysql server is not available, don't use mysql server at all. Fall back to spreadsheet implementation and advertise this to console
console.log('WARN', 'MYSQL', 'Using spreadsheet file to populate database instead. (' + err + ')');
// if error, assume SQL server is not available, don't use SQL server at all. Fall back to spreadsheet implementation and advertise this to console
console.log('WARN', 'SQL', 'Using spreadsheet file to populate database instead. (' + err + ')');

// populate database from spreadsheet and exit
return scanner.populateDatabaseFromSpreadsheet(scanner, database, function(err) {

if(err) {
// if fallback spreadsheet implementation errors, advertise error message and exit.
return console.log( '[Fatal]: There was an error populating the database using spreadsheet' +
'file as backup, and the mysql database as a primary means -> ' + err);
'file as backup, and the SQL database as a primary means -> ' + err);
}

database.emit('ready', ['excel']);
database.emit('ready', [ExcelExportStrategyName]);

});
}

// if no error fetching data, check to see if any data in database. don't take into account if table has been created or not
if(rows.length) {

// if mysql table contains data, tell program
mysql.hasData = true;
// if SQL table contains data, tell program
sqlServer.hasData = true;

// then, begin adding such data to internal database object
scanner.populateDatabaseFromMysql(scanner, database, rows, function(err) {

if(!mysql.eventEntryCreated) {
database.initializeEventEntry(scanner, mysql, api, function() {
database.emit('ready', ['mysql']);
if(!sqlServer.eventEntryCreated) {
database.initializeEventEntry(scanner, sqlServer, api, function() {
database.emit('ready', [SqlServerExportStrategyName]);
});
}

});

} else {

// mysql database is empty. advertise that we are loading data from spreadsheet to populate mysql table
console.log('EXCEL', 'No data found on mysql server. Using spreadsheet to populate internal database.');
// SQL database is empty. advertise that we are loading data from spreadsheet to populate SQL table
console.log('EXCEL', 'No data found on SQL server. Using spreadsheet to populate internal database.');

// if no data in database, use spreadsheet data to populate our local database object, and then
// use the newly populated local 'database' object to populate mysql server database
// use the newly populated local 'database' object to populate SQL server database
scanner.populateDatabaseFromSpreadsheet(scanner, database, function(err) {

if(err) {
return console.log('[Fatal]: Error populating local database object from spreadsheet -> ' + err);
}

// once internal database object has data in it, export data to mysql server if empty
scanner.exportDatabase(scanner, database, mysql, api, output, 'mysql', consts.EXCEL_AUTOSAVE_FILE, function(err) {
// once internal database object has data in it, export data to SQL server if empty
scanner.exportDatabase(scanner, database, sqlServer, api, output, SqlServerExportStrategyName, consts.EXCEL_AUTOSAVE_FILE, function(err) {

if(err) {
console.log('An error occurred populating empty mysql database -> ' + err);
return database.emit('ready', ['excel']);
console.log('An error occurred populating empty SQL database -> ' + err);
return database.emit('ready', [ExcelExportStrategyName]);
}

// begin auto-saving new data to mysql database
database.emit('ready', ['mysql']);
// begin auto-saving new data to SQL database
database.emit('ready', [SqlServerExportStrategyName]);
});
});

Expand Down
46 changes: 25 additions & 21 deletions js/mysql.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
/**
* define mysql connection object
* @implements sqldatabase interface
**/

var consts = require('./constants.js');
var date = require('./date.js');
var sqldatabase = require('./prototypes/sqldatabase.js');

var mysql = {

// define mysql object properties
connection : null, // holds the connection object to the mysql server or null if not connected
eventEntryCreated : false, // flag indicating whether a mysql entry has been added (`events`) for current event
hasData : false, // flag indicating whether mysql database table contains any data
isBusy : false, // flag indicating whether a mysql query is currently ongoing
isConnected : false, // flag indicating whether a connection to mysql server has been established
library : require('mysql'), // define and import node.js package

/**
* @private method
* creates and establishes a connection to
* the mysql server
*
Expand All @@ -24,7 +20,7 @@ var mysql = {
* @param password = {String} specifying database account password
* @param database = {String} specifying the name of database to connect to
**/
connect : function(host, user, password, database) {
_connect : function(host, user, password, database) {
// check to see if previous connection exists, or @params for new connection are passed
if(!mysql.isConnected || (host && user && password)) {
// create connection blueprint
Expand Down Expand Up @@ -59,6 +55,16 @@ var mysql = {
}
},

/**
* performs a query using the underlying database connection
*
* @param sqlQuery = {String} specifying SQL query to execute
* @param callback = {Function} to call after operation has completed successfully
**/
query : function(sqlQuery, callback) {
mysql._connect().query(sqlQuery, callback);
},

/**
* deletes entries from table where whereLogic applies
*
Expand All @@ -71,8 +77,7 @@ var mysql = {
deleteFrom : function(mysqlTableName, whereLogic, callback) {
if(whereLogic) {
// perform query only if whereLogic has been passed
mysql.connect()
.query('DELETE FROM ' + mysqlTableName + ' WHERE ' + (whereLogic || '1 = 1'), callback);
mysql.query('DELETE FROM ' + mysqlTableName + ' WHERE ' + (whereLogic || '1 = 1'), callback);
} else {
// fail and exit function with error
callback.call(this, 'ERR: (mysqldatabasedeletionerror): no \'WHERE\' condition applies for selected logic.');
Expand Down Expand Up @@ -107,8 +112,7 @@ var mysql = {
});

// join arrays of column names and values to add by commas and add them to our query string
mysql.connect()
.query('INSERT INTO ' + mysqlTableName + '(' + (databaseColumns.join(',')) + ') VALUES (' + valuesToAdd.join(',') + ')',
mysql.query('INSERT INTO ' + mysqlTableName + '(' + (databaseColumns.join(',')) + ') VALUES (' + valuesToAdd.join(',') + ')',
// call user's callback function
function(err) {
// get err param if any and pass it to callback before calling
Expand All @@ -128,8 +132,7 @@ var mysql = {
**/
selectFrom : function(mysqlTableName, databaseColumns, whereLogic, callback) {
// perform query
mysql.connect()
.query('SELECT ' + databaseColumns.join(',') + ' FROM ' + mysqlTableName + ' WHERE ' + (whereLogic || '1 = 1'), callback);
mysql.query('SELECT ' + databaseColumns.join(',') + ' FROM ' + mysqlTableName + ' WHERE ' + (whereLogic || '1 = 1'), callback);
},

/**
Expand All @@ -155,15 +158,16 @@ var mysql = {
keyValuePairs = keyValuePairs.substring(1);

// join arrays of column names and values to add by commas and add them to our query string
mysql.connect()
.query('UPDATE ' + mysqlTableName + ' SET ' + keyValuePairs + ' WHERE ' + (whereLogic || '1 = 1'),
// call user's callback function
function(err) {
// get err param if any and pass it to callback before calling and exit
return callback.call(mysql, err);
});
mysql.query('UPDATE ' + mysqlTableName + ' SET ' + keyValuePairs + ' WHERE ' + (whereLogic || '1 = 1'),
// call user's callback function
function(err) {
// get err param if any and pass it to callback before calling and exit
return callback.call(mysql, err);
}
);
}

};

mysql.__proto__ = sqldatabase;
module.exports = mysql;
4 changes: 2 additions & 2 deletions js/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ var output = {
}

// add to `attendance` table
mysql.connect().query(
mysql.query(

"INSERT INTO `attendance` (`student_id`, `event_id`, `is_new`)" +
"VALUES" +
Expand Down Expand Up @@ -175,7 +175,7 @@ var output = {
entry.addedToCurrentMysqlEventTable = true;

// add to `attendance` table
mysql.connect().query(
mysql.query(

"INSERT INTO `attendance` (`student_id`, `event_id`, `is_new`)" +
"VALUES" +
Expand Down
14 changes: 14 additions & 0 deletions js/prototypes/baseproto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var baseproto = {
_protoName: 'baseproto',

isPrototypeOf: function(obj) {
return obj._protoName && this._protoName === obj._protoName;
},

getPrototypeOf: function() {
return this._protoName;
}
}


module.exports = baseproto;
89 changes: 89 additions & 0 deletions js/prototypes/sqldatabase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* define sqldatabase prototype
**/

var baseproto = require('./baseproto.js');

var sqldatabase = {
_protoName : 'sqldatabase',

// define sqldatabase object properties
connection : null, // holds the connection object to the SQL server or null if not connected
eventEntryCreated : false, // flag indicating whether a SQL entry has been added (`events`) for current event
hasData : false, // flag indicating whether SQL database table contains any data
isBusy : false, // flag indicating whether a SQL query is currently ongoing
isConnected : false, // flag indicating whether a connection to SQL server has been established

/**
* performs a query using the underlying database connection
*
* @param sqlQuery = {String} specifying SQL query to execute
* @param callback = {Function} to call after operation has completed successfully
**/
query : function(sqlQuery, callback) {
throw "unimplemented query method";
},

/**
* deletes entries from table where whereLogic applies
*
* @param sqlTableName = {Object} entry object from local 'database' object
* @param whereLogic = {String} containing equality to use to target the selection of a specific row
* @param callback = {Function} to call after operation has completed successfully
*
* for data protection, if @param whereLogic is 'null', nothing should be deleted / returned
**/
deleteFrom : function(sqlTableName, whereLogic, callback) {
throw "unimplemented deleteFrom method";
},

/**
* safely closes the SQL server connection
**/
end : function() {
throw "unimplemented end method";
},

/**
* inserts new entry to SQL database
*
* @param sqlTableName = {Object} entry object from local 'database' object
* @param databaseColumns = {Array} containing names of SQL table columns to insert values into
* @param valuesToAdd = {Array} containing entry values to add
* @param callback = {Function} to call after operation has completed successfully
**/
insertInto : function(sqlTableName, databaseColumns, valuesToAdd, callback) {
throw "unimplemented insertInto method";
},

/**
* selects entries from table, using passed logic
*
* @param sqlTableName = {Object} entry object from local 'database' object
* @param databaseColumns = {Array} containing names of SQL table columns to select
* @param whereLogic = {String} containing equality to use to target the selection of a specific row
* @param callback = {Function} to call after operation has completed successfully
*
* if @param whereLogic is 'null', all rows are selected and returned
**/
selectFrom : function(sqlTableName, databaseColumns, whereLogic, callback) {
throw "unimplemented selectFrom method";
},

/**
* updates entry in database table, using passed logic
*
* @param sqlTableName = {Object} entry object from local 'database' object
* @param databaseColumns = {Array} containing names of SQL table columns to update values
* @param updatedValues = {Array} containing updated entry values
* @param whereLogic = {String} containing equality to use to target the update of a specific row
* @param callback = {Function} to call after operation has completed successfully
**/
update : function(sqlTableName, databaseColumns, updatedValues, whereLogic, callback) {
throw "unimplemented update method";
}

};

sqldatabase.__proto__ = baseproto;
module.exports = sqldatabase;
2 changes: 1 addition & 1 deletion js/scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ var _scanner = {
syncAttendanceTableWithAPIServer: function(mysql, api, callback) {

// get dataset containing hash of latest attendance result
mysql.connect().query('SELECT MD5(concat(student_id, event_id, is_new, COUNT(*))) AS md5, COUNT(*) AS total FROM `attendance` ORDER BY student_id DESC', function(err, rows) {
mysql.query('SELECT MD5(concat(student_id, event_id, is_new, COUNT(*))) AS md5, COUNT(*) AS total FROM `attendance` ORDER BY student_id DESC', function(err, rows) {

if(err) {
return console.log('API', 'SYNC', 'ERR', err);
Expand Down
2 changes: 1 addition & 1 deletion js/tests/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if(!USE_CLOUD_DB) {

}

mysql.connect(function(err) {
mysql._connect(function(err) {

if(err) {
return console.log('MYSQL', 'ERR', err);
Expand Down

0 comments on commit bc597b2

Please sign in to comment.