graph_d 1.3.2

A native graph database implementation in Rust with built-in JSON support and SQLite-like simplicity
Documentation
//! GQL (Graph Query Language) implementation for Graph_D.
//!
//! This module provides a complete GQL parser and executor following the ISO/IEC 39075:2024 standard.
//! GQL is the standardized query language for property graphs, offering SQL-like syntax with
//! graph pattern matching capabilities.

pub mod ast;
pub mod error;
pub mod executor;
pub mod lexer;
pub mod parser;

#[cfg(test)]
mod tests;

pub use ast::*;
pub use error::{GqlError, GqlResult};
pub use executor::GqlExecutor;
pub use lexer::Lexer;
pub use parser::Parser;

use crate::Graph;
use std::cell::RefCell;

/// Main GQL interface for executing queries against a graph database.
///
/// The GQL interface uses interior mutability via `RefCell` to support both
/// read operations (MATCH, RETURN) and write operations (CREATE, INSERT).
///
/// # Example
///
/// ```rust
/// use graph_d::{Graph, gql::Gql};
/// use std::cell::RefCell;
///
/// # fn main() -> graph_d::Result<()> {
/// let graph = RefCell::new(Graph::new()?);
/// let gql = Gql::new(&graph);
///
/// // Execute a simple query
/// let results = gql.execute("MATCH (n) RETURN n");
/// # Ok(())
/// # }
/// ```
pub struct Gql<'a> {
    #[allow(dead_code)]
    graph: &'a RefCell<Graph>,
    executor: GqlExecutor<'a>,
}

impl<'a> Gql<'a> {
    /// Create a new GQL interface for the given graph.
    ///
    /// The graph must be wrapped in a `RefCell` to allow both read and write operations.
    pub fn new(graph: &'a RefCell<Graph>) -> Self {
        Self {
            graph,
            executor: GqlExecutor::new(graph),
        }
    }

    /// Execute a GQL query and return the results.
    pub fn execute(&self, query: &str) -> GqlResult<QueryResult> {
        let mut lexer = Lexer::new(query);
        let tokens = lexer.tokenize()?;

        let mut parser = Parser::new(tokens);
        let ast = parser.parse()?;

        self.executor.execute(ast)
    }

    /// Parse a GQL query without executing it (useful for validation).
    pub fn parse(&self, query: &str) -> GqlResult<GqlStatement> {
        let mut lexer = Lexer::new(query);
        let tokens = lexer.tokenize()?;

        let mut parser = Parser::new(tokens);
        parser.parse()
    }
}

/// Represents the result of a GQL query execution.
#[derive(Debug, Clone)]
pub struct QueryResult {
    /// The column names returned by the query
    pub columns: Vec<String>,
    /// The data rows, where each row contains values corresponding to the columns
    pub rows: Vec<Vec<QueryValue>>,
}

/// Represents a value that can be returned from a GQL query.
#[derive(Debug, Clone, PartialEq)]
pub enum QueryValue {
    /// Null value representation
    Null,
    /// Boolean value (true/false)
    Boolean(bool),
    /// 64-bit signed integer value
    Integer(i64),
    /// 64-bit floating point value
    Float(f64),
    /// String value
    String(String),
    /// Graph node with ID, labels, and properties
    Node {
        /// Unique node identifier
        id: u64,
        /// Node labels/types
        labels: Vec<String>,
        /// Node properties as key-value pairs
        properties: std::collections::HashMap<String, serde_json::Value>,
    },
    /// Graph relationship with source, target, type, and properties
    Relationship {
        /// Unique relationship identifier
        id: u64,
        /// Source node ID
        from_id: u64,
        /// Target node ID
        to_id: u64,
        /// Relationship type
        rel_type: String,
        /// Relationship properties as key-value pairs
        properties: std::collections::HashMap<String, serde_json::Value>,
    },
    /// Path through the graph (sequence of nodes and relationships)
    Path(Vec<QueryValue>),
    /// List of values
    List(Vec<QueryValue>),
}

impl QueryResult {
    /// Create a new empty query result.
    pub fn new() -> Self {
        Self {
            columns: Vec::new(),
            rows: Vec::new(),
        }
    }

    /// Add a column to the result.
    pub fn add_column(&mut self, name: String) {
        self.columns.push(name);
    }

    /// Add a row to the result.
    pub fn add_row(&mut self, row: Vec<QueryValue>) {
        self.rows.push(row);
    }

    /// Get the number of rows in the result.
    pub fn row_count(&self) -> usize {
        self.rows.len()
    }

    /// Check if the result is empty.
    pub fn is_empty(&self) -> bool {
        self.rows.is_empty()
    }
}

impl Default for QueryResult {
    fn default() -> Self {
        Self::new()
    }
}