oql

package module
v0.0.0-...-b9b2519 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2026 License: MIT Imports: 14 Imported by: 0

README ยถ

OmniQL

Universal Query Language for All Databases

Write once, run anywhere. One language for PostgreSQL, MySQL, MongoDB, and Redis.

Go Version License PRs Welcome


๐ŸŽฏ The Problem

Modern applications use multiple databases (polyglot persistence), but each requires different query syntax:

  • PostgreSQL uses SQL with $1, $2 parameters
  • MySQL uses SQL with ? placeholders
  • MongoDB uses JSON queries with {$gt: 25}
  • Redis uses command syntax like ZRANGEBYSCORE

Context-switching kills productivity. Developers spend hours rewriting queries when changing databases.


โœจ The Solution

OmniQL provides a single, universal query language that translates to native database syntax:

GET User WHERE age > 25 AND status = 'active' LIMIT 10

Translates to:

PostgreSQL:

SELECT * FROM users WHERE age > $1 AND status = $2 LIMIT 10

MySQL:

SELECT * FROM users WHERE age > ? AND status = ? LIMIT 10

MongoDB:

db.users.find({age: {$gt: 25}, status: "active"}).limit(10)

Redis:

SCAN 0 MATCH user:* COUNT 10

One query. Four databases. Zero rewrites.


โœจ Features

๐Ÿ—๏ธ Production-Ready Architecture (v2.0)

  • โœ… TrueAST Parser - 100% expression-based AST, recursive structures everywhere
  • โœ… Bidirectional Translation - OQL โ†” Native (PostgreSQL, MySQL, MongoDB, Redis)
  • โœ… Smart Error Messages - Typo detection with "Did you mean?" suggestions
  • โœ… Zero-Latency Translation - Parse and translate in microseconds
  • โœ… Type Safety - Universal type system with database-specific mappings
  • โœ… Battle-Tested - 765+ tests across all components

๐Ÿ”„ Bidirectional Translation

OQL โ†’ Native (Forward):

query, _ := parser.Parse("GET User WHERE id = 1")
result, _ := translator.Translate(query, "postgresql", "tenant1")
// โ†’ SELECT * FROM users WHERE id = $1

Native โ†’ OQL (Reverse):

query, _ := reverse.PostgreSQLToQuery("SELECT * FROM users WHERE id = 1")
// โ†’ {Operation: "GET", Entity: "User", Conditions: [...]}

query, _ := reverse.MySQLToQuery("SELECT * FROM users WHERE status = 'active'")
query, _ := reverse.MongoDBToQuery(`{"find": "users", "filter": {"id": 1}}`)
query, _ := reverse.RedisToQuery("HGETALL tenant:123:users:1")

๐Ÿ’ก Smart Error Messages

OmniQL detects typos and suggests corrections:

GTE User
โ†’ parse error: unknown operation 'GTE'. Did you mean 'GET'?

GET User WHER id = 1
โ†’ parse error: unknown keyword 'WHER'. Did you mean 'WHERE'?

GET User WHERE id INN (1,2,3)
โ†’ parse error: unknown operator 'INN'. Did you mean 'IN'?

GET User ORDRE BY name
โ†’ parse error: unknown keyword 'ORDRE'. Did you mean 'ORDER BY'?

Coverage: 87 operations, 16 clauses, 19 operators - all with typo detection.

๐ŸŽฏ 87 Universal Operations

Category Operations Count
CRUD GET, CREATE, UPDATE, DELETE, UPSERT, BULK INSERT, REPLACE โœ… 7
DDL CREATE/DROP/ALTER TABLE, INDEX, VIEW, DATABASE, SCHEMA, SEQUENCE, TRIGGER, FUNCTION, TYPE, DOMAIN, POLICY, RULE, EXTENSION โœ… 28
DQL JOIN (5 types), Aggregations (5), Window Functions (6), CTEs, Subqueries, Set Operations (4), CASE, EXISTS, PARTITION BY โœ… 31
TCL BEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK TO, RELEASE SAVEPOINT, START, SET TRANSACTION โœ… 8
DCL GRANT, REVOKE, CREATE/DROP/ALTER USER, CREATE/DROP ROLE, ASSIGN ROLE, REVOKE ROLE โœ… 9
TOTAL โœ… 87

