Page cover

Queries

When working with a database, all operations are asynchronous — that’s just how things work in Lua and in GMod. Most Lua libraries deal with async code using callbacks… But I, the author of Wise, fucking hate callbacks.

Instead, Wise uses coroutines, which allow you to write asynchronous code that looks synchronous — clean, readable, no spaghetti.

🚦 Working with coroutines

To run any database query, you must wrap your logic in a coroutine:

local co = coroutine.create(function()
  local profile = profiles:findFirst({
    where = {
      steamid = player:SteamID64()
    }
  })

  if not profile then
    error("no profile")
  end

  print(profile.username) -- "wiseisbest!"
end)

coroutine.resume(co)

If you don’t understand how coroutines work, then honestly — don’t use Wise. This library is not made for people stuck in callback hell.

🧱 Tables

In SQL, tables are core to everything — they're where your data lives. Wise reflects that by treating tables as objects. You define a table like this:

local db = wise.new("sqlite", {})
local profiles = db:registerTable("profiles")

This profiles object now has full access to query methods like findFirst, insert, update, and so on.

📡 Query methods

Wise borrows heavily from Prisma’s model — a clean set of high-level query functions:

Method
Description

findFirst

Returns a single result matching query

findMany

Returns multiple results

insert

Creates a new record

update

Updates an existing record

delete

Deletes a record

🔍 findFirst

Returns the first row that matches the filter.

local profile = profiles:findFirst({
  where = {
    steamid = player:SteamID64()
  }
})

if not profile then
  error("no profile")
end

print(profile.username)

📋 findMany

Returns an array of matching rows.

local users = profiles:findMany({})

if not users then
  error("no profiles")
end

print(#users) -- e.g., 14

With limit

local users = profiles:findMany({
  limit = 5
})

print(#users) -- 5

With offset

local users = profiles:findMany({
  limit = 5,
  offset = 2
})

-- Skips first two results, gives next 5

insert

Creates a new row in the table.

local profile = profiles:insert({
  data = {
    steamid = player:SteamID64(),
    username = "wiseuser",
  }
})

✏️ update

Updates one or more rows.

local updated = profiles:update({
  where = {
    steamid = player:SteamID64()
  },
  data = { -- new data
    level = 2
  }
})

delete

Deletes rows matching condition.

local deleted = profiles:delete({
  where = {
    steamid = player:SteamID64()
  }
})

Last updated