FileDB前两版是基于Java和Servlet容器的,且只能现实简单的Key/Value数据存取。
V3.0版使用了Javascript语言重写代码,并进行了重新设计,运行环境改为了Node.js。
V3.0版功能有所增强,支持建任意多个表,前端还支持简单的SQL语句查询。
使用中建议配合JQuery库一起使用,想test.html中的一样。
数据库相关代码在附件中,感兴趣的同学可以下载下来测试下,也欢迎与我讨论。
数据库代码:
// This class parses the sql statement alike.
// Examples : create table abc; insert into abc(field, field2, field3) values('xxx', 123, 234);
// update abc set field = 'xxx', field2 = 123 where [id] = 123;
// select * from abc where [field] = 'xxx' and ([field2] >= 123 or [field3] < 234) order by field desc limit 0, 20
function Query(sql) {
this.sql = sql.toLowerCase().replace(/\'/g, '"').replace(/;/g, '');
}
Query.prototype.exec = function() {
if (this.sql.indexOf('create') != -1) {
return JSON.stringify(this.create());
} else if (this.sql.indexOf('insert') != -1) {
return JSON.stringify(this.insert());
} else if (this.sql.indexOf('update') != -1) {
return JSON.stringify(this.update());
} else if (this.sql.indexOf('select') != -1) {
return JSON.stringify(this.select());
} else if (this.sql.indexOf('show') != -1) {
var str = '{';
for (var tab in App.db.data) {
str += '"' + tab + '":' + App.db.data[tab].data.length + ',';
}
str = (str.length > 1 ? str.slice(0, -1) : str) + '}';
return str;
} else {
return 'false';
}
};
Query.prototype.create = function() {
var arr = this.sql.match(/table\s+(\w+)/); // regex is : table \s+ (\w+)
if (!arr || arr.length != 2) return false;
if (App.db.get(arr[1])) return false; // already exists.
var tab = new Table(arr[1]);
App.db.set(tab);
return true;
};
Query.prototype.insert = function() {
// regex is : (\w+) \( ([\w\s,]+) \) \s+ values \( ([\w\s,\"]+) \)
var arr = this.sql.match(/(\w+)\s*\(([\w\s,]+)\)\s+values\(([\w\s,\"]+)\)/);
if (!arr || arr.length != 4) return false;
var tab = new Table('rs').init(App.db.get(arr[1]));
var fields = arr[2].split(/\s*,\s*/);
var values = arr[3].split(/\s*,\s*/);
var str = '{';
for (var i = 0; i < fields.length; i++) {
str += '"' + fields[i] + '":' + values[i] + ',';
}
str = str.slice(0, -1) + '}';
var obj = JSON.parse(str);
tab.insert(obj);
Cache.change[arr[1]] = true; File.save();
return true;
};
Query.prototype.update = function() {
// regex is : update \s+ (\w+) \s+ set \s+ ([\w\s,=\'\"]+?) \s+ where \s+ ([\w\s=\[\]\'\"]+)
var arr = this.sql.match(/update\s+(\w+)\s+set\s+([\w\s,=\'\"]+?)\s+where\s+([\w\s=<>\[\]\'\"]+)/);
if (!arr || arr.length != 4) return false;
var tab = new Table('rs').init(App.db.get(arr[1]));
var sets = arr[2].split(/\s*,\s*/);
var rs = tab.select(arr[3]);
for (var i = rs.data.length - 1; i >= 0; i--) {
for (var j = sets.length - 1; j >= 0; j--) {
var kv = sets[j].split(/\s*=+\s*/);
tab.update(rs.data[i].id, kv[0], isNaN(kv[1]) ? kv[1] : parseInt(kv[1]));
}
}
Cache.change[arr[1]] = true; File.save();
return true;
};
Query.prototype.select = function() {
var limit = this.sql.split(/\s+limit\s+/);
var order = limit[0].split(/\s+order\s+by\s+/);
var where = order[0].split(/\s+where\s+/);
var from = where[0].replace(/.+?from\s+/, '');
if (!from.match(/[0-9A-z_]+/)) return false;
if (Cache.change[from]) {
Cache.change[from] = false;
Cache.set(this.sql, null);
}
if (Cache.get(this.sql)) return Cache.get(this.sql);
var tab = new Table('rs').init(App.db.get(from));
tab = tab.select(where[1]).orderby(order[1]).limit(limit[1]);
Cache.set(this.sql, tab);
return tab;
};
exports.Query = Query;
function Cache() {
}
Cache.change = {}; // This property preserved the changed tables.
Cache.data = {}; // This property preserverd the cache data.
Cache.set = function(sql, tab) {
Cache.data[sql] = tab;
}
Cache.get = function(sql) {
return Cache.data[sql];
}
function DB(name) {
this.name = name;
this.data = {};
}
DB.prototype.set = function(tab) {
this.data[tab.name] = tab;
};
DB.prototype.get = function(name) {
return this.data[name];
};
function Table(name) {
this.name = name;
this.data = [];
}
Table.prototype.init = function(json) {
this.name = json.name;
this.data = json.data;
return this;
};
Table.prototype.insert = function(obj) {
obj.id = this.data.length;
this.data.push(obj);
};
Table.prototype.update = function(id, k, v) {
this.data[id][k] = v;
};
Table.prototype.select = function(con) {
var rs = new Table('rs');
if (!con) { rs.data = this.data; return rs; }
con = con.replace(/and/g, '&&').replace(/or/g, '||').replace(/([^<>!=])=\s*/g, '$1 == ');
con = con.replace(/\[\"?\'?(\w+)\"?\'?]/g, "this.data[i]['$1']"); // regex is : \[ \"? \'? (\w+) \"? \'? ]
for (var i = this.data.length - 1; i >= 0; i--) {
try {
if (eval(con)) rs.data.push(this.data[i]);
} catch(e) {
console.log(new Date() + ' : 查询条件解析错误:' + e);
}
}
return rs;
};
Table.prototype.orderby = function(str) {
var rs = new Table('rs');
rs.data = this.data;
if (!str || rs.data.length < 2) return rs;
var strs = str.split(/\s+/);
rs.data.sort(function(a, b) {
if (!isNaN(a[strs[0]]) && !isNaN(b[strs[0]])) {
if (strs[1] && strs[1].toLowerCase() == 'desc') {
return b[strs[0]] - a[strs[0]];
} else {
return a[strs[0]] - b[strs[0]];
}
} else {
if (strs[1] && strs[1].toLowerCase() == 'desc') {
return b[strs[0]].localeCompare(a[strs[0]]);
} else {
return a[strs[0]].localeCompare(b[strs[0]]);
}
}
});
return rs;
};
Table.prototype.limit = function(str) {
var rs = new Table('rs');
rs.data = this.data;
if (!str) return rs;
var strs = str.split(/,/); // separated by ","
if (!strs[1]) { strs[1] = strs[0]; strs[0] = 0; }
rs.data = this.data.slice(parseInt(strs[0]), parseInt(strs[0]) + parseInt(strs[1]));
return rs;
};
function File() {
}
File.read = function(str) {
File.time = new Date().getTime();
var file = new DB('db');
try {
var fs = require('fs');
var dbFile = fs.readFileSync('./' + str + '.txt', 'utf8');
var dbObj = JSON.parse(dbFile);
file.name = dbObj.name;
file.data = dbObj.data;
} catch (e) {
console.log(new Date() + ' : Error : File ' + str + '.txt is not successfully loaded!');
}
return file;
};
File.write = function(db) {
var data = JSON.stringify(db);
var fs = require('fs');
fs.writeFile('./' + db.name + '.txt', data, function (err) {
if (err) console.log(new Date() + ' : Error : ' + db.name + ' is not successfully saved!');
});
};
File.save = function() {
var curTime = new Date().getTime();
if (curTime - File.time > 10000) File.write(App.db); // If > 10s, then saved.
File.time = curTime;
};
function App() {
}
App.run = function() {
App.db = File.read('db'); // Defined a static property named 'db'.
};
exports.run = App.run;
数据库代码二:
var http = require('http');
var url = require('url');
var fs = require('fs');
var path = require('path');
var db = require('./filedb3.js');
var mime = {
"css": "text/css",
"gif": "image/gif",
"html": "text/html",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg+xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml"
};
var server = http.createServer(function(req, res) {
if (req.url !== '/favicon.ico') {
var urlObj = url.parse(req.url, true);
var pathname = urlObj.pathname;
if (pathname !== '/db.php') {
var realPath = pathname.slice(1);
path.exists(realPath, function (exists) {
if (!exists) {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('This request URL ' + pathname + ' was not found on this server.');
res.end();
} else {
fs.readFile(realPath, 'binary', function (err, file) {
if (err) {
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end(err);
} else {
var ext = path.extname(realPath);
ext = ext ? ext.slice(1) : 'unknown';
var contentType = mime[ext] || "text/plain";
res.writeHead(200, {'Content-Type': contentType});
res.write(file, "binary");
res.end();
}
});
}
});
} else {
var query = urlObj.query;
res.writeHead(200, {'Content-Type': 'application/json'});
var str = new db.Query(query.sql).exec();
res.write(query.callback + '(' + str + ')');
res.end();
}
} else {
//res.writeHead(404, {'Content-Type': 'text/plain'});
}
});
server.on('error', function(err) {
console.log(new Date() + ' : ' + err);
});
db.run();
server.listen(8080);
console.log(new Date() + ' : Server running at http://localhost:8080/');
测试代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>FileDB V3.0 测试页面</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('input[type="button"]').click(function() {
var sql = $.trim($(this).prev().val()); //alert(sql);
$.getJSON('http://localhost:8080/db.php?callback=?', {sql : sql}, function(data) {
alert(JSON.stringify(data));
//$('#result').html(JSON.stringify(data));
});
});
});
</script>
</head>
<body>
<h1>FileDB V3.0 测试页面</h1>
<form id="form1" name="form1" method="post" action="">
<p>
<input name="textfield" type="text" value="create table abc" />
<input type="button" name="Submit" value="执行语句" />
</p>
<p>
<input name="textfield2" type="text" value="insert into abc(name, age, job) values('yfs', 30, 'developer')" size="80" />
<input type="button" name="Submit2" value="执行语句" />
</p>
<p>
<input name="textfield3" type="text" value="insert into abc(name, age, job) values('why', 28, 'developer')" size="80" />
<input type="button" name="Submit3" value="执行语句" />
</p>
<p>
<input name="textfield4" type="text" value="insert into abc(name, age, job) values('liyan', 27, 'developer')" size="80" />
<input type="button" name="Submit4" value="执行语句" />
</p>
<p>
<input name="textfield5" type="text" value="insert into abc(name, age, job) values('lipeng', 31, 'designer')" size="80" />
<input type="button" name="Submit5" value="执行语句" />
</p>
<p>
<input name="textfield6" type="text" value="select * from abc where [job] = 'developer' and ([age] >= 30 or [age] < 28) order by age desc limit 0, 1" size="120" />
<input type="button" name="Submit6" value="执行语句" />
</p>
<p>
<input name="textfield7" type="text" value="update abc set name = 'xxx', age = 123 where [name] = 'yfs' or [age] <= 28" size="80" />
<input type="button" name="Submit7" value="执行语句" />
</p>
<p>
<input name="textfield8" type="text" value="show status" />
<input type="button" name="Submit8" value="执行语句" />
</p>
</form>
<p id="result"></p>
<p>PS :此NoSQL数据库仅支持基本的SQL语句关键字,不支持联合查询和SQL函数及in、like关键字。</p>
<p>PS2:where子句字段名需用中括号[]括起来,update语句必须带where子句。</p>
</body>
</html>
分享到:
相关推荐
标题中的“Node.js-样板:Next.js(React)ExpressRESTAPIMongoDBMongoose-Crudify”揭示了一个基于Node.js的Web开发项目模板,它整合了几个关键的技术栈,包括Next.js、Express、REST API、MongoDB以及Mongoose。...
Node.js 是一种基于 Chrome V8 引擎的 JavaScript 运行环境,它允许开发者在服务器端使用 JavaScript 进行编程,极大地拓宽了JavaScript的应用场景。本项目“Node.js-基于node.js Mongodb构建的后台系统”是利用Node...
Node.js是一个开放源代码、跨平台的JavaScript运行环境,用于在服务器端执行JavaScript代码。它基于Chrome V8引擎,使得开发者可以用JavaScript编写服务器端程序,打破了传统意义上前后端分离的界限。Node.js采用...
Node.js 使用 V8 引擎,这是 Google 为 Chrome 浏览器开发的高性能 JavaScript 和 WebAssembly 引擎。Node.js 的设计思想是事件驱动、非阻塞 I/O 模型,使其在数据密集型实时应用中表现出色。 标题中的“node.js...
【标题】:“Node.js-基于React.js的Node.js开源博客框架” 这个项目是一个结合了Node.js后端技术和React.js前端框架的开源博客平台。它利用了Node.js的非阻塞I/O模型和JavaScript的全栈能力,实现了高效、可扩展的...
1. **Node.js**:Node.js基于Chrome V8引擎,用JavaScript编写服务器端程序。它的异步I/O模型使得它在处理高并发请求时表现出色,适合构建实时通信应用,如聊天系统、流媒体服务或API服务器。 2. **Express框架**:...
Node.js是一款基于Chrome V8引擎的JavaScript运行环境,它让JavaScript可以在服务器端执行,打破了JavaScript只能在浏览器中运行的传统。Node.js采用了事件驱动、非阻塞I/O模型,使其在高并发场景下表现出色,非常...
Node.js是一个流行的开源JavaScript运行环境,它允许开发人员使用JavaScript进行服务器端编程。这个系统不仅适用于大学生的课程设计,对于初学者和专业人士来说,也是一个很好的学习资源,可以深入理解Web应用开发。...
Node.js,作为一款基于Chrome V8引擎的JavaScript运行环境,以其非阻塞I/O和事件驱动的特性,使得它在构建高效、可扩展的网络应用时展现出强大的性能。本项目“基于Node.js的极简的学生管理系统”就是利用了这些优势...
标题中的“Node.js-基于Node.js Expressejs MongoDB Bootstrap搭建的班级博客系统”揭示了这个项目的核心技术栈,包括Node.js、Express、ejs模板引擎、MongoDB数据库以及Bootstrap前端框架。接下来,我将详细阐述...
《基于Node.js的部门管理系统设计与实现》 Node.js,作为一个强大的开源JavaScript运行环境,以其异步非阻塞I/O模型、高效的性能以及丰富的生态系统,成为构建高效网络应用的首选工具。本文将深入探讨如何利用Node....
Node.js是一款基于Chrome V8引擎的JavaScript运行环境,它允许开发者在服务器端使用JavaScript进行开发,极大地扩展了JavaScript的应用范围。 描述中的信息与标题相同,再次确认了这是一个针对Linux平台的Node.js...
总结,基于Node.js的宠物领养系统利用了JavaScript全栈开发的优势,结合现代化的Web技术和工具,构建了一个功能完善、安全可靠的平台,旨在促进宠物领养的透明度和便利性。在实际开发过程中,开发者应不断学习新技术...
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它让JavaScript得以在服务器端运行,打破了JavaScript只能在浏览器中使用的限制。Node.js采用单线程、事件驱动的非阻塞I/O模型,使其在高并发场景下表现出色,...
Node.js是一种基于Chrome V8引擎的JavaScript运行环境,它让开发者能够在服务器端使用JavaScript编写代码,极大地推动了前后端同栈开发的潮流。MongoDB是一个流行的NoSQL数据库,以其灵活性和高性能著称,适合处理...
Node.js是一种基于Chrome V8引擎的JavaScript运行环境,它允许开发者在服务器端使用JavaScript进行编程。这本《Node入门一本全面地Node.js教程》PDF,是学习Node.js的基础指南,涵盖了从安装到实际项目开发的全方位...
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它让开发者能够在服务器端使用 JavaScript 进行编程,极大地推动了全栈开发的流行。在这个名为 "Node.js-node开发的博客项目" 的案例中,我们看到的是一...
nosql, 面向小型 node.js 项目的NoSQL 嵌入式数据库 node.js NoSQL 嵌入数据库 重要: 新版本 has has新版本的新方法 has 。 数据库文件的结构是相同的。与专业支持的在线聊天。支持专业支持 。新: 在线 NoSQL 嵌入式...
Node.js作为一个高效的JavaScript运行环境,以其异步非阻塞I/O和事件驱动的特性,为开发高性能服务器端应用提供了可能。而MongoDB则是一款流行的NoSQL数据库,特别适合处理大量结构化和半结构化数据。 首先,我们...