๐Ÿงฎ Advanced Expression Engine

Expressions work everywhere: UPDATE SET, WHERE, ORDER BY, SELECT WITH

Binary Arithmetic:

UPDATE Product SET price = price * 1.1
UPDATE Order SET total = price * quantity
UPDATE Sale SET profit = (price - cost) * qty * (1 - discount)

String Functions:

UPDATE User SET name = UPPER(name)
UPDATE Profile SET full_name = CONCAT(first, ' ', last)
GET User WHERE UPPER(email) = 'ADMIN@EXAMPLE.COM'

CASE WHEN Logic:

UPDATE User SET status = CASE 
  WHEN age >= 18 THEN 'adult' 
  WHEN age >= 13 THEN 'teen' 
  ELSE 'child' 
END

Calculated Columns:

GET Order WITH price * quantity AS total
GET Sale WITH price - cost AS profit, price * qty AS revenue

Supported:

  • Operators: +, -, *, /, %, <, >, <=, >=, =, !=, AND, OR, NOT
  • Functions: UPPER, LOWER, CONCAT, LENGTH, ABS, ROUND, NOW, COALESCE

๐Ÿ“Š Complete Aggregation Support

# Basic aggregations
COUNT User
SUM Sale amount
AVG Score points
MIN Price value
MAX Stock quantity

# With filtering
COUNT User WHERE age > 25
SUM Sale WHERE status = 'completed' amount

# With grouping
COUNT Order GROUP BY customer
SUM Revenue GROUP BY region

# With HAVING
SUM Sale GROUP BY dept HAVING SUM(amount) > 10000

# Complex combinations
SUM Order WHERE status = 'active' GROUP BY customer 
  HAVING SUM(total) > 1000 ORDER BY customer LIMIT 10

๐Ÿ”— Advanced Query Features

JOINs (5 types):

GET User INNER JOIN Order ON User.id = Order.user_id
GET User LEFT JOIN Order ON User.id = Order.user_id WHERE Order.status = 'active'
GET Product RIGHT JOIN Category ON Product.category_id = Category.id
GET TableA FULL JOIN TableB ON TableA.key = TableB.key
GET UserA CROSS JOIN UserB

Window Functions (6 types):

GET Sale WITH ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS rank
GET Employee WITH LAG(salary) OVER (ORDER BY hire_date) AS prev_salary
GET Student WITH RANK() OVER (PARTITION BY class ORDER BY score DESC) AS rank
GET Data WITH DENSE_RANK() OVER (ORDER BY value) AS dense_rank
GET Category WITH NTILE(4) OVER (ORDER BY revenue DESC) AS quartile
GET Metric WITH LEAD(value) OVER (ORDER BY date) AS next_value

Common Table Expressions (CTEs):

CTE regional_sales AS (SUM Sale GROUP BY region) 
  GET regional_sales WHERE total > 100000

Set Operations:

GET User WHERE age > 25 UNION GET User WHERE status = 'premium'
GET Product WHERE category = 'electronics' INTERSECT GET Product WHERE price < 1000
GET Employee EXCEPT GET Employee WHERE department = 'deprecated'
UNION ALL ...

