GlueSQL is quite sticky. It attaches to anywhere.
from gluesql import Glue, MemoryStorage
from tabulate import tabulate
db = Glue(MemoryStorage())
sql = """
SELECT
u.name as user,
d.name as device
FROM User u
JOIN Device d ON u.id = d.userId
""".strip().replace(
" ", ""
)
result = db.query(sql)
rows = result[0].get("rows")
print(f"\n[Query]\n{sql}")
print(tabulate(rows, headers="keys", showindex=True, tablefmt="simple_outline"))
ADD_MONTH
function @kite707 (#1341)SPLICE
function @jinlee0 (#1371)SLICE
function @Kwontaehwon (#1340)ast_builder
for skip function @cl-kim (#1334)SORT
function @Jaehui-Lee (#1300)LENGTH
function @jopemachine (#1298)ast_builder
for replace function @ChobobDev (#1275)SLICE
function doc @fregataa (#1425)from_utc
in Crate chrono
@zmrdltl (#1415)ConvertError
, @ever0de (#1401)Result
from ast_builder::transaction
return type @ever0de (#1404)actions-rs/toolchain
with dtolnay/rust-toolchain
@jongwooo (#1251)tabular off
and SelectMap
@devgony (#1314)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.14.0...v0.15.0
We now provide an official documentation website at https://gluesql.org/docs
GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. To create a schemaless table, simply run CREATE TABLE without specifying any columns. For more information on querying schemaless data, please refer to the following link: querying schemaless data
CREATE TABLE Bar;
To insert values,
INSERT INTO Bar VALUES
('{ "name": "ast", "value": 30 }'),
('{ "name": "glue", "rate": 3.0, "list": [1, 2, 3] }'),
Then, selecting values from schemaless table is simple.
SELECT name, rate, list[0] FROM Bar WHERE name = 'glue';
e.g.
CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');
CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');
SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/
GlueSQL supports handling in-memory, localStorage, sessionStorage, and even IndexedDB using the same SQL syntax. All you need to know is how to specify the ENGINE
when creating a table.
e.g.
CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;
SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;
UINT32
, UINT64
, UINT128
, POINT
and FLOAT32
POINT
Type and geometric functions @seonghun-dev (#1048)UINT32
, UINT64
and UINT128
data types @ChobobDev (#1019)APPEND
, PREPEND
, RAND
, FIND_IDX
, INITCAP
and CALC_DISTANCE
PREPEND
function for LIST
data type @seonghun-dev (#1149)FIND_IDX
function @zmrdltl (#1100)By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions. e.g.
CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;
SELECT ADD_ONE(10) AS test;
DROP FUNCTION ADD_ONE;
The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.
Jsonl
Storage to Json
Storage @devgony (#1128)JSON
format in JSONL storage
@devgony (#1123)Jsonl
Storage @devgony (#1053)"
) at to_sql
@devgony (#1130)Schema::from_ddl(ddl: &str) -> String
@devgony (#1089)TableFactor::{Derived, Dictionary, Series}
in AstBuilder @devgony (#1007)Vec<ColumnDef>
to Option<Vec<ColumnDef>>
@devgony (#1086)MutResult
@panarch (#1073)GLUE_TABLE_COLUMNS
@devgony (#1177)Cargo.lock
@ever0de (#1121)data/interval
module @ever0de (#1118)f64
support to data::Key
@panarch (#1114)ilike
function on Literal
being treated as⦠@ever0de (#1107)Rc
in validate.rs
@ever0de (#1106)Error::Storage
variant @ever0de (#1105)Box::pin
to futures_enum::Stream
@ever0de (#1103)TryStream
to Stream
@ever0de (#1102)Rc
from ColumnValidation
@ever0de (#1101)StringExt
implementation to use str
@ever0de (#1082)StrSlice
under enum Evaluated
@zmrdltl (#999)dyn object
to generic @ever0de (#1075)clone
in check_table_factor
@ever0de (#1058)1.66
@ever0de (#1057)sqlparser
version to 0.30
@ever0de (#1056)Box::pin
to futures_enum
in aggregate module @ever0de (#1055)Content::Shared
variant in executor/ RowContext
@ever0de (#1032)data::Row
to contain columns @panarch (#1026)ColumnOption
used only by alter-table
feature in ast-builder @ever0de (#1014)Parital{Ord,Cmp}
impl macro @ever0de (#1013)Value::position
@ever0de (#1012)double quotes
to identifier
@devgony (#1001)from_*
methods to from_*_opt
@ever0de (#1000)lock
when fetch_all_schemas
face idle
@devgony (#996)We now provide an official documentation website at https://gluesql.org/docs
docs/**
pa⦠@panarch (#1168)TryFrom<&Value> for Decimal
@ChobobDev (#1139)core/data
module unit tests @pythonbrad (#1092)Value::Str
to u128
not to use parse_uuid
@ChobobDev (#1134)TableFactor::Derived
@ding-young (#1119)deleted_by
is not present @ever0de (#1117)plan::validate
to handle CTAS
and ITAS
adding unit test @devgony (#1074)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.13.1...v0.14.0
--dump {PATH}
option$ gluesql --path ~/glue_data --dump ./dump.sql
-- dump.sql
CREATE TABLE Item (id INT, name TEXT);
CREATE INDEX item_id ON Item (id);
..
INSERT INTO Item VALUES (1, 'Foo'), (2, 'Bar') ..
..
$ gluesql --path ~/new_data --execute ./dump.sql
--dump {PATH}
argument (+to_ddl()
) by @devgony in https://github.com/gluesql/gluesql/pull/977
TryFrom for AstLiteral
=> TryFrom for Expr
, add more test to dump by @devgony in https://github.com/gluesql/gluesql/pull/990
Full Changelog: https://github.com/gluesql/gluesql/compare/v0.13.0...v0.13.1
AST Builder is now ready to be used! GlueSQL AST builder provides iterator chaining experience to manipulate data which is similar to array chaining methods or DataFrame syntax. For someone who is already familiar with SQL, then there would be almost no extra learning cost to use GlueSQL AST builder. AST builder accepts various sets of params - not only the expression built by its own expr builder, but also it even accepts raw SQL text and prebuilt ASTs.
e.g.
table("Item")
.select()
.join("Category")
.on(col("Category.id").eq("Item.category_id"))
.group_by("Item.category_id")
.having("SUM(Item.price) > 80")
.project("Category.name AS category")
.project("SUM(Item.price) AS sum_price")
.execute(glue)
.await;
category | sum_price |
---|---|
Meat | 90 |
Drink | 85 |
SELECT queries INSERT queries UPDATE queries DELETE queries
ArrayIndex
Expr @ding-young (#880)Into<..Node>
@panarch (#926)GLUE_TABLES
, GLUE_TABLE_COLUMNS
and GLUE_INDEXES
gluesql> SELECT * FROM GLUE_TABLES;
TABLE_NAME |
---|
Bar |
Foo |
gluesql> SELECT * FROM GLUE_TABLE_COLUMNS;
TABLE_NAME | COLUMN_NAME | COLUMN_ID |
---|---|---|
Bar | id | 1 |
Bar | name | 2 |
Bar | type | 3 |
Foo | id | 1 |
Foo | name | 2 |
gluesql> SELECT * FROM GLUE_INDEXES;
TABLE_NAME | INDEX_NAME | ORDER | EXPRESSION | UNIQUENESS |
---|---|---|---|---|
Foo | PRIMARY | BOTH | id | TRUE |
Foo | Foo_id_1 | BOTH | id + 1 | FALSE |
Foo | Foo_name_concat | BOTH | name + "_" | FALSE |
GLUE_INDEXES
reserved table which provides all index info @devgony (#935)ALIAS
clause like belowSELECT column_name AS alias_name FROM Table ORDER BY alias_name DESC
[error] value not found: alias_name
column_name
is still available at ORDER BY clause though SELECT clause uses alias_name
SELECT column_name AS alias_name FROM Table ORDER BY column_name DESC
COLUMN_INDEX
SELECT alpha, beta FROM Table ORDER BY 1 DESC
1
means the column_index which is first column alpha
ORDER BY
clause in VALUES list
gluesql> VALUES (1, 'a'), (2, 'b') ORDER BY column1 DESC;
column1 | column2
---------+---------
2 | b
1 | a
ALIAS
and COLUMN_INDEX
@devgony (#805)ORDER BY
clause in VALUES list
@devgony (#730)ToSql
trait for AST which provides AST to SQL text conversion for easier debugginge.g.
ToSql::to_sql
from the below AST returns this simple SQL text.
CREATE TABLE Foo (id INT, num INT NULL, name TEXT);
Statement::CreateTable {
if_not_exists: false,
name: "Foo".into(),
columns: vec![
ColumnDef {
name: "id".to_owned(),
data_type: DataType::Int,
options: vec![]
},
ColumnDef {
name: "num".to_owned(),
data_type: DataType::Int,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::Null
}]
},
ColumnDef {
name: "name".to_owned(),
data_type: DataType::Text,
options: vec![]
}
],
source: None
}
.to_sql()
UINT8
ASCII
, CHR
, POSITION
, TO_DATE
, TO_TIMESTAMP
and FORMAT
POSITION
@zmrdltl (#862)TO_TIME
function and let FORMAT
get TIME
data type @ChobobDev (#842)TO_DATE
and TO_TIMESTAMP
function @ChobobDev (#833)FORMAT
function @ChobobDev (#818).edit {fileName|None}
in CLI @devgony (#871)$> cargo run
gluesql> .run
[error] Nothing in SQL history to run.
gluesql> SELECT 1, 'a', true
1 | 'a' | true |
---|---|---|
1 | a | TRUE |
gluesql> .edit
=> open Editor with last command on temporary file like /tmp/Glue_****.sql
-- modify in editor
SELECT 1, 'a', true, 2, 'b'
If you want to fix editor type, run below command on OS
# (optional)
$> export EDITOR=vi
gluesql> .run
1 | 'a' | true | 2 | 'b' |
---|---|---|---|---|
1 | a | TRUE | 2 | b |
gluesql> .edit foo.sql
-- modify in editor
SELECT 1 AS no, 'In physical file' AS name
gluesql> .execute foo.sql
no | name |
---|---|
1 | In physical file |
gluesql> .set tabular OFF
gluesql> .set colsep ,
gluesql> .set colwrap '
gluesql> .set heading OFF
gluesql> VALUES (1, 'a', true), (2, 'b', false)
'1','a','true'
'2','b','false'
Set markdown as default print style like below
gluesql> SELECT * FROM (VALUES (1, 'a', true), (2, 'b', false)) AS Sub;
column1 | column2 | column3 |
---|---|---|
1 | a | TRUE |
2 | b | FALSE |
(pasted from gluesql directly) |
comfy-table
with tabled
@devgony (#830)Expr::Case
in aggregate module @ever0de (#945)Expr
@zmrdltl (#749)sqlparser-rs
upgradesoperator.rs
@ChobobDev (#783)error test cases
to correct file
@zmrdltl (#794)top level test files
to new tester folder
@zmrdltl (#792)uuid
version to 1.2.1
@ever0de (#943)GlueSQL
projects into pkg/*
per language @ever0de (#917)TryBinaryOperator
, @ever0de (#915)await
keyword. @24seconds (#889)GStore
, GStoreMut
traits @ever0de (#884)ObjectName
with String
@devgony (#873)validate_unique
function when only PrimaryKey
exists @ever0de (#832)TryFrom<&Value> for usize
@devgony (#795)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.12.0...v0.13.0
T
// v0.11
pub trait Store<T: Debug> { .. }
pub trait StoreMut<T: Debug> where Self: Sized { .. }
pub trait Index<T: Debug> { .. }
pub trait IndexMut<T: Debug> where Self: Sized { .. }
// v0.12
pub trait Store { .. }
pub trait StoreMut where Self: Sized { .. }
pub trait Index { .. }
pub trait IndexMut where Self: Sized { .. }
Related PRs
Store::fetch_data
is newly added, Store
trait now requires three methods to implement
pub trait Store {
async fn fetch_schema(&self, table_name: &str) -> Result<Option<Schema>>;
async fn fetch_data(&self, table_name: &str, key: &Key) -> Result<Option<Row>>;
async fn scan_data(&self, table_name: &str) -> Result<RowIter>;
}
Related PR
StoreMut
trait method renamings - insert_data -> append_data
and update_data -> insert_data
pub trait StoreMut where Self: Sized {
...
async fn append_data(..) -> ..;
async fn insert_data(..) -> ..;
}
Related PR
GlueSQL now supports PRIMARY KEY!
CREATE TABLE Allegro (
id INTEGER PRIMARY KEY,
name TEXT,
);
more info - test-suite/primary_key
Expr::CompoundIdentifier
to have more accurate data format @devgony (#770)SERIES(N)
SELECT 1;
SELECT N FROM SERIES(10);
more info - test-suite/series
SELECT * FROM Series(N)
and SELECT 1
(without table) @devgony (#733)VALUES
supportVALUES (1, 'a'), (2, 'b');
VALUES (1, 'a'), (2, 'b') LIMIT 1;
VALUES (1, 'a'), (2, 'b') LIMIT 1 OFFSET 1;
SELECT * FROM (VALUES (1, 'a'), (2, 'b')) AS Derived;
SELECT * FROM (VALUES (1, 'a'), (2, 'b')) AS Derived(id, name);
CREATE TABLE TableFromValues AS VALUES (1, 'a', True, Null, Null), (2, 'b', False, 3, Null)
more info - test-suite/values
Derived VALUES
@devgony (#731)Values List
to validate column type @devgony (#659)VALUES List
in select
module @devgony (#648)SELECT * FROM (SELECT COUNT(*) FROM InnerTable) AS InlineView
more info - test-suite/inline_view
SharedMemoryStorage
Non-persistent storage engine which works in multi-threaded environment
Now, SQL is not the only language supported by GlueSQL! AST Builder generates GlueSQL AST directly from Rust codes.
e.g.
let actual = table("Bar")
.select()
.filter(col("id").is_null())
.group_by("id, (a + name)")
.build();
let expected = "
SELECT * FROM Bar
WHERE id IS NULL
GROUP BY id, (a + name)
";
let actual = table("Bar")
.select()
.group_by("city")
.project("city, COUNT(name) as num")
.build();
let expected = "
SELECT
city, COUNT(name) as num
FROM Bar
GROUP BY city
";
let actual = table("Person")
.delete()
.filter(col("name").is_null())
.build();
let expected = "DELETE FROM Person WHERE name IS NULL";
more info - core/ AST Builder
Related PRs
Gcd
and Lcm
function to ast_builder
@ChobobDev (#734)Log
function to ast_builder
@ChobobDev (#729)Power
and Sqrt
function to ast_builder
@ChobobDev (#726)ln
in ast_builder @gimwonbae (#680)COUNT
@zmrdltl (#656).spool FilePath
command in CLI @devgony (#748).columns TABLE
command in CLI @devgony (#736)STDEV
& VARIANCE
STDEV
aggregate funtion @zmrdltl (#684)VARIANCE
aggregate function & update aggregate test @zmrdltl (#598)sqrt
for enum Value
@zmrdltl (#675)IFNULL
SHOW INDEXES FROM {table}
ToSql
ToSql
trait which displays AST as SQL text format @bearney74 (#554)basic
@zmrdltl (#785)vec!
, iter()
@zmrdltl (#775)arithmetic
@zmrdltl (#773)aggregate
@zmrdltl (#771)Duration
@ever0de (#722)Box
@ever0de (#716)TryInto
traits into TryFrom
@nyeong (#682)test-suite
workspace @ever0de (#649)Result
@ever0de (#622)Deserialize
for Payload
@ever0de (#607)Dialect
in parse_query @ever0de (#584)to_string
macro with the serialize_all
macro @ever0de (#565)gluesql-js/README.md
Webpack example @MRGRAVITY817 (#559)CAST
into i32 or i64 from numeric literals @bearney74 (#611)sled_multi_threaded
example code with threads of INSERT
and SELECT
, @ever0de (#580)DROP INDEX
invalid params @ever0de (#566)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.11.0...v0.12
JavaScript interface for both web browsers and Node.js
GlueSQL works again in web browsers!
e.g.
import { gluesql } from 'gluesql';
const db = await gluesql();
db.query(`
CREATE TABLE User (id INTEGER, name TEXT);
INSERT INTO User VALUES (1, "Hello"), (2, "World");
`);
const [{ rows }] = await db.query('SELECT * FROM User;');
console.log(rows);
ABS
, SIGN
and CONCAT
SHOW COLUMNS
SledStorage
export and importINT8
type @MRGRAVITY817 (#477)limit
, offset
clause in Insert into values ~ @devgony (#484)sqlparser-rs
migrationsqlparser
crate version from 0.11 to 0.13 @MRGRAVITY817 (#479)IndexMut
@ever0de (#488)Debug
macro from the generic requirements for key @ever0de (#486)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.10.2...v0.11.0
# Cargo.toml
[dependencies.gluesql]
version = "0.10.2"
default-features = false
features = ["memory-storage"]
# or features = ["sled-storage"]
Configuration above now works.
memory-storage
or sled-storage
features were not working in v0.10.1
and it is fixed in v0.10.2
.
limit
, offset
clause in Insert into Table Select ~
@devgony (#466)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.10.1...v0.10.2
$ cargo install gluesql
cli/target
to <general>/target
in ignore, @ever0de (#443)INT(8)
Add int8 data type @ever0de (#407)DECIMAL
Adding data type: Decimal @boomkim (#377)EXTRACT
& NOW
CREATE TABLE AS SELECT
) support3! = 6
) operator supportSHOW TABLES
& SHOW VERSION
Metadata
optional store trait, @panarch (#438)gluesql
workspace to root lib-package @ever0de (#446)join_columns
argument from Join::apply()
to Join::new()
@MRGRAVITY817 (#441)order_by
from query to select @devgony (#435)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.9.0...v0.10.1
MemoryStorage
Now GlueSQL supports two reference storages - SledStorage
and MemoryStorage
UUID
- add uuid data type @maruoovv (#360)MAP
- Add MAP
data type and UNWRAP
function @panarch (#367)LIST
- Add LIST data type, @panarch (#370)SQRT
, POWER
- Add Sqrt, Power @simple6192 (#312)RADIANS
, DEGREES
, PI
- Implement radians, degrees, pi math functions #280 @devil-k (#322)LTRIM
, RTRIM
- Implement Function: LTRIM, RTRIM @devgony (#294)REVERSE
- [ADD] - reverse function @zmrdltl (#327)ASIN
, ACOS
, ATAN
- Add functions: ASIN(), ACOS(), ATAN() @boomkim (#296)TRIM
- Implement TRIM function - Other features @ever0de (#307)SUBSTR
- Implement substr function @vbbono (#341)LOG
- Support function LOG
@slhmy (#371)REPEAT
- Implement REPEAT Function @inhwa1025 (#352)UUID
- add function random generate uuid value @maruoovv (#372)AVG
- Support aggregation AVG
@zmrdltl (#368)%
- Implement binary operator modulo %
@MRGRAVITY817 (#319)ILIKE
& NOT ILIKE
- Support ILIKE and NOT ILIKE operator @maruoovv (#334)XOR
- Support binary operator XOR
, update data-type Int
@zmrdltl (#359)CASE
- Support conditional function CASE
@MRGRAVITY817 (#330)'static
lifetime of generic types for GStore
@ever0de (#400)SledStorage::check_retry
wrapper function @ever0de (#392)1.56
& edition 2021
@ever0de (#395)UUID
to Uuid
to follow the naming convention of Enums @MRGRAVITY817 (#389)MOD
to use modulo
in Evaluated
@MRGRAVITY817 (#321)PRIMARY KEY
is used. @heka1024 (#339)Full Changelog: https://github.com/gluesql/gluesql/compare/v0.8.0...v0.9.0
GlueSQL now supports "TRANSACTION"!
New Transaction
store trait with three interface methods: begin
, rollback
and commit
is added.
GlueSQL's default storage engine, SledStorage
supports MVCC transaction using snapshot based internal data structure.
SledStorage
transaction detailsSNAPSHOT ISOLATION
or also known as REPEATABLE READ
.TRIM
, LPAD
and RPAD
FLOOR
, CEIL
, ROUND
, DIV
, MOD
, GCD
, LCM
, SIN
, COS
, TAN
, EXP
, LN
, LOG2
and LOG10
.Exp
, Ln
, Log2
, Log10
@heka1024 (#305)DivisorShouldNotBeZero
error and Remove {number} / {interval}
implementations @MRGRAVITY817 (#309)sled_transaction_timeout_
tests timeout duration, @panarch (#316)Welcome and thanks a lot to new contributors!