SQLite-Express Version 3
The third version of SQLite-Express is much more convenient and powerful, as it has evolved from being a simple object with methods to a full-fledged class.
Installation
To install, execute the following command in your terminal:
npm i sqlite-express
Initialization
To instantiate the package, start with these lines:
const SqliteExpress = require('./index');
const session = new SqliteExpress();
With this new instance, you can execute all the previous methods in the same way you used to.
if you are using an environment with complex path handling such as next.js or react-router, it is recommended to instantiate the class with a parameter with the root path from which you are instantiating the class.
This avoids conflicts, however in simple applications it is not necessary.
const SqliteExpress = require('./index');
const session = new SqliteExpress('my/root/path');
Key Features
-
Queue System: The most substantial improvement is the integration of a queue to serialize operations. This avoids conflicts with the order of operations and prevents database overload. Thus, you're free to use loops.
-
Default Options Property: Another added feature is the defaultOptions
property. It eliminates the need to repeatedly pass the same arguments to methods. Now, all the properties you use in methods can be set in this object. Below is a list of these properties. If a value is already assigned (=
), it's the default:
rootPath = (path from where you instantiate the class)
emptyResult = undefined
route
db
key
table
where
columns
select = '*'
connector = 'AND'
update
row
processColumns = true
processRows = true
logQuery = true
You can modify these values individually or with the set
method:
session.defaultOptions.table = 'the_table';
session.defaultOptions.db = 'dataBase1';
session.defaultOptions.set({
table: 'the_table',
db: 'dataBase1',
route: './nuevaCarpeta/my_database.db',
logQuery: false
});
width set method yo don't need put all default options. Just the ones you want.
Methods
All of the following methods can either accept parameters in a specific order or receive an object as an argument.
createDB
The createDB
method allows you to create a new SQLite database or connect to an existing one. You need to specify both a relative path (based on the path from which the class was instantiated) and a unique key that identifies the database.
Usage
To create or connect to a database, use the following syntax:
session.createDB({ route: './data.db', key: 'dataBase1' });
In the example above, createDB
is invoked with a route of "./data.db", which refers to a new SQLite database file named "data.db" in the directory relative to where the class was instantiated. The key 'dataBase1' serves as a unique identifier for the database.
If a database file with the same name already exists at the specified path, createDB
will establish a connection to that existing database.
It's important to note:
- If the
route
is not provided, an error will be thrown. - If the
key
is not specified, a hexadecimal string will be generated and used as the default key.
The method returns the key, allowing you to store it as demonstrated below:
Using an explicit key:
const db = session.createDB({ route: './data.db', key: 'dataBase1' });
Using a generated hexadecimal key:
const db = session.createDB({ route: './data.db' });
It's important not to use the same key for different databases because this would cause an error.
Using Databases with Methods
Every subsequent method requires specifying a database (db
). If you are using only one database, it's advantageous to set it as the default.
To reference a database in methods, you can either use the explicit key
as a string or the return value from the createDB
method.
Using the Key Explicitly
First, create or connect to the database:
session.createDB({ route: './data.db', key: 'dataBase1' });
session.createTable({ db: 'dataBase1' });
Using the Return Value of createDB
Create or connect to the database and store the return value:
const db = session.createDB({ route: './data.db', key: 'dataBase1' });
session.createTable({ db: db });
This approach mirrors the method employed in version 2 of this package. As observed, there's no need to save the return value of createDB
to a variable if you're using an explicit key. However, if you do not provide an explicit key and rely on the generated hexadecimal key, you will need to store the return value for future references.
createTable
The createTable
method is used to create a new table in an SQLite database by specifying the database object, the table name as a string, and an object representing the column names and their respective data types.
Usage
To create a table in the database, use the following syntax:
session.createTable( 'dataBase1', "the_table", { name: "text", age: "integer", city: "text" } );
or
const objectToCreateTable = {
db : 'dataBase1',
table : "the_table",
columns : { name: "text", age: "integer", city: "text" }
}
session.createTable( objectToCreateTable );
In the example above, createTable is called with the database object data, the table name "la_tabla", and an object representing the column names and their data types. The column names and data types are defined within the object as key-value pairs. In this case, the table will have three columns: nombre of type text, edad of type integer, and ciudad of type text.
insert
The insert
method is used to insert data into a specific table in an SQLite database. It requires three parameters: the database object, the table name as a string, and an object representing the column names and the corresponding values to be inserted.
Usage
To insert data into a table in the database, use the following syntax:
session.insert( 'dataBase1', "the_table", { name: "Jhon", age: 27, city: "New York" } );
or
const rowToInsert = {
db : 'dataBase1',
table : "the_teble",
row : { name: "Jhon", age: 27, city: "New York" }
}
session.insert( rowToInsert );
In the example above, insert is called with the database object data, the table name "the_table", and an object representing the column names and their corresponding values. The object consists of key-value pairs, where the keys represent the column names and the values represent the data to be inserted into those columns. In this case, the name column will have the value "Jhon", the age column will have the value 27, and the city column will have the value "New York".
This method includes the possibility of saving automatically srtingify objects and arrays in a column of type text:
const rowToInsert = {
db : 'dataBase1',
table : "the_teble",
row : {
name: "Jhon",
age: 27,
city: ["New York", "Paris"]
}
}
session.insert( rowToInsert );
you should not stop the booleans to text either. The program understands that you want to convert them to text and saves them without any problems.
where constructor
The last 3 methods (update, delete and select) have among their possible parameters the where.
the basic use of the where constructor is the one already shown but it offers many more options.
const where = { age : 27 }
By default it assumes that the comparison operator you want to use is "=". But if you need another type of operator you can use the following format:
const where = {
age : {
operator : ">",
value : 27
}
}
In addition, several conditions can be added:
const where = {
age : {
operator : ">",
value : 27
},
name : "Alex"
}
When there is more than one condition the program assumes that the connector is "AND", if you want to use another one you have 2 options. The connector property represents the lowest connector of the logic:
const connector = "OR"
const where = {
age : {
operator : ">",
value : 27
},
name : "Alex"
}
All 3 methods accept this parameter, but you can also structure series of conditions from within where, so you can create more complex conditions. If you want to create a block of conditions whose connector is "OR" you must create an OR property and the same with AND:
const where = {
age : {
operator : ">",
value : 27
},
OR:{
name : "Alex",
city : "New York"
}
}
Ademas puedes asignar un array a los valores de las codiciones
const where = {
age : {
operator : ">",
value : 27
},
OR:{
name : ["Alex", "John", "Paul"],
city : "New York"
}
}
In this way we can create much more complex selectors.
update
The update
method is used to update records in a specific table in an SQLite database. It requires four parameters: the database object, the table name as a string, an object representing the column and the new data to be updated, and an object representing the condition for the update.
Usage
To update records in a table based on a specific condition, use the following syntax:
session.update('dataBase1', "the_table", {name: "Alex"}, {age: 27}, "OR");
or
const instructionsToUpdate = {
db : 'dataBase1',
table : "the_table",
update : {name: "Alex"},
where : {age: 27},
connector : "OR"
}
session.update(instructionsToUpdate);
In the example above, update is called with the database object data, the table name "the_table", an object representing the column and the new data {name: "Alex"}, and an object representing the condition {age: 27}. This means that the name column will be updated to "Alex" if the age column matches the value 27. For example, if there is a record with the name "Jhon" and the age 27, it will be updated to "Alex".
An interesting feature that this method has, is that some value of some update column can pass a funct
const instructionsToUpdate = {
db : 'dataBase1',
table : "the_table",
update : {age: (x)=>{return (x + 1)}},
where : {name: "Alex"},
connector : "OR"
}
session.update(instructionsToUpdate);
in this case it will select all the rows whose column "name" contains "Alex", it will take the current value of that cell and add 1. And it also works with arrays or objects. You can create functions that add an item to the array and return it for example.
const instructionsToUpdate = {
db : 'dataBase1',
table : "the_table",
update : {city: (x)=>{return [...x, "Londres"]}},
where : {name: "Alex"},
connector : "OR"
}
session.update(instructionsToUpdate);
delete
The delete
method is used to delete records from a specific table in an SQLite database based on a condition. It requires three parameters: the database object, the table name as a string, and an object representing the condition for the deletion.
Usage
To delete rows from a table based on a specific condition, use the following syntax:
session.delete('dataBase1', "the_table", {age: 27});
or
const rowToDelete = {
db : 'dataBase1',
table : "the_table",
where : {age: 27}
}
sqliteExpress.delete('dataBase1', "the_table", {age: 27});
In the example above, delete is called with the database object data, the table name "the_table", and an object representing the condition {age: 27}. This means that all records in the table with an age column equal to 27 will be deleted.
select
The select
method is used to retrieve data from a specific table in an SQLite database based on a condition. It requires four primary parameters: the database identifier, the table name as a string, the column name as a string (currently only supports one column), and an object representing the condition for the selection. It returns a Promise that resolves to the selected data.
Usage
To select data from a table based on a specific condition, use the following syntax:
async function theData() {
console.log(await session.select('dataBase1', "the_table", "city", {name: "Alex"}));
}
theData();
or
const objectToQuery = {
db: 'dataBase1',
table: "the_table",
select: "city",
where: {name: "Alex"}
}
async function theData() {
console.log(await session.select(objectToQuery));
}
theData();
You can also use .then
for handling the Promise:
session.select(objectToQuery).then(data => {
console.log(data);
});
In the examples above, the select
method is called with the database identifier dataBase1
, the table name "the_table", the column name "city", and an object representing the condition {name: "Alex"}. The method retrieves the values from the "city" column where the name
column matches "Alex". The selected data is returned as a Promise, and it is logged to the console.
The program detects if what is passed in is a stringified object and automatically handles it. The same goes for booleans. Additionally, if the method detects a single value being received, it directly provides the value to avoid the common situation of accessing a single-property object inside an array.
In this latest version, three more parameters were integrated for this method:
processColumns
: (default: true)processRows
: (default: true)emptyResult
: (default: undefines)
By default, sqlite3's select
method returns an array of objects. However, there are times when you might want to select just one column from one row, leading to repetitive code like rows[0].nombre
. With these parameters, you can decide if you want to unwrap the result object.
If the number of selected rows is 1 and processRows
is set to true, the method will return the row outside of the array. Similarly, if there's only one column and processColumns
is set to true, the value of that column will be returned outside of the object.
Furthermore, if the select
method's result doesn't match any rows with the query, it will return the value set in emptyResult
. This can be useful in different scenarios. Depending on your requirements, you might want it to return an empty array, an empty string, an empty object, null, false, or any other value you specify.
Recommendations
-
Avoid Referencing the Same Database from Different Instances:
It's not advisable to reference the same database from two different SqliteExpress
instances.
const instance1 = new SqliteExpress();
const instance2 = new SqliteExpress();
instance1.createDB({route : '.the_sameroute/the_same_DB.db'});
instance2.createDB({route : '.the_sameroute/the_same_DB.db'});
The class is designed to manage the waiting list of a database in order. However, with two instances pointing to the same file, there could be an asynchronicity conflict, negating the package's benefits.
-
Different Instances for Different Databases:
It's generally a good idea to create different instances for different databases. This allows you to assign default values suitable for each instance. Nevertheless, the class is equipped to handle multiple databases if desired.
-
Utilize Default Values:
Default values are handy and allow for cleaner subsequent code.
-
Method Parameters:
It's recommended to use methods by passing parameters as objects with their respective property names. While you can use parameters in order, it's not always practical when combined with default values.
If you wish to use a default value for one of the later parameters, simply don't include it. But if you want to use a default for an earlier parameter, you should mark it as undefined
.
session.defaultOptions.db = 'dataBase1';
session.insert(undefined, 'the_table', );
For accurate parameter handling, it's crucial to maintain their order. Below is a list showing the order of parameters for each method:
const orderOfParams = {
createDB: ['route', 'key', 'logQuery'],
createTable: ['db', 'table', 'columns', 'logQuery'],
insert: ['db', 'table', 'row', 'logQuery'],
select: ['db', 'table', 'select', 'where', 'connector', 'processColumns', 'processRows', 'emptyResult', 'logQuery'],
update: ['db', 'table', 'update', 'where', 'connector', 'logQuery'],
delete: ['db', 'table', 'where', 'connector', 'logQuery']
}
-
The logQuery
Parameter:
In this version, all methods have a logQuery
parameter which defaults to true
. This prints the generated SQL query to the console for further analysis. If you'd prefer less information in the console, you can set its default value to false
or pass a false
value to the methods as you see fit.
License
This software is licensed under the ISC License. The ISC License is a permissive free software license, allowing for freedom to use, modify, and redistribute the software, with some conditions. For the complete terms and conditions, please see the LICENSE file in the root directory of this project.