mysql-restful
Version:
MySQL RESTful API server
582 lines (569 loc) • 20.6 kB
JavaScript
var dbs = require('./dbcon.js');
var utils = require('./fgen.js');
var rpda = require('./rpdafter.js');
var rpdb = require('./rpdbefore.js');
module.exports = {
runsql: function(req,rdbcb){
var rcfg = process.rapidcfg;
var query = req.query;
//console.log(rcfg);
function seterror(error_name,desc,has_required){
err = {error:error_name,
description:desc,
method:'GET',
action:'rpdquery',
notes:'run a SQL statement stored serverside by name and other required parameters'}
if (has_required == 1){
err.required = ['csql', 'limit', 'offset'];
err.csql = 'sql statement name';
err.limit = 'number of records to be returned';
err.offset = 'start record number from result set'};
return err
};
function qccb(error,message){
response = ''
if (message){
response = {}
response[query.csql]=message
}
client.end();
rdbcb(error,response);
};
if (!query.csql) {return rdbcb(seterror('missing parameter','csql - is required',1),'')};
if (!query.limit) {return rdbcb(seterror('missing parameter','limit - is required',1),'')};
if (!query.offset){return rdbcb(seterror('missing parameter','offset - is required',1),'')};
if (!rcfg.mdb.sqls[query.csql]) {return rdbcb(seterror('Query:'+query.csql,'Query does not exist!',1),'')};
var sqlstat = rcfg.mdb.sqls[query.csql].sqlstat;
var arr = []
if (sqlstat.search("&")>-1){
arr = sqlstat.match(/(^|\s)&(\w+)/g).map(function(v){return v.trim().substring(1);});
arr = arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});
}
var qp = [];
arr.forEach(function(item){
if (!query[item]) {return rdbcb(seterror('missing parameter',item+' - parameter is required',0),'')};
sqlstat = sqlstat.split('&'+item).join('?')
});
function dbconncb (error,message){
if (error){
client.end()
return rdbcb({error:'rapid database connection error/ '+dbcon.rapiddb},"");
}else{
arr.forEach(function(item){
qp.push(query[item]);
});
//console.log(qp);
dbs.getsql(client,sqlstat,qp,query.limit,query.offset,qccb);
};
};
var dbcon = {}
var dbname = ""
if (rcfg.mdb.databases.number == 1){
dbname = rcfg.mdb.databases.names[0];
} else {
if (rcfg.mdb.sqls[query.csql]){
dbname = rcfg.mdb.sqls[query.csql].database;
} else {
err = seterror('invalid parameter/ csql',query.csql +' SELECT STAT. - does not exist or is not in use',0);
return rdbcb(err,'')};
};
rcfg.distributeddata === 0
if (rcfg.distributeddata === 0 || rcfg.mdb.databases[dbname].distributeddata === 0){
dbcon = rcfg.mdb.databases[dbname];
dbcon.rapiddb = dbname
} else {
var dist_db = dbs.getdbdist(dbname,req.token.user);
if (rcfg.mdb.connections[dist_db]){
dbcon = rcfg.mdb.connections[dist_db];
dbcon.rapiddb = dist_db;
} else {
err = seterror('distributed database setting error',dist_db +' database - does not exist',0);
err.notes = 'distributed database settings need additional settings';
return rdbcb(err,'');
};
};
//var client = dbs.getclient(dbcon);
//client.connect(dbconncb)
// implement before
var bfunc = query.csql+'RunSql'
var client = {}
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.query,start);
} else { start ()}
}
function start(err){
if (err) {return rdbcb({error:err},'')};
client = dbs.getclient(dbcon);
client.connect(dbconncb)
}
//
},
find: function(req,table,primary_key,table_structure,dbcon,rediscon,rdbcb){
function findrecord(){
function qccb(error,message){
client.end()
delete client
if (error){
console.log({error:'rapid - find error',errmsg:error});
rdbcb({error:'rapid - find error',errmsg:error},'');
}else{
// implement after - code
function last(err){
if (err){
rdbcb({error:table+' after-error',errmsg:err});
} else {if (!message[0]){rdbcb('',{})}else{
rdbcb('',message)}};
};
var afunc = table+'Find'
if (typeof rpda[afunc] == 'function') {
rpda[afunc](req,message.rows,last);
} else {last()}
}
}
var key_value = req.query[primary_key]
var qval = []
if (primary_key){
var sqlstat = "select * from "+table+" where " + primary_key +" = ?";
qval.push(key_value)
} else {
var sqlstat = "select * from "+table+" limit 1000"
}
if (table_structure.deleted){
sqlstat = sqlstat + ' and deleted = false';
}
dbs.runquery(client,sqlstat,qval,0,qccb);
}
function dbconncb (error,message){
if (error){
client.end()
delete client
console.log({error:'rapid database connection error/'+dbcon.rapiddb});
return rdbcb({error:'rapid database connection error/ '+dbcon.rapiddb},"");
}else{
findrecord();
};
};
// implement before
var bfunc = table+'Find'
var client = {}
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.query,start);
} else { start ()}
}
function start(err){
if (err) {rdbcb({error:err},'')};
client = dbs.getclient(dbcon);
client.connect(dbconncb)
}
},
create: function(req,table,primary_key,table_structure,dbcon,rediscon,rdbcb){
function createrecord(){
function qccb(error,message){
//console.log('client end final');
client_PGI.end();
delete client_PGI;
if (error){
console.log({error:'rapid - create error',errmsg:error});
rdbcb({error:'rapid - create error',errmsg:error},'');
}else{
function last(err){
if (err){rdbcb({error:table+' after-error',errmsg:err});
} else {if (!message.rows[0]){rdbcb('',{})}else{
if (message.msg.insertId>0){
message.rows[0][primary_key]=message.msg.insertId;
}
rdbcb('',message.rows[0])}};
};
var afunc = table+'Create'
if (typeof rpda[afunc] == 'function') {
rpda[afunc](req,message.rows[0],last);
} else {last()}
}
}
var key_value = req.body[primary_key]
if (key_value == 'rpderror'){
if (client_PGI){
client_PGI.end();
delete client_PGI;
};
return rdbcb({error:'Insert request error',rapidinsertfields_error:'invalid primary key'},'')};
if (Object.keys(req.body).length===0){
if (client_PGI){
client_PGI.end();
delete client_PGI;
};
return rdbcb({error:'Insert request error',rapidinsertfields_error:'invalid request body/data'},'')};
var ins_fields = dbs.get_fields(table_structure,primary_key,req.body,1,table)
if(!ins_fields.rapidinsertfields_error){
dbs.insert(client_PGI,table,ins_fields,0,qccb);
} else {
if (client_PGI){
client_PGI.end();
delete client_PGI;
};
rdbcb(ins_fields.rapidinsertfields_error,'')};
}
function dbconncb (error,message){
if (error){
client_PGI.end()
console.log({error:'rapid database connection error/'+dbcon.rapiddb});
return rdbcb({error:'rapid database connection error/ '+dbcon.rapiddb},"");
}else{
createrecord();
};
};
// implement before
var bfunc = table+'Create'
var client_PGI = {}
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.body,start);
} else { start ()}
}
function start(err){
if (err) {rdbcb({error:err},'')};
client_PGI = dbs.getclient(dbcon);
client_PGI.connect(dbconncb)
}
},
update: function(req,table,primary_key,table_structure,dbcon,rediscon,rdbcb){
function updaterecord(){
function qccb(error,message){
client_PGI.end()
if (error){
console.log({error:'rapid - update error',errmsg:error});
rdbcb({error:'rapid - update error',errmsg:error},'');
}else{
function last(err){
if (err){rdbcb({error:table+' after-error',errmsg:err});
} else {if (!message.rows[0]){rdbcb('',{})}else{
rdbcb('',message.rows[0])}};
};
var afunc = table+'Update'
if (typeof rpda[afunc] == 'function') {
rpda[afunc](req,message.rows[0],last);
} else {last()}
}
}
var key_value = req.query[primary_key]
var upd_fields = dbs.get_fields(table_structure,primary_key,req.body,0,table)
if(!upd_fields.rapidinsertfields_error){
var key_value = upd_fields[primary_key];
delete upd_fields[primary_key]
dbs.update(client_PGI,table,primary_key,key_value,upd_fields,0,qccb);
} else {rdbcb(upd_fields.rapidinsertfields_error,'')};
}
function dbconncb (error,message){
if (error){
client_PGI.end()
console.log({error:'rapid database connection error/'+dbcon.rapiddb});
return rdbcb({error:'rapid database connection error/ '+dbcon.rapiddb},"");
}else{
updaterecord();
};
};
// implement before
var bfunc = table+'Update'
var client_PGI = {}
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.body,start);
} else { start ()}
}
function start(err){
if (err) {rdbcb({error:err},'')};
client_PGI = dbs.getclient(dbcon);
client_PGI.connect(dbconncb)
}
},
destroy: function(req,table,primary_key,table_structure,dbcon,key_value,rediscon,rdbcb){
function deleterecord(){
function qccb(error,message){
client.end()
if (error){
rdbcb({error:'rapid - delete error',errmsg:error},'');
}else{
var deletemessage = {table:table,
primary_key:primary_key,
key_value:key_value,
action:'DELETE',
success:true
}
if (message.affectedRows==0){
deletemessage.success = false
deletemessage.error = 'key not found!'
}
function last(err){
if (err){rdbcb({error:table+' after-error',errmsg:err});
} else {rdbcb('',deletemessage)};
};
var afunc = table+'Delete'
if (typeof rpda[afunc] == 'function') {
rpda[afunc](req,deletemessage,last);
} else {last()}
}
}
if (!table_structure.deleted){
var sqlstat = "delete from "+table+" where " + primary_key +" = ?";
} else {
var sqlstat = "update "+table+" set deleted = true where " + primary_key +" = ?";
};
var qval = []
qval.push(key_value)
dbs.runquery(client,sqlstat,qval,0,qccb);
}
function dbconncb (error,message){
if (error){
client.end()
console.log({error:'rapid database connection error/'+dbcon.rapiddb});
return rdbcb({error:'rapid database connection error/ '+dbcon.rapiddb},"");
}else{
deleterecord();
};
};
// implement before
var bfunc = table+'Delete'
var client = {}
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.query,start);
} else { start ()}
}
function start(err){
if (err) {rdbcb({error:err},'')};
client = dbs.getclient(dbcon);
client.connect(dbconncb)
}
},
dataset: function(req,dstype,rdbcb){
function dscallback(err,msg){
if (err){
rdbcb(err,'');
}else {
rdbcb('',msg)};
};
function closeconn(error,message){
if (Object.keys(open_connections).length>0){;
connexion_name = Object.keys(open_connections)[0]
if (!dstype){
open_connections[connexion_name].end()
delete open_connections[connexion_name];
closeconn(error,message);
} else {
if (error){
var transact = 'rollback'
} else {var transact = 'commit'};
function conncallback (cerror,cmessage){
open_connections[connexion_name].end()
delete open_connections[connexion_name];
if (cerror){
return closeconn({error:error,connection:connexion_name,action:transact},'')
} else {closeconn(error,message)};
};
dbs.transaction(open_connections[connexion_name],transact,conncallback);
//
};
} else { return dscallback(error,message)};
};
var connexion_name = ""
var record_action = 0
var current_table_position = 0
var open_connections = {}
var res_message = {}
var rcfg = process.rapidcfg;
if (!req.body.data){return dscallback({error:"Your JSON request should contain an object called:data"},'')};
var req_data = req.body.data
if (req_data.constructor !== Object){return dscallback({error:"Json request: data - is not an Object"},'')};
var transaction_tables = Object.keys(req_data)
if (transaction_tables.length == 0){return dscallback({error:"Json request: data - has no tables objects"},'')};
function next_table (err,message){
if(err){
return closeconn(err,'');
} else {
current_table_position = current_table_position + 1
if (transaction_tables[current_table_position] == undefined){
return closeconn('',{data:res_message})
} else {table_cu(req,transaction_tables[current_table_position],next_table)}
}
};
function table_cu(req,table_x,next){
var primary_key = rcfg.mdb.tables.keys[table_x]
var table_structure = rcfg.mdb.tables.structures[table_x]
function table_set_request (req,table_x,connobj,connname,next){
function tnext_record(err,message){
if (!res_message[table_x]){res_message[table_x] = []};
var rec_result = req.body.data[table_x][curent_record];
delete rec_result.deleted
delete rec_result.alta
delete rec_result.createdAt
delete rec_result.updatedAt
if (err) {
if (!res_message.errors){res_message.errors = []};
errmsg = {connexion:connexion_name,
database:rcfg.mdb.tables.db[table_x],
table:table_x,
error:err,
record:curent_record,
request:req.body.data[table_x][curent_record]}
res_message.errors.push(errmsg);
rec_result.rpdstatus = 9;
if (dstype) {return next({error:res_message.errors},'')};
} else {
if (record_action != -1) {rec_result.rpdstatus = 0};
};
if (record_action != -1) {
res_message[table_x].push(rec_result);
} else {
if (!res_message.deleted){res_message.deleted = {}};
if (!res_message.deleted[table_x]){res_message.deleted[table_x] = []};
res_message.deleted[table_x].push(rec_result);
};
curent_record = curent_record + 1;
return table_record(table_x,connobj,tnext_record)
}
function table_record(table_x,connobj,rnext){
function querycb(error,message){
if (error){return rnext(error,'');
} else {return rnext('',message)} ;
}
if (req.body.data[table_x].length < (curent_record+1)){
next('','message');
} else {
var rec_status = req.body.data[table_x][curent_record].rpdstatus
record_action = rec_status
if (rec_status == undefined){return rnext({error:'rpdstatus - field not found'},'')};
//console.log(rec_status);
switch (rec_status) {
case 1:
function tinsert_record(){
//console.log("T insert",req.body.data[table_x][curent_record])
var key_value = req.body.data[table_x][curent_record][primary_key];
var c_record = req.body.data[table_x][curent_record];
delete c_record.rpdstatus;
var ins_fields = dbs.get_fields(table_structure,primary_key,c_record,1,table_x);
if(key_value){ins_fields[primary_key] = key_value};
if(!ins_fields.rapidinsertfields_error){
dbs.insert(connobj,table_x,ins_fields,0,rnext);
} else {rnext(ins_fields.rapidinsertfields_error,'')};
}
var bfunc = table_x+'Create'
//console.log(bfunc);
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb1);
} else {checkrb1()}
function checkrb1(){
//console.log('checkrb1');
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.body.data[table_x][curent_record],tinsert_record);
} else { tinsert_record()}
}
break;
case 2:
var key_value = req.body.data[table_x][curent_record][primary_key]
if (key_value==undefined){return rnext({error:'invalid primary key ' + primary_key},'')};
function tupdate_record(){
var c_record = req.body.data[table_x][curent_record]
delete c_record.rpdstatus
var upd_fields = dbs.get_fields(table_structure,primary_key,c_record,0,table_x)
if(!upd_fields.rapidinsertfields_error){
var key_value = req.body.data[table_x][curent_record][primary_key]
dbs.update(connobj,table_x,primary_key,key_value,upd_fields,0,rnext);
} else {rnext(upd_fields.rapidinsertfields_error,'')};
}
var bfunc = table_x+'Update'
if (typeof rpdb.checkAll == 'function'){
rpdb.checkAll(req,req.query,checkrb);
} else {checkrb()}
function checkrb(){
if (typeof rpdb[bfunc] == 'function') {
rpdb[bfunc](req,req.body.data[table_x][curent_record],tupdate_record);
} else { tupdate_record()}
}
break;
case -1:
var key_value = req.body.data[table_x][curent_record][primary_key]
if (key_value==undefined){return rnext({error:'invalid primary key ' + primary_key},'')};
if (!table_structure.deleted){
var sqlstat = "delete from "+table_x+" where " + primary_key +" = ?";
} else {
var sqlstat = "update "+table_x+" set deleted = true where " + primary_key +" = ?";
};
var qval = []
qval.push(key_value)
dbs.runquery(connobj,sqlstat,qval,0,rnext);
break;
default: rnext({error:'rpdstatus'+rec_status+'not implemented!'},'');
};
}
};
var table_response = []
var curent_record = 0
table_record(table_x,connobj,tnext_record)
};
function dbconncb (error,message){
if (error){
open_connections[connexion_name].end()
console.log({error:'rapid database connection error/'+new_connexion_name});
return closeconn({error:'rapid database connection error/ '+new_connexion_name},"");
}else{
connexion_name = new_connexion_name
function conncallback (error,message){
if (error){
return closeconn({error:error,connection:connexion_name},'')
} else {table_set_request(req,table_x,open_connections[connexion_name], connexion_name, next_table)};
};
if (dstype) {
console.log('transaction mode for' + connexion_name)
dbs.transaction(open_connections[connexion_name],'begin transaction',conncallback);
} else {
table_set_request(req,table_x,open_connections[connexion_name],connexion_name,next_table)};
};
};
function set_connection(connname,conobj){
open_connections[connname] = dbs.getclient(conobj)
open_connections[connname].connect(dbconncb)
};
var dbcon = {};
var base_db = rcfg.mdb.tables.db[table_x];
if (rcfg.distributeddata == 1 && rcfg.mdb.databases[base_db].distributeddata==1){
var dist_db = dbs.getdbdist(base_db,req.token.user);
dbcon = rcfg.mdb.connections[dist_db];
dbcon.rapiddb = dist_db
} else {dbcon = rcfg.mdb.databases[base_db];dbcon.rapiddb = base_db};
var new_connexion_name = dbcon.rapiddb
if (open_connections[new_connexion_name]){
if (new_connexion_name != connexion_name){
open_connections[new_connexion_name].connect(dbconncb);
} else {table_set_request(req,table_x,open_connections[connexion_name],connexion_name,next_table)};
} else {set_connection(new_connexion_name,dbcon)};
};
if (!req.body.data){return dscallback({error:"DATA object not found!"},'')}
for (table_x in req.body.data){
if (utils.findin(rcfg.mdb.tables.names,table_x)){
var table_xtype = req.body.data[table_x].constructor
if (table_xtype !== Array){return dscallback({error:'Table:'+table_x + ' - should be represented as an Array in request JSON!',table:table_x,requestpart:req.body.data[table_x]},'')};
}else {return dscallback({error:'Table:'+table_x + ' - not found in databases!'},'')};
if (req.body.data[table_x].length == 0){return dscallback({error:'Table:'+table_x + ' - has no records',table:table_x,requestpart:req.body.data[table_x]},'')};
}
table_cu(req,transaction_tables[0],next_table)
}
}