Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
MySQL.ready(async function () {
// Async/Await demo:

console.log(await MySQL.Async.fetchScalar("SELECT @parameters", { "@parameters": 1 }))

console.log(await MySQL.Async.fetchScalar("SELECT @parameters", { "@parameters": "Hello World" }))

console.log(await MySQL.Async.fetchAll("SELECT * FROM whitelist", {}))

console.log(await MySQL.Async.insert("INSERT INTO players(name, money, location) VALUES (@name, @money, @location)",
{
"@name": "Player 1",
"@money": 5000,
"@location": JSON.stringify({ x: 50, y: 10, z: 20 })
})
)

// Callback demo:
MySQL.fetchScalar("SELECT @parameters", { "@parameters": 1 }, function (result) {
console.log(result);
})

MySQL.fetchScalar("SELECT @parameters", { "@parameters": "Hello Callback!" }, function (result) {
console.log(result);
})

MySQL.fetchAll("SELECT * FROM whitelist", {}, function (results) {
console.log(results);
})

MySQL.insert("INSERT INTO players(name, money, location) VALUES (@name, @money, @location)",
{
"@name": "Player 1",
"@money": 5000,
"@location": JSON.stringify({ x: 50, y: 10, z: 20 })
},
function (insertId) {
console.log(insertId)
}
)
})
164 changes: 164 additions & 0 deletions lib/MySQL.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
var MySQL = {
Async: {},
}

function safeParameters(params) {
if (!params) return { "": "" };
if (typeof (params) != "object") throw new Error("A Object is expected");
if (!Object.keys(params).length) return { "": "" };

return params
}

/**
* Execute a query with no result required, sync version
* @param {String} query
* @param {Object} params
* @returns Promise (Number of rows updated)
*/
MySQL.Async.execute = (query, params) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_execute(query, safeParameters(params), function (result) {
resolve(result);
})
})
}

/**
* Execute a query and fetch all results, sync version
* @param {String} query
* @param {Object} params
* @returns Promise (Array of Query results)
*/
MySQL.Async.fetchAll = (query, params) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_fetch_all(query, safeParameters(params), function (result) {
resolve(result);
})
})
}

/**
* Execute a query and fetch the first column of the first row, sync version
* Useful for count function by example
* @param {String} query
* @param {Object} params
* @returns Promise (mixed Value of the first column in the first row)
*/
MySQL.Async.fetchScalar = (query, params) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_fetch_scalar(query, safeParameters(params), function (result) {
resolve(result);
})
})
}

/**
* Execute a query and retrieve the last id insert, sync version
* @param {String} query
* @param {Object} params
* @returns Promise (mixed Value of the last insert id)
*/
MySQL.Async.insert = (query, params) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_insert(query, safeParameters(params), function (result) {
resolve(result);
})
})
}

/**
* Stores a query for later execution
* @param {String} query
* @returns Promise
*/
MySQL.Async.store = (query) => {
if (typeof (query) != "string") throw new Error("The SQL Query must be a string")
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_store(query, function (result) {
resolve(result);
})
})
}

/**
* Execute a List of querys and returns bool true when all are executed successfully
* @param {Array} querys
* @param {Object} params
* @returns Promise (bool if the transaction was successful)
*/
MySQL.Async.transaction = (querys, params) => {
return new Promise((resolve, reject) => {
exports['mysql-async'].mysql_transaction(querys, params, function (result) {
resolve(result);
})
})
}

/**
* Execute a query with no result required, async version
* @param {String} query
* @param {Object} params
* @param {Function} func
*/
MySQL.fetchAll = (query, params, func) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
exports['mysql-async'].mysql_fetch_all(query, safeParameters(params), func)
}

/**
* Execute a query and fetch the first column of the first row, async version
* Useful for count function by example
* @param {String} query
* @param {Object} params
* @param {Function} func
*/
MySQL.fetchScalar = (query, params, func) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
exports['mysql-async'].mysql_fetch_scalar(query, safeParameters(params), func)
}

/**
* Execute a query and retrieve the last id insert, async version
* @param {String} query
* @param {Object} params
* @param {Function} func
*/
MySQL.insert = (query, params, func) => {
if (typeof (query) != "string" && typeof (query) != "number") throw new Error("The SQL Query must be a string")
exports['mysql-async'].mysql_insert(query, safeParameters(params), func)
}

/**
* Stores a query for later execution
* @param {String} query
* @param {Function} func
*/
MySQL.store = (query, func) => {
if (typeof (query) != "string") throw new Error("The SQL Query must be a string")
exports['mysql-async'].mysql_store(query, func)
}

/**
* Execute a List of querys and returns bool true when all are executed successfully
* @param {Array} querys
* @param {Object} params
* @param {Function} func
* @returns Bool true if successfully
*/
MySQL.transaction = (querys, params, func) => {
return exports['mysql-async'].mysql_transaction(querys, params, func)
}

