UNPKG

miridoo-js-orm

Version:
337 lines (304 loc) 12.1 kB
var Table = require(__dirname+'/../sgbd/Table'); var ShemaBuilder = require(__dirname+'/ShemaBuilder'); var QueryBuilder = require(__dirname+'/QueryBuilder'); function getOrmType(type){ if(type == 'varchar') return 'string'; if(type == 'enum') return 'choice'; return type; } function fromEnum(str){ var r = str.split(',').map(function(value){ if((value[0] == '\'' && value[value.length-1] == '\'') || (value[0] == '"' && value[value.length-1] == '"')) value = value.substr(1, value.length-2); return value; }); return r; } var MySqlTable = function($name, $connection){ Table.apply(this, arguments); this.$primaryColumn = 'id'; this.$relations = []; this.$proxy = { $original : [], $yield : 0, $set : {} }; var self = this; $name = ($name || '').toLowerCase(); //contain all query who must be execute this.queue = []; this.$QueryBuilder = function(){ var r = new QueryBuilder($name, $name); r.$builder = new MySqlTable($name, $connection); return r; }; this.alter = function(schema){ var rschema = {}; for(var i in schema) rschema[i] = (typeof schema[i] == 'function')?schema[i]().get():schema[i].get(); return new Promise(function(resolve, reject){ self.schema().then(function(columns){ var make = []; var fromTable = Object.keys(columns); for(var col in fromTable){ if(!rschema[fromTable[col]]){ make.push('DROP COLUMN '+fromTable[col]); } } for(var col in rschema){ if(columns[col]){ if( (rschema[col].type != columns[col].type) || (rschema[col].default != columns[col].default && rschema[col].default != undefined) || (rschema[col].null != columns[col].null && rschema[col].null != undefined) || (rschema[col].size != columns[col].size && rschema[col].type != 'enum') || (rschema[col].values != columns[col].values && rschema[col].type == 'enum') ) make.push('CHANGE '+col+' '+col+' '+ShemaBuilder(schema[col], col)); }else make.push('ADD COLUMN '+col+' '+ShemaBuilder(schema[col], col)); } var i = 0; var fn = function(){ if(i >= make.length) return resolve() self.$sql.query('ALTER TABLE '+$name+' '+make[i], {}, function(rsp, err){ if(err) throw new Error(err); fn(i++); }); }; if(make.length > 0) fn(); else resolve(); //build the query }).catch(reject); }); }; this.create = function(schema, autoUpdate){ return new Promise(function(resolve, reject){ self.$sql.tables().then(function(r){ if(r.indexOf($name) != -1){ if(autoUpdate) self.alter(schema).then(resolve).catch(reject); else resolve(); } else{ var query = []; for(var i in schema) query.push(i+' '+ShemaBuilder(schema[i], i)); $connection.query('CREATE TABLE IF NOT EXISTS '+$name+'('+query.join(',')+')', function(res, err){ if(err) reject(err); else resolve(res); }); } }).catch(reject); }); }; this.drop = function(){ return new Promise(function(resolve, reject){ $connection.query('DROP TABLE IF EXISTS '+$name, function(res, err){ if(err) reject(err); else resolve(res); }); }); }; this.rename = function(newname){ return new Promise(function(resolve, reject){ $connection.query('RENAME TABLE '+$name+' TO '+newname, function(res, err){ if(err) reject(err); else{ $name = newname; resolve(res); } }); }); }; this.clone = function(newtable, data){ var sql = 'CREATE TABLE '+newtable+' LIKE '+$name; if(data === true) sql = 'CREATE TABLE '+newtable+' AS SELECT * FROM '+$name; return new Promise(function(resolve, reject){ $connection.query(sql, function(res, err){ if(err) reject(err); else{ resolve(new MySqlTable(newtable)); } }); }); }; this.delete = function(where, params, uquer){ return new Promise(function(resolve, reject){ var query = ''; if(typeof where == 'function'){ var x = new QueryBuilder($name, $name); where(x); query = x.toString(); params = x.params; }else if(!uquer){ query = 'DELETE FROM '+$name+' '+(where?'WHERE '+where:''); } $connection.query(query, params || {}, function(res, err){ if(err) reject(err); else{ resolve(res); } }); }); }; this.reset = function(){ return new Promise(function(resolve, reject){ $connection.query('TRUNCATE '+$name, function(res, err){ if(err) reject(err); else{ resolve(res); } }); }); }; this.all = function(query, params){ return this.get(query, params); }; this.get = function(query, params, uquer){ return new Promise(function(resolve, reject){ query = (self.$where?'WHERE '+self.$where:'')+self.$query+(query || ''); if(typeof query == 'function'){ var x = new QueryBuilder($name, $name); query(x); query = x.toString(); params = x.params; }else if(!uquer){ query = 'SELECT '+self.only()+' FROM '+$name+' '+query; } $connection.query(query, params || {}, function(res, err){ if(err) reject(err); else{ for(var i in res){ for(var j in self.$relationsUes){ self.$relationsUes[j].push(res[i][j]); } } self.$hrefBuilder(res, function(){ self.$cleanRelation(); self.$proxy.$original = res; resolve(res); }); } }); }); }; this.schema = function(){ return new Promise(function(resolve, reject){ $connection.query('DESCRIBE '+$name, function(res, err){ if(err) reject(err); else{ var r = {}, x = null, type = ''; for(var i in res){ x = res[i]; type = {type : '', size : 0}; x.Type.replace(/([a-z]+)\(([\s\S]+)\)/ig, function(all, t, s){ type = {type : t, size : s}; }); if(!type.type) type.type = x.Type; r[x.Field] = { type : getOrmType(type.type), size : parseInt((type.type != 'enum')?type.size:''), value : (type.type == 'enum')?fromEnum(type.size):'', unsigned : (new RegExp(/unsigned/)).test(x.Type), null : (x.Null == 'YES'), default : x.Default, pk : (x.Key == 'PRI'), increment : (r.Extra == 'auto_increment') }; } resolve(r); } }); }); }; this.save = function(json){ json = json || {}; var keys = Object.keys(json); return new Promise(function(resolve, reject){ $connection.query('INSERT INTO '+$name+'('+keys.join(',')+') VALUES (:'+keys.join(', :')+')', json , function(res, err){ if(err) reject(err); else{ resolve(res); } }); }); }; this.msave = function(){ var values = [], valuesData = {}; var args = Array.from(arguments); var keys = Object.keys(args[0]); args.map(function(obj, index){ var r = {}, k = '', lkeys = []; for(var key in obj){ k = key+'_'+index; lkeys.push(k); valuesData[k] = obj[key]; } values.push('(:'+lkeys.join(', :')+')'); return obj; }); return new Promise(function(resolve, reject){ $connection.query('INSERT INTO '+$name+'('+keys.join(',')+') VALUES '+values.join(','), valuesData , function(res, err){ if(err) reject(err); else{ resolve(res); } }); }); }; this.link = function(name, relation){ //name is the var name in the result object self.$relationsUes[relation.use] = []; this.$relations.push({ auto : relation.auto, name : name, call : function(next){ relation.only = relation.only || []; if(relation.only.length > 0 && relation.only[0] != '*' && relation.only.indexOf(relation.column) == -1) relation.only.push(relation.column); $connection.query('SELECT '+((relation.only && relation.only.length > 0)?relation.only.join(','):'*')+' FROM '+relation.to+' WHERE '+relation.column+' IN ('+(self.$relationsUes[relation.use].join(','))+')', function(res, err){ if(err) next(err); else{ next(name, res, relation); } }); } }); return this; }; this.column = function(){ return new Column($name, $connection); }; /* * simple query maker */ this.first = function(nb){ nb = nb || 1; this.$query += ' ORDER BY '+self.$primaryColumn+' ASC LIMIT 0, '+nb; return new Promise(function(resolve, reject){ self.get().then(function(r){ resolve((r.length > 0 && nb == 1)?r[0]:r); }).catch(reject) }); }; this.last = function(nb){ nb = nb || 1; this.$query += ' ORDER BY '+self.$primaryColumn+' DESC LIMIT 0, '+nb; return new Promise(function(resolve, reject){ self.get().then(function(r){ resolve((r.length > 0 && nb == 1)?r[0]:r); }).catch(reject) }); }; this.each = function(calback){ this.$proxy.$original.forEach(calback); return this; }; }; module.exports = MySqlTable;