From fbf54e7cd564b57990e9e876bc1c9319aae7682d Mon Sep 17 00:00:00 2001 From: FullGreaM Date: Sun, 26 Jun 2022 20:40:36 +0300 Subject: [PATCH] upload v. 1.0.0 --- README.md | 308 +++++++++++++++++--------------------- SQLEasyTools.js | 92 ++++++++++++ index.js | 27 ++++ mysql.js | 371 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 208 +++++++++++++++++++++++++- package.json | 15 +- sqlite3.js | 189 +++++++++++++++++++++++ 7 files changed, 1033 insertions(+), 177 deletions(-) create mode 100644 SQLEasyTools.js create mode 100644 mysql.js create mode 100644 sqlite3.js diff --git a/README.md b/README.md index cd10c4f..a0d10f2 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,137 @@ -**WARNING!!!** It's a legacy version of current library! *Do not use in release product!!* - -# SQLEasy.js -module for simple works from sqlite3 (JavaScript edition) -## Prepare for work (install from github) -Use npm from install in your project: -```bash -npm install sql-easy-lib -``` -import database object in your project -``` javascript -const SQLEasy = require('sql-easy-lib'); -var database = new SQLEasy.database('/path/to/database.db'); -``` -This object have 4 methods: add, remove, set, get -## Prepare for work (install from github) -My module use module **better-sqlite3**, you must download it. -```bash -npm install better-sqlite3 -``` -from next, you can download folder of project, and load in folder "node_modules" -``` bash -cd node_modules -git clone https://github.com/Nikiroy78/SQLEasy.js.git -``` -import database object in your project -``` javascript -const SQLEasy = require('SQLEasy.js'); -var database = new SQLEasy.database('/path/to/database.db'); -``` -This object have 4 methods: add, remove, set, get -## Methods of SQLEasy object -### get -This method getting date from included database -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -console.log(database.get('table')); -``` -output... -``` javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 2, 'content': 'Content number 3 :)'}, {'ID': 3, 'content': 'etc.'}] -``` - -You can apply condition's settings from filt your data... -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -console.log(database.get('table', [{'ID': 0}, {'content': 'etc.'}])); -``` -output... -``` javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 3, 'content': 'etc.'}] -``` -Response show is... -```SQL -SELECT * FROM table WHERE (ID=0) OR (content='etc.') -``` -And you edit uploaded columns -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -console.log(database.get('table', [{'ID': 0}, {'content': 'etc.'}], 'content')); -``` -output... -``` javascript -[{'content': 'content 1'}, {'content': 'etc.'}] -``` -Response show is... -```SQL -SELECT content FROM table WHERE (ID=0) OR (content='etc.') -``` -### add -This is sql response -```SQL -INSERT -``` -Using add method in your code (from your simply, we used old date from last database). -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -database.add('table', [{'ID': 4, 'content': 'test example, from fucking tests :)'}]) -console.log(database.get('table')); -``` -output... -```javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 2, 'content': 'Content number 3 :)'}, {'ID': 3, 'content': 'etc.'}, {'ID': 4, 'content': 'test example, from fucking tests :)'}] -``` -### remove -Using remove method in your code (from your simply, we used old date from last database). -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -database.remove('table', {'ID': 4}); -console.log(database.get('table')); -``` -output... -```javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 2, 'content': 'Content number 3 :)'}, {'ID': 3, 'content': 'etc.'}] -``` -### set -Using set method in your code (from your simply, we used old date from last database). -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -database.set('table', {'ID': 3}, {'content': 'edited'}); // First param - index key, found param - edit content... -console.log(database.get('table')); -``` -output... -```javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 2, 'content': 'Content number 3 :)'}, {'ID': 3, 'content': 'edited'}] -``` -### execute -This is important method from execute your SQL script in your code. -Using method **execute** in test code (from your simply, we used old date from last database). -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database'); - -var data = database.execute('SELECT * FROM table'); -console.log(data); -``` -output... -```javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 2, 'content': 'Content number 3 :)'}, {'ID': 3, 'content': 'etc.'}] -``` -### getIndex -Use this method from getting index value. -```javascript -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); - -console.log(database.get('table')); -console.log(database.getIndex('table', 'ID')); -``` -output... -```javascript -[{'ID': 0, 'content': 'content 1'}, {'ID': 1, 'content': 'other content'}, {'ID': 3, 'content': 'Content number 3 :)'}, {'ID': 4, 'content': 'edited'}] -2 -``` -## Other functions that you can use in this module -### get_from_key -This function needs from works data in buffer. -The main advantage of this method is that you do not need to request data from the database every time, it is enough to use the data uploaded to memory: -```javascript -// Legacy method! -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); -var rolesData = database.get('users').map(i => { - return { - user: i, - role_data: database.get('role', [{id: i.role}]) - } -}); -``` -```javascript -// New method! -const sqlite = require('SQLEasy.js'); -var database = sqlite.database('/path/to/database.db'); -var roleData = database.get('role', [{id: i.role}]); -var rolesData = database.get('users').map(i => { - return { - user: i, - role_data: sqlite.get_from_key(roleData, [{id: i.role}]) - } -}); +# SQLEasy library +This library was written from simple work with databases. In current version supported next famous databases: sqlite3 and MySQL. In future, list with supported databases will be replenishing. +## Prepare to work +Before you use this module you must install it. +```bash +npm install sql-easy-lib --save +``` +and you can include it! +```node +const SQLEasy = require('sql-easy-lib'); +``` +## Tools and main objects +Before work, you must know about twice main tools: **get_from_key** and **Request**. +```node +const SQLEasy = require('sql-easy-lib'); + +var req = new SQLEasy.Request([{id: 1, value: 12}, {name: 'CirillaGif'}]); +/* This is boolean operation: "(id=1 AND value=12) OR (name=`CirillaGif`)" */ +var get_from_key = SQLEasy.tools.get_from_key; +/* get_from_key function, about him in down. */ +``` +**Request** use from create logic expression +*example:* +```node +// ... +new SQLEasy.Request([{id: 1, value: 12}, {name: 'CirillaGif'}]); +``` +```mysql +(id=1 AND value=12) OR (name=`CirillaGif`) +``` +**get_from_key** use for more efficient queries from buffer variables. +*example:* +```node +// Without use get_from_key +const SQLEasy = require('sql-easy-lib'); +var database = new SQLEasy.SQLite3_database('/path/to/database.db'); +var rolesData = database.get('users').map(i => { + return { + user: i, + role_data: database.get('role', new SQLEasy.Request([{id: i.role}])) + } +}); +``` +```node +// With use get_from_key +const SQLEasy = require('sql-easy-lib'); +var database = new SQLEasy.SQLite3_database('/path/to/database.db'); +var roleData = database.get('role', new SQLEasy.Request([{id: i.role}])); +var rolesData = database.get('users').map(i => { + return { + user: i, + role_data: sqlite.get_from_key(roleData, new SQLEasy.Request([{id: i.role}])) + } +}); +``` +## Methods of databases +In all databases methods is equally *(except for the connection)*. +```node +const SQLEasy = require('sql-easy-lib'); +/* Method for connection sqlite3 database */ +var sqlite3 = new SQLEasy.SQLite3_database('/path/to/database.db'); +/* Method for connection MySQL database */ +var mysql = new SQLEasy.MySQL_database({ + host: "mysql.example.org", + user: "username", + password: "password" +}); +mysql.set_db("Example_db"); // setting database in server +``` +*(for example, we use abstract database object):* **database** +```node +const SQLEasy = require('sql-easy-lib'); + +var database = new SQLEasy.AnyDatabase(args); +``` +### get +This is getting items from table: +```mysql +SELECT +``` +*syntax:* +```node +database.get( + 'table_name', + new SQLEasy.Request([{param: 'value'}]), // Not required: ...WHERE (CONDITION) in request + '*' // Not required: Items in table +); +``` +```mysql +SELECT * FROM table_name WHERE (param=`value`) +``` +### set +This is set values in items in table: +```mysql +UPDATE .. SET +``` +*syntax:* +```node +database.set( + 'table_name', + new SQLEasy.Request([{param: 'value_require_edit'}]), // Required: ...WHERE (CONDITION) in request + [{param: 'value'}] // Required: Items in table +); +``` +```mysql +UPDATE table_name SET param=`value` WHERE (param=`value_require_edit`) +``` +### remove +This method for remove items into database. +```mysql +DELETE +``` +*syntax:* +```node +database.remove( + 'table_name', + new SQLEasy.Request([{param: 'value'}]) // Required: ...WHERE (CONDITION) in request +); +``` +```mysql +DELETE FROM table_name WHERE (param=`value_require_edit`) +``` +### add +Method for add items into database. +```mysql +INSERT +``` +*syntax:* +```node +database.remove( + 'table_name', + [{param: 'value'}] // Required: ... Rows what you add in table. +); +``` +```mysql +INSERT INTO table_name (param) VALUES (`value`) ``` \ No newline at end of file diff --git a/SQLEasyTools.js b/SQLEasyTools.js new file mode 100644 index 0000000..acca08e --- /dev/null +++ b/SQLEasyTools.js @@ -0,0 +1,92 @@ +function get_from_key (db_data, conditions) { + conditions = conditions.requestElements.requestElements.filter(i => i != {}); + if (conditions == [] || !conditions) return db_data; + let item = new Object(); + let bool_conditions = new Array(); + let condition_item = new Object(); + let int_condition = 1; + + let out_objs = new Array(); + + for (let i in db_data) { + bool_conditions = new Array(); + item = db_data[i]; + + for (let index in conditions) { + int_condition = 1; + condition_item = conditions[index]; + for (key in condition_item) { + int_condition *= Number(item[key] == condition_item[key]); + } + bool_conditions.push(int_condition); + } + if (bool_conditions.reduce((a, b) => Boolean(a + b))) out_objs.push(item); + } + + return out_objs; +} + + +class SQLEasy_error extends Error { + constructor(message) { + super(message); + this.name = "SQLEasy_error"; + } +} + + +class Request { + constructor (construction) { + if (typeof(construction) != 'object') throw SQLEasy_error('in Request you can use only object type'); + try { + construction.map(i => i); + this.requestElements = construction; + } + catch (err) { + this.requestElements = [construction]; + } + } + + toString (query_funct = (value) => '?') { + let values = new Array(); + return { str: this.requestElements.map(items => { + let queries = new Array(); + for (let key in items) { + queries.push(`${key}=${query_funct(items[key])}`); + values.push(items[key]); + } + return `(${queries.join(' AND ')})`; + }).join(' OR '), values: values}; + } +} + + +class db { + constructor () { + // get + this.getTable = this.get; + this.getBase = this.get; + this.select = this.get; + + // set + this.update = this.set; + this.setItem = this.set; + + // add + this.insert = this.add; + this.push = this.add; + this.append = this.add; + + // remove + this.del = this.remove; + this.pop = this.remove; + } +} + + +module.exports = { + Request: Request, + SQLEasy_error: SQLEasy_error, + get_from_key: get_from_key, + Database: db +} \ No newline at end of file diff --git a/index.js b/index.js index a1135f4..ab4ed7a 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,29 @@ +<<<<<<< HEAD +const mysql = require('./mysql'); +const sqlite = require('./sqlite3'); +const sqleasy_tools = require('./SQLEasyTools'); + + +class legacy_sqlite3_db extends sqlite.database { + constructor (path, warning=true) { + super(path, warning); + console.log('You use legacy method of connect to sqlite3 database. If you want use actual method, then use "new SQLite3_database(\'/path/to/database.db\');"'); + console.log('This connection method can be deactivated in next versions!!'); + } +} + + +module.exports = { + database: legacy_sqlite3_db, + SQLite3_database: sqlite.database, + MySQL_database: mysql.mysql_database, + + Request: sqleasy_tools.Request, + tools: { + get_from_key: sqleasy_tools.get_from_key + } +} +======= const sqlite3 = require('better-sqlite3'); @@ -197,3 +223,4 @@ module.exports = { database: database, get_from_key: get_from_key }; +>>>>>>> 631660a213570390163bbcd41828a472dbf95841 diff --git a/mysql.js b/mysql.js new file mode 100644 index 0000000..9175073 --- /dev/null +++ b/mysql.js @@ -0,0 +1,371 @@ +const MySql = require('sync-mysql'); +const sqleasy_tools = require('./SQLEasyTools'); + + +class MySQL_error extends Error { + constructor(message) { + super(message); + this.name = "MySQL_error"; + } +} + +function gen_qw (value) { + if (typeof(value) == 'number') return '?'; + else return '??'; +} + + +function compile_responses(responses) { + let string_responses = new Array(); + let gen_resp = ''; + let item = ''; + for (ind in responses) { + item = responses[ind]; + if (item == undefined) { + string_responses.push(gen_resp); + break; + } + else if (item.length < 81) { + if (gen_resp == '') { + gen_resp = item; + } + else if ((gen_resp + ';\n' + item).length >= 81) { + string_responses.push(gen_resp); + gen_resp = item; + } + else { + gen_resp += ';\n' + item; + } + } + else string_responses.push(item); + } + if (gen_resp != '') { + string_responses.push(gen_resp); + } + return string_responses; +} + + +function convert_to_object (output, index_key, save_ik = false) { // Not checked! + let item = new Object(); + let out_object = new Object(); + let item_obj = new Object(); + + for (let i in output) { + item = output[i]; + item_obj = item; + if (!save_ik) delete item_obj[index_key]; + + out_object[item[index_key]] = item_obj; + } + + return item_obj; +} + + +class mysql_database { + ToString(value) { // Convertion to string (legacy) + // return typeof (value) === 'string' ? '\'' + value + '\'' : value; + if (typeof (value) === 'string') { + if (warns == true) { + // console.log('WARNING!! You use legacy function, please reword your code from used current methods'); + } + value = value.replace(new RegExp("'", 'g'), "\\'"); + value = `'${value}'`; + return value; + } + else return value; + } + debug (Text) { + if (this.settings.debug) console.log(Text); + } + constructor(connection_object, settings = new Object()) { // init + this.settings = { + toggle_commit: Boolean(settings.toggle_commit), + warns: Boolean(settings.warns), + debug: Boolean(settings.debug) + } + + if (settings.warns == undefined) this.settings.warns = true; + if (settings.debug == undefined) this.settings.debug = false; + if (settings.toggle_commit == undefined) this.settings.toggle_commit = true; + + this.connection = new MySql(connection_object); + this.db_connection = undefined; + this.isCommiting = this.settings.toggle_commit; + this.warns = this.settings.warns; + + this.commit_steps = new Array(); + this.commit_values = new Array(); + + this.commit_sessions = new Object(); + } + toggle_commit (condition) { // toggle using .commit() in methods + this.isCommiting = condition; + } + operation(SQLRequest, values, session = null) { // Add to commit's buffer + if (SQLRequest[SQLRequest.length - 1] != ';') SQLRequest = `${SQLRequest};` + if (session == null) { + this.commit_steps.push(SQLRequest); + for (let v=0; v < values.length; v++) { + this.commit_values.push(values[v]); + } + } + else { + if (this.commit_sessions[session] != undefined) { + this.commit_sessions[session].commit_steps.push(SQLRequest); + for (let v=0; v < values.length; v++) { + this.commit_sessions[session].commit_values.push(values[v]); + } + } + else throw new MySQL_error('Session not founded.'); + } + } + new_commit_session (session) { // Create new commit's session + this.commit_sessions[session] = { + commit_steps: new Array(), + commit_values: new Array() + }; + } + commit(session = null) { // commit changes in database + // console.log(`Called commit with session ${session}`); + this.debug(`Called commit with session ${session}`); + let SQLRequest = ''; + let commit_values = new Array(); + if (session == null) { + SQLRequest = this.commit_steps.join('\n'); + commit_values = this.commit_values; + } + else { + if (this.commit_sessions[session] != undefined) { + let session_info = this.commit_sessions[session]; + + SQLRequest = session_info.commit_steps.map((item) => { + if (Boolean(item)) return item; + }).join('\n'); + commit_values = session_info.commit_values; + } + else throw new MySQL_error('Session not founded.'); + } + + let result = undefined; + let error = false; + try { + // this.debug(` >> SQLRequest: ${SQLRequest}\n >> commit_values: ${commit_values}`); + this.debug(`\n################################################################\n${SQLRequest}\n################################################################`); + this.debug(`${commit_values}\n################################################################`); + // result = this.connection.query(SQLRequest, commit_values); + // console.log('SQLRequest:', SQLRequest); + // console.log('commit_values:', commit_values); + result = this.exec(SQLRequest, commit_values); + } + catch (err) { + error = err; + } + + if (session == null) this.commit_steps = new Array(); + else this.commit_sessions[session].commit_steps = new Array(); + + if (session == null) this.commit_values = new Array(); + else this.commit_sessions[session].commit_values = new Array(); + + this.debug(` >> LEN: ${this.commit_steps}`); + + if (error.message != undefined) { + console.log(error.stack); + throw new MySQL_error(error.message); + } + return result; + } + getIndex(table, index_column, start_index_value = 0) { // getting index + if (this.db_connection == undefined) throw new MySQL_error('You must choose database. Use [mysql_database Object].set_db(\'database_name\')'); + // let database_data = this.get(table).sort(i => i[index_column]); + let database_data = this.get(table).sort((a, b) => a[index_column] - b[index_column]); + let filter_dict = new Object(); + let item = Object(); + let index = start_index_value; + + for (let i in database_data) { + item = database_data[i]; + if (item[index_column] >= start_index_value) { + if (item[index_column] > index) return index; + else index++; + } + } + + /*for (let i = start_index_value; i < database_data.length; i++) { + filter_dict = database_data[i]; + filter_dict[index_column] = i; + if (!get_from_key(database_data, [filter_dict])) return i; + }*/ + return index; + // return this.get(table).length; + } + // SQL Methods + set_db(database_name) { // using database + try { + this.debug(`USE ${database_name}`); + this.connection.query(`USE ${database_name}`); + + this.db_connection = database_name; + } + catch (err) { + throw new MySQL_error(err.message); + } + } + exec(SQLRequest, params = []) { // Execute SQL Request + /*if (typeof(params) !== 'object' || typeof(params) !== 'array') { + params = new Array(); + }*/ + let SQLRequests = SQLRequest.split(';').filter(i => Boolean(i)).map((item) => `${item.trim()};`); + let results = new Array(); + + for (let i in compile_responses(SQLRequests)){ + SQLRequest = SQLRequests[i]; + if (Boolean(SQLRequest)) { + try { + this.debug(`\n################################################################\n${SQLRequest}\n################################################################`); + this.debug(`${params}\n################################################################`); + results.push(this.connection.query(SQLRequest, params)); + } + catch (err) { + // console.log(err.stack); + throw new MySQL_error(err.message); + } + } + } + results = results.filter(i => Boolean(i)); + /*results = results.map((res) => { + if (res != undefined) return res; + });*/ + if (results.length == 1) return results[0]; + else return results; + } + get(table, filt = null, keys = '*', commit = false, session = null) { // Select rows from table + if (this.db_connection == undefined) throw new MySQL_error('You must choose database. Use [mysql_database Object].set_db(\'database_name\')'); + let SQLRequest = `\nSELECT ${keys} FROM ${this.db_connection}.${table}`; + try { + /*let args = new Array(); + if (Boolean(filt) != false) { + let orBlock = new Array(); + for (let i = 0; i < filt.length; i++) { + let andBlock = new Array(); + for (let key in filt[i]) { + andBlock.push(`${key}=?`); + args.push(filt[i][key]); + } + orBlock.push(`(${andBlock.join(' AND ')})`); + } + SQLRequest = `${SQLRequest} WHERE ${orBlock.join(' OR ')}`; + } + this.debug(`GET: ${SQLRequest}`); + this.debug(`ARGS: ${args}`);*/ + if (!!filt) SQLRequest = `${SQLRequest} WHERE ${filt.toString().str}`; + this.debug(' GET >> SQLRequest:', SQLRequest); + + if (!!filt) this.operation(SQLRequest, filt.toString().values); + else this.operation(SQLRequest, []); + if (this.isCommiting || commit) return this.commit(session); + } + catch (err) { + console.log(err.stack); + throw new MySQL_error(err.message); + } + } + add(table, addvArray, ignore = false, commit = false, session = null) { // Insert new values + if (this.db_connection == undefined) throw new MySQL_error('You must choose database. Use [mysql_database Object].set_db(\'database_name\')'); + try { + this.get(table); + + let SQLRequest = new Array(); + let args = new Array(); + for (let i = 0; i < addvArray.length; i++) { + let addObject = addvArray[i]; + let keys = new Array(); + let values = new Array(); + for (let key in addObject) { + keys.push(key); + values.push('?'); + args.push(addObject[key]); + } + let op = 'INSERT'; + if (ignore) op = 'INSERT OR IGNORE'; + SQLRequest.push(`${op} INTO ${this.db_connection}.${table} (${keys.join(', ')}) VALUES (${values.join(', ')});`); + } + SQLRequest = SQLRequest.join('\n'); + // let SQLRequest = `${}`; + + this.debug(` ADD >> ${SQLRequest}`); + this.operation(SQLRequest, args); + + if (this.isCommiting || commit) return this.commit(session); + } + catch (err) { + throw new MySQL_error(err.message); + } + } + remove(table, index, commit = false, session = null) { // Delete values + if (this.db_connection == undefined) throw new MySQL_error('You must choose database. Use [mysql_database Object].set_db(\'database_name\')'); + try { + this.get(table); + let SQLRequest = new Array(); + let args = new Array(); + + // let equal_req = ''; + // let equal_req = new Array(); + /*for (let key in index) { + // equal_req = `${key} = ?`; + equal_req.push(`${key} = ?`); + args.push(index[key]); + // break; + }*/ + SQLRequest = `DELETE FROM ${this.db_connection}.${table} WHERE ${index.toString().str}`; + this.debug(SQLRequest); + this.operation(SQLRequest, index.toString().values); + if (this.isCommiting || commit) return this.commit(session); + } + catch (err) { + throw new MySQL_error(err.message); + } + } + + set(table, index, values, ignore=false, commit = false, session = null) { // Updating setav data + if (this.db_connection == undefined) throw new MySQL_error('You must choose database. Use [mysql_database Object].set_db(\'database_name\')'); + try { + let op = 'UPDATE'; + + this.get(table); + let SQLRequest = new Array(); + let args = new Array(); + + // let equal_index = new Array(); + let equal_values = new Array(); + + for (let key in values) { + equal_values.push(`${key} = ?`); + args.push(values[key]); + } + for (let i in index.requestElements) { + for (let key in index.requestElements[i]) { + // equal_index.push(`${key} = ?`); + args.push(index.requestElements[i][key]); + } + } + if (ignore) op = 'UPDATE OR IGNORE'; + SQLRequest = `${op} ${this.db_connection}.${table} SET ${equal_values.join(', ')} WHERE ${index.toString().str}`; + this.debug(SQLRequest); + this.operation(SQLRequest, args); + if (this.isCommiting || commit) return this.commit(session); + } + catch (err) { + console.log(err.stack); + throw new MySQL_error(err.message); + } + } +} + + +module.exports = { + mysql_database: mysql_database, + MySQL_error: MySQL_error +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index eef88a4..0722f91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,41 @@ { "name": "sql-easy-lib", - "version": "0.9.1", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "asap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha512-Ej9qjcXY+8Tuy1cNqiwNMwFRXOy9UwgTeMA8LxreodygIPV48lx8PU1ecFxb5ZeU1DpMKxiq6vGLTxcitWZPbA==" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "barrage": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/barrage/-/barrage-1.1.0.tgz", + "integrity": "sha512-lmhNsUZG+34gUrZl0SKOeYZ20o4Xni2wd52fzzrIsniQqoqfwa3otEP4Vceks+KwGACNsnQ1YSYtsaPWHrQ+3Q==", + "requires": { + "promise": "^6.0.0" + }, + "dependencies": { + "promise": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha512-O+uwGKreKNKkshzZv2P7N64lk6EP17iXBn0PbUnNQhk+Q0AHLstiTrjkx3v5YBd3cxUe7Sq6KyRhl/A0xUjk7Q==", + "requires": { + "asap": "~1.0.0" + } + } + } + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -18,6 +50,11 @@ "prebuild-install": "^7.1.0" } }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -45,11 +82,66 @@ "ieee754": "^1.1.13" } }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -91,6 +183,11 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==" + }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -111,6 +208,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -134,6 +236,46 @@ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", @@ -174,6 +316,26 @@ "tunnel-agent": "^0.6.0" } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + }, + "dependencies": { + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + } + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -204,6 +366,11 @@ "util-deprecate": "^1.0.1" } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -232,6 +399,11 @@ "simple-concat": "^1.0.0" } }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -245,6 +417,25 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" }, + "sync-mysql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sync-mysql/-/sync-mysql-3.0.1.tgz", + "integrity": "sha512-EKWJFuiPRtj1s6bjSaf4tzMFeq8x0JgKtgyIsTTkD20E8pkzInEFxj1B+efbYMjQUfN9MEY3HOsaSYUmSbsUKw==", + "requires": { + "babel-runtime": "^6.18.0", + "concat-stream": "^1.6.0", + "sync-rpc": "^1.1.1", + "then-mysql": "^1.1.1" + } + }, + "sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "requires": { + "get-port": "^3.1.0" + } + }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -268,6 +459,16 @@ "readable-stream": "^3.1.1" } }, + "then-mysql": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/then-mysql/-/then-mysql-1.1.1.tgz", + "integrity": "sha512-QqWODY1xtWFo3XR4GllWFkXMTz+QirJKcggMETNPeGqPDcxUyApqDW5GgAUJEz4Dga3/WrXNmZY0bT+cAWjQ2g==", + "requires": { + "barrage": "^1.1.0", + "mysql": "^2.10.0", + "promise": "^7.1.1" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -276,6 +477,11 @@ "safe-buffer": "^5.0.1" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 30ff9bd..810142e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sql-easy-lib", - "version": "0.9.1", - "description": "(Legacy version of SQLEasy library)", + "version": "1.0.0", + "description": "This library was written from simple work with databases. In current version supported next famous databases: sqlite3 and MySQL. In future, list with supported databases will be replenishing.", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -17,6 +17,13 @@ }, "homepage": "https://github.com/Nikiroy78/SQLEasy.js#readme", "dependencies": { - "better-sqlite3": "^7.5.3" - } + "better-sqlite3": "^7.5.3", + "sync-mysql": "^3.0.1" + }, + "keywords": [ + "sqlite3", + "sql", + "database", + "mysql" + ] } diff --git a/sqlite3.js b/sqlite3.js new file mode 100644 index 0000000..3926884 --- /dev/null +++ b/sqlite3.js @@ -0,0 +1,189 @@ +const sqlite3 = require('better-sqlite3'); +const sqleasy_tools = require('./SQLEasyTools'); + + +function get_from_key (db_data, conditions) { + conditions = conditions.filter(i => i != {}); + if (conditions == [] || !conditions) return db_data; + let item = new Object(); + let bool_conditions = new Array(); + let condition_item = new Object(); + let int_condition = 1; + + let out_objs = new Array(); + + for (let i in db_data) { + bool_conditions = new Array(); + item = db_data[i]; + + for (let index in conditions) { + int_condition = 1; + condition_item = conditions[index]; + for (key in condition_item) { + int_condition *= Number(item[key] == condition_item[key]); + } + bool_conditions.push(int_condition); + } + if (bool_conditions.reduce((a, b) => Boolean(a + b))) out_objs.push(item); + } + + return out_objs; +} + + +class database { + constructor(path, warning=true){ + this.PATH = path; + // this.db = new sqlite3.Database(this.PATH); // async - heresy! + this.db = new sqlite3(this.PATH); + // Создаём "функции-двойники" + this.getTable = this.getBase; + this.get = this.getTable; + this.select = this.get; + this.set = this.setItem; + this.insert = this.add; + this.update = this.set; + this.remove = this.del; + this.pop = this.del; + this.exec = this.execute; + } + ToString(value) { + return typeof(value) === 'string' ? '\'' + value + '\'' : value; + } + getIndex (table, indexColumn, index_starts = 0) { + // return this.get(table).length; + let tableData = this.get(table).sort((a, b) => a[indexColumn] - b[indexColumn]); + let index = index_starts - 1; + for (let i in tableData) { + if (index_starts <= i) { + if (i != tableData[i][indexColumn]) return i; + index = i; + } + } + return Number(index) + 1; + } + execute(SQLRequest) { + try { + return this.db.prepare(SQLRequest).all(); + } catch(err) { + if(err.message.indexOf('run()') !== -1) { + try { + this.db.prepare(SQLRequest).run(); + return null; + } catch(err) { + throw new Error(`SQLEasy error: ${err.message}`); + } + } + else{ + throw new Error(`SQLEasy error: ${err.message}`); + } + } + } + getBase(table, condition=null, keys='*') { + let SQLRequest = `SELECT ${keys} FROM ${table}`; + let values = null; + if (condition !== null) { + /*let orBlock = new Array(); + for(let i = 0; i < condition.length; i++){ + let andBlock = new Array(); + for(let key in condition[i]){ + andBlock.push(`${key}=${this.ToString(condition[i][key])}`); + } + orBlock.push(`(${andBlock.join(' AND ')})`); + }*/ + SQLRequest = `${SQLRequest} WHERE ${condition.toString().str}`; + } + // console.log(SQLRequest); // Убрать после тестов!! + try { + // let rows = this.db.prepare(SQLRequest).all(); + let rows; + if (!condition) rows = this.db.prepare(SQLRequest).all(); + else rows = this.db.prepare(SQLRequest).all(condition.toString().values); + if (!!rows) return rows; + else throw new Error('SQLEasy error: Rows given null.'); + } catch(err) { + if(err.message.indexOf('no such table') !== -1){ + throw new Error('SQLEasy error: this table not founded.'); + } + else throw new Error(`SQLEasy error: ${err.message}`); + } + } + add(table, addvArray, ignore=false){ + this.getBase(table); + let SQLRequest = new Array(); + let setting_values = new Array(); + for(let i = 0; i < addvArray.length; i++) { + let addObject = addvArray[i]; + let keys = new Array(); + let values = new Array(); + // setting_values = new Array(); + for(let key in addObject){ + keys.push(key); + setting_values.push(addObject[key]); + values.push('?'); + } + let op = 'INSERT'; + if(ignore) op = 'INSERT OR IGNORE'; + SQLRequest.push(`${op} INTO ${table} (${keys.join(', ')}) VALUES (${values.join(', ')});`); + } + SQLRequest = SQLRequest.join('\n'); + try{ + // this.db.prepare(SQLRequest).run(setting_values); + // this.db.prepare(SQLRequest).exec(setting_values); + this.db.prepare(SQLRequest).run(setting_values); + } catch(err){ + if (ignore) throw new Error(`SQLEasy error: ${err.message}`); + else this.add(table, addvArray, true); + } + } + del(table, index){ + this.get(table); + /*let equal_req = ''; + for(let key in index) { + equal_req = `${key} = ${this.ToString(index[key])}`; + break; + }*/ + let SQLRequest = `DELETE FROM ${table} WHERE ${index.toString().str}`; + try { + this.db.prepare(SQLRequest).run(index.toString().values); + } catch(err) { + throw new Error(`SQLEasy error: ${err.message}`); + } + } + setItem(table, index, values){ + this.getBase(table); + let equal_index = ''; + let equal_values = ''; + let value_array = new Array(); + + for (let key in values) { + // equal_values = `${key} = ${this.ToString(values[key])}`; + equal_values = `${key} = ?`; + value_array.push(values[key]); + break; + } + for (let i in index.requestElements) { + for(let key in index.requestElements[i]){ + // equal_index = `${key} = ${this.ToString(index.requestElements[key])}`; + equal_index = `${key} = ?`; + value_array.push(index.requestElements[i][key]); + break; + } + } + // let SQLRequest = `UPDATE ${table} SET ${equal_values} WHERE ${equal_index}`; + let SQLRequest = `UPDATE ${table} SET ${equal_values} WHERE ${index.toString().str}`; + try { + // this.db.prepare(SQLRequest).get(value_array).run(); + this.db.prepare(SQLRequest).run(value_array); + } catch(err) { + console.log(err.stack); + throw new Error(`SQLEasy error: ${err.message}`); + } + } +} + + +module.exports = { + database: database, + get_from_key: get_from_key +}; \ No newline at end of file