MySQL.ready = (callback) => {
const i = setInterval(() => {
if (GetResourceState('mysql-async') != 'started') return;
if (!exports['mysql-async'].is_ready()) return;
clearInterval(i);
callback()
}, 100)
}
111 changes: 111 additions & 0 deletions src/docs/content/pages/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Contrary to older *Sync* implementations, these functions are safe to use, since
### MySQL.ready

You need to encapsulate your code into `MySQL.ready` to be sure that the mod will be available and initialized before your first request. In subsequent examples the `MySQL.ready` function will not be shown, and it is expected that the code is encapsulated.
#### Lua
```lua
MySQL.ready(function ()
print(MySQL.Sync.fetchScalar('SELECT @parameters', {
Expand All @@ -23,10 +24,26 @@ string
]]--
```

#### JavaScript
```javascript
MySQL.ready(function () {
console.log(await MySQL.Async.fetchScalar('SELECT @parameters', {
'@parameters': 'string'
}
))
})
/*
prints:

string
*/
```

### execute

Execute a mysql query which should not send any result (like a Insert / Delete / Update), and will return the number of affected rows.

#### Lua
```lua
MySQL.Async.execute('INSERT INTO users_log (x, y, z, playerId) VALUES (@x, @y, @z, @id)',
{ ['x'] = pos.x, ['y'] = pos.y, ['z'] = pos.z, ['id'] = player.id },
Expand All @@ -41,10 +58,25 @@ prints:
]]--
```

#### JavaScript
```javascript
console.log(await MySQL.Async.execute('INSERT INTO users_log (x, y, z, playerId) VALUES (@x, @y, @z, @id)',
{ '@x': pos.x, '@y': pos.y, '@z': pos.z, '@id': player.id }
))
/*
prints:

1
*/
```



### fetchAll

Fetch results from MySQL and returns them in the form of an Array of Objects:

#### Lua
```lua
MySQL.Async.fetchAll('SELECT * FROM users WHERE id = @id', { ['@id'] = playerId }, function(result)
print(json.encode(result))
Expand All @@ -63,9 +95,30 @@ prints:
]]--
```

#### JavaScript
```javascript
console.log(await MySQL.Async.fetchAll('SELECT * FROM users WHERE id = @id',
{ '@id': playerId }
))
/*
prints:

[{
"id": 95585726093402110,
"cash": 0,
"bank": 0,
"skin": "{}",
"online": true,
"lastSeen": 1590656804000
}]
*/
```

### fetchScalar

Fetch the first field of the first row in a query:

#### Lua
```lua
MySQL.Async.fetchScalar('SELECT COUNT(1) FROM users', {}, function(result)
print(result)
Expand All @@ -77,10 +130,21 @@ prints:
]]--
```

#### JavaScript
```javascript
console.log(await MySQL.Async.fetchScalar('SELECT COUNT(1) FROM users', {} ))
/*
prints:

15
*/
```

### insert

Returns the last insert id of the inserted item. Needs an auto-incremented primary key to work.

#### Lua
```lua
MySQL.Async.insert('INSERT INTO users_log (x, y, z, playerId) VALUES (@x, @y, @z, @id)',
{ ['x'] = pos.x, ['y'] = pos.y, ['z'] = pos.z, ['id'] = player.id },
Expand All @@ -95,12 +159,25 @@ prints:
]]--
```

#### JavaScript
```javascript
console.log(await MySQL.Async.fetchScalar('INSERT INTO users_log (x, y, z, playerId) VALUES (@x, @y, @z, @id)',
{ '@x': pos.x, '@y': pos.y, '@z': pos.z, '@id': player.id }
))
/*
prints:

1137
*/
```

### store

The store export should be used for storing query strings, when a lot of queries are expected to be triggered at once. The idea behind this feature is, that while recieving data puts stress on your server infrastructure, so does sending data. And the biggest polluter for this resource is sending overly long and complicated query strings.

While the server is running you want to minimize the impact of sending a lot of queries at once puts on your architecture, thus you can already store these queries ahead of time, and just pass the id returned by the callback function and pass the parameters for these queries along.

#### Lua
```lua
insertUserLog = -1
MySQL.Async.store("INSERT INTO users_log SET ?", function(storeId) insertUserLog = storeId end)
Expand All @@ -112,4 +189,38 @@ MySQL.Async.insert(insertUserLog, {
end)
```

#### JavaScript
```javascript
var insertUserLog = await MySQL.Async.store('INSERT INTO users_log SET ?');
// ...
console.log(await MySQL.Async.insert(insertUserLog,
{ '@x': pos.x, '@y': pos.y, '@z': pos.z, '@id': player.id }
))
```

This works like the example above, but the query string does not need to be reset and is a bit more elegant in the writing.


Every JavaScript function is also available as a callback function.
Just leave out the ".Async" keyword and add a callback as the last argument.
#### JavaScript
```javascript
MySQL.fetchAll('SELECT * FROM users WHERE id = @id',
{ '@id': playerId },
function (results) {
console.log(results);
}
)
/*
prints:

[{
"id": 95585726093402110,
"cash": 0,
"bank": 0,
"skin": "{}",
"online": true,
"lastSeen": 1590656804000
}]
*/
```