๐Ÿ”’ Enterprise-Grade Security

  • โœ… SQL Injection Prevention - Parameterized queries for all operations
  • โœ… Input Sanitization - Automatic escaping of special characters
  • โœ… Safe String Handling - Apostrophes (O'Brien), quotes, backslashes handled correctly
  • โœ… Type Validation - Strong type checking at parse time

โšก Transaction Support

BEGIN
UPDATE Account SET balance = balance - 100 WHERE id = 1
UPDATE Account SET balance = balance + 100 WHERE id = 2
COMMIT

# Or rollback on error
BEGIN
UPDATE Inventory SET stock = stock - 10
ROLLBACK

Advanced Transaction Control:

  • โœ… SAVEPOINT - Create rollback points within transactions
  • โœ… ROLLBACK TO - Partial rollback to savepoint
  • โœ… Isolation Levels - READ COMMITTED, REPEATABLE READ, SERIALIZABLE
  • โœ… ACID Guarantees - Full transactional integrity

๐Ÿ—„๏ธ Supported Databases

Database Version CRUD Expressions Aggregations JOINs Window Fns Transactions Reverse Parser
PostgreSQL 16+ โœ… โœ… โœ… โœ… โœ… โœ… โœ…
MySQL 8.0+ โœ… โœ… โœ… โœ… โœ… โœ… โœ…
MongoDB 8.0+ โœ… โœ… โœ… โœ… via $lookup โš ๏ธ Limited โœ… โœ…
Redis 7.0+ โœ… โš ๏ธ Limited โœ… via SCAN โŒ โŒ โœ… โœ…

Tested versions: PostgreSQL 16.10, MySQL 8.0.44, MongoDB 8.0.15, Redis 7.4.4

Legend:

  • โœ… Full support
  • โš ๏ธ Partial support (database architectural limitations)
  • โŒ Not applicable to database type

๐Ÿš€ Installation

go get github.com/omniql-engine/omniql

๐Ÿ’ก Quick Examples

Basic CRUD

import (
    "github.com/omniql-engine/omniql/engine/parser"
    "github.com/omniql-engine/omniql/engine/translator"
)

// Parse OQL
query, _ := parser.Parse("GET User WHERE age > 25")

// Translate to any database
pgResult, _ := translator.Translate(query, "postgresql", "tenant1")
myResult, _ := translator.Translate(query, "mysql", "tenant1")
mongoResult, _ := translator.Translate(query, "mongodb", "tenant1")
redisResult, _ := translator.Translate(query, "redis", "tenant1")

Reverse Parsing (SQL โ†’ OQL)

import "github.com/omniql-engine/omniql/engine/reverse"

// PostgreSQL โ†’ OQL
query, _ := reverse.PostgreSQLToQuery("SELECT * FROM users WHERE id = 1")
fmt.Println(query.Operation) // "GET"
fmt.Println(query.Entity)    // "User"

// MySQL โ†’ OQL
query, _ := reverse.MySQLToQuery("INSERT INTO users (name, age) VALUES ('John', 25)")
fmt.Println(query.Operation) // "CREATE"

// MongoDB โ†’ OQL
query, _ := reverse.MongoDBToQuery(`{"find": "users", "filter": {"status": "active"}}`)

// Redis โ†’ OQL
query, _ := reverse.RedisToQuery("HGETALL tenant:123:users:1")

Error Handling with Suggestions

query, err := parser.Parse("GET User WHER id = 1")
if err != nil {
    fmt.Println(err)
    // parse error at line 1, column 10: unknown keyword 'WHER'. Did you mean 'WHERE'?
}

๐Ÿ“ Project Structure

omniql/
โ”œโ”€โ”€ engine/
โ”‚   โ”œโ”€โ”€ ast/           # Abstract Syntax Tree nodes
โ”‚   โ”œโ”€โ”€ models/        # Query model definitions
โ”‚   โ”œโ”€โ”€ lexer/         # Tokenizer with error suggestions
โ”‚   โ”œโ”€โ”€ parser/        # OQL โ†’ AST parser
โ”‚   โ”œโ”€โ”€ builders/      # AST โ†’ Native query builders
โ”‚   โ”‚   โ”œโ”€โ”€ mongodb/
โ”‚   โ”‚   โ”œโ”€โ”€ mysql/
โ”‚   โ”‚   โ”œโ”€โ”€ postgres/
โ”‚   โ”‚   โ””โ”€โ”€ redis/
โ”‚   โ”œโ”€โ”€ reverse/       # Native โ†’ OQL parsers
โ”‚   โ”œโ”€โ”€ translator/    # Translation orchestration
โ”‚   โ””โ”€โ”€ validator/     # Query validation per database
โ”œโ”€โ”€ mapping/           # Operations, clauses, operators (SSOT)
โ””โ”€โ”€ utilities/
    โ””โ”€โ”€ proto/         # Protocol buffer definitions

๐ŸŽ‰ What's New in v2.0

Major Features

๐Ÿ”„ Bidirectional Translation

  • Forward: OQL โ†’ PostgreSQL, MySQL, MongoDB, Redis
  • Reverse: PostgreSQL, MySQL, MongoDB, Redis โ†’ OQL
  • Full round-trip support for query migration

๐Ÿ’ก Smart Error Messages

  • Levenshtein distance-based typo detection
  • Suggestions for 87 operations, 16 clauses, 19 operators
  • Unconsumed token detection (no more silent failures)

๐Ÿ—๏ธ TrueAST Architecture

  • 100% expression-based AST
  • Recursive structures for complex expressions
  • Clean separation: Lexer โ†’ Parser โ†’ Translator โ†’ Builder

โœ… Comprehensive Testing

  • 765+ tests across all components
  • Round-trip validation for all reverse parsers
  • Expression parsing edge cases covered

๐Ÿค Contributing

We welcome contributions! OmniQL is open-source and community-driven.

Areas for contribution:

  • Additional database support (CassandraDB, TimescaleDB, ClickHouse)
  • SDK implementations (Node.js, Python, Rust)
  • Documentation improvements
  • Bug fixes and performance improvements

To contribute:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ—บ๏ธ Roadmap

v2.1 (Planned)

  • Advanced JOIN operations (LATERAL, CROSS APPLY)
  • More window functions (FIRST_VALUE, LAST_VALUE, CUME_DIST)
  • Enhanced CTEs (recursive CTEs)
  • Performance optimizations

v2.2 (Planned)

  • JavaScript/TypeScript SDK
  • Python SDK
  • Query optimization hints
  • Execution plan analysis

v3.0 (Future)

  • Additional databases (CassandraDB, TimescaleDB, ClickHouse)
  • GraphQL-style nested queries
  • Query result caching
  • Real-time query monitoring

๐Ÿ’ก Want a feature? Open an issue!


๐Ÿ“„ License

MIT License - see LICENSE for details.


๐Ÿ’ฌ About

OmniQL is developed and maintained by Binary Leap Oรœ (https://binaryleap.eu).

Why we built this:

We needed a universal query abstraction for a multi-tenant database platform. Instead of keeping it proprietary, we're open-sourcing it to help the entire developer community solve the polyglot persistence challenge.

Powered by OmniQL: TenantsDB - Multi-tenant database platform


โญ Star this repo if you find it useful!

Questions? Open an issue

Documentation ยถ

Index ยถ

Constants ยถ

This section is empty.

Variables ยถ

This section is empty.

Functions ยถ

func Parse ยถ

func Parse(input string) (*models.Query, bool, error)

Parse handles OmniQL queries with : prefix Returns:

  • query: parsed AST (nil if not OmniQL)
  • isOQL: true if input had : prefix
  • error: parsing error (nil if success or not OmniQL)

Types ยถ

type Client ยถ

type Client struct {
	// contains filtered or unexported fields
}

Client wraps a database connection with OmniQL

func WrapMongo ยถ

func WrapMongo(db *mongo.Database) *Client

WrapMongo wraps a MongoDB database connection

func WrapRedis ยถ

func WrapRedis(rdb *redis.Client, tenantID string) *Client

WrapRedis wraps a Redis client connection

func WrapSQL ยถ

func WrapSQL(db *sql.DB, dbType string) *Client

WrapSQL wraps a SQL database connection (PostgreSQL or MySQL)

func (*Client) Query ยถ

func (c *Client) Query(input string) ([]map[string]any, error)

Query executes an OmniQL or native query and returns results

func (*Client) SetContext ยถ

func (c *Client) SetContext(ctx context.Context)

SetContext sets the context for database operations

func (*Client) SetTenant ยถ

func (c *Client) SetTenant(tenantID string)

SetTenant sets the tenant ID for multi-tenant queries

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL