{"id":29624923,"url":"https://github.com/excalibase/excalibase-graphql","last_synced_at":"2026-02-27T01:30:54.396Z","repository":{"id":304128654,"uuid":"990166231","full_name":"excalibase/excalibase-graphql","owner":"excalibase","description":"Excalibase GraphQL instantly turns your database into a GraphQL API. Built with Spring Boot, it supports schema discovery, subscriptions, and type handling — no manual resolvers needed.","archived":false,"fork":false,"pushed_at":"2026-01-21T18:48:01.000Z","size":1690,"stargazers_count":28,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-01-22T07:08:15.457Z","etag":null,"topics":["api","api-automation","api-generator","code-generation","database-to-graphql","developer-tools","graphql","graphql-server","java","postgres","postgresql","postgresql-database","spring","spring-boot","springboot","sql"],"latest_commit_sha":null,"homepage":"https://excalibase.github.io/excalibase-graphql/","language":"Groovy","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/excalibase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-25T16:29:13.000Z","updated_at":"2026-01-21T18:48:06.000Z","dependencies_parsed_at":"2025-07-11T11:05:18.322Z","dependency_job_id":"f0cadb1e-ffe4-4388-a311-d88c9dbe1ada","html_url":"https://github.com/excalibase/excalibase-graphql","commit_stats":null,"previous_names":["excalibase/excalibase-graphql"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/excalibase/excalibase-graphql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/excalibase%2Fexcalibase-graphql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/excalibase%2Fexcalibase-graphql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/excalibase%2Fexcalibase-graphql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/excalibase%2Fexcalibase-graphql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/excalibase","download_url":"https://codeload.github.com/excalibase/excalibase-graphql/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/excalibase%2Fexcalibase-graphql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29880676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T23:51:21.483Z","status":"ssl_error","status_checked_at":"2026-02-26T23:50:46.793Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-automation","api-generator","code-generation","database-to-graphql","developer-tools","graphql","graphql-server","java","postgres","postgresql","postgresql-database","spring","spring-boot","springboot","sql"],"created_at":"2025-07-21T06:03:05.549Z","updated_at":"2026-02-27T01:30:54.382Z","avatar_url":"https://github.com/excalibase.png","language":"Groovy","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Excalibase GraphQL\n[![CI](https://github.com/excalibase/excalibase-graphql/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/excalibase/excalibase-graphql/actions/workflows/ci.yml)\n[![E2E Tests](https://github.com/excalibase/excalibase-graphql/actions/workflows/e2e.yml/badge.svg?branch=main)](https://github.com/excalibase/excalibase-graphql/actions/workflows/e2e.yml)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Java Version](https://img.shields.io/badge/Java-21+-orange.svg)](https://openjdk.java.net/)\n[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.0-brightgreen.svg)](https://spring.io/projects/spring-boot)\n[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-15+-blue.svg)](https://www.postgresql.org/)\n\n## 🚀 Overview\n\nExcalibase GraphQL is a powerful Spring Boot application that **automatically generates GraphQL schemas from your existing database tables**. It eliminates the need for manual schema definition and provides instant GraphQL APIs with advanced features like cursor-based pagination, relationship resolution, and comprehensive CRUD operations.\n\n### ✨ Current Features\n- **🔄 Automatic Schema Generation**: Creates GraphQL types from PostgreSQL tables\n- **📊 Rich Querying**: Filtering, sorting, and pagination out of the box\n- **🗓️ Enhanced Date/Time Filtering**: Comprehensive date and timestamp operations with multiple format support\n- **🔍 Advanced Filter Types**: StringFilter, IntFilter, FloatFilter, BooleanFilter, DateTimeFilter with operators like eq, neq, gt, gte, lt, lte, in, notIn, isNull, isNotNull\n- **🎯 Custom PostgreSQL Types**: Full support for custom enum and composite types with automatic GraphQL mapping\n- **📄 Enhanced PostgreSQL Data Types**: JSON/JSONB with **direct GraphQL object support** 🆕, arrays with **proper PGArray mapping** 🆕, network types (INET, CIDR), enhanced datetime, binary, and XML support  \n- **🔗 Relationship Resolution**: Automatic foreign key relationship handling\n- **🛠️ CRUD Operations**: Full create, read, update, delete support with **composite key support**\n- **🔑 Composite Primary Keys**: Complete support for tables with multi-column primary keys\n- **🔄 Composite Foreign Keys**: Seamless handling of multi-column foreign key relationships\n- **📄 Cursor Pagination**: Relay-spec compatible connection queries\n- **⚡ N+1 Prevention**: Built-in query optimization\n- **🔧 OR Operations**: Complex logical conditions with nested filtering\n- **🛡️ GraphQL Security**: Query depth and complexity limiting following GraphQL.org best practices\n- **🐳 Docker Support**: Container images with Docker Compose setup\n- **🔄 CI/CD Pipeline**: GitHub Actions integration with automated testing\n\n### ✅ Real-Time Subscriptions\n- **🔄 GraphQL Subscriptions** - Real-time data updates via WebSocket connections\n- **⚡ Change Data Capture (CDC)** - PostgreSQL logical replication for instant notifications\n- **📡 Table Subscriptions** - Subscribe to INSERT, UPDATE, DELETE operations\n- **💓 Connection Management** - WebSocket heartbeat and automatic reconnection\n- **🛡️ Error Handling** - Graceful error recovery and client notification\n\n### 🚧 Planned Features\n\n- [ ] **Schema Caching** - Performance optimization for large schemas\n- [ ] **MySQL Support** - Complete MySQL database integration\n- [ ] **Oracle Support** - Add Oracle database compatibility\n- [ ] **SQL Server Support** - Microsoft SQL Server implementation\n- [ ] **Custom Directives** - Extended GraphQL functionality\n- [ ] **Authentication/Authorization** - Role-based access control\n\n## 📋 Quick Start\n\n### Prerequisites\n\n- Java 21+\n- Maven 3.8+\n- PostgreSQL 15+\n\n### Installation\n\n#### Option 1: Docker (Recommended)\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/excalibase/excalibase-graphql.git\n   cd excalibase-graphql\n   ```\n\n2. **Configure your database**\n\n   Edit `docker-compose.yml` or set environment variables:\n   ```yaml\n   environment:\n     - DB_HOST=your_postgres_host\n     - DB_PORT=5432\n     - DB_NAME=your_database\n     - DB_USERNAME=your_username\n     - DB_PASSWORD=your_password\n     - DATABASE_SCHEMA=your_schema\n     # Optional CDC configuration (defaults shown)\n     - APP_CDC_ENABLED=true\n     - APP_CDC_CREATE_SLOT_IF_NOT_EXISTS=true\n     - APP_CDC_CREATE_PUBLICATION_IF_NOT_EXISTS=true\n   ```\n\n3. **Run with Docker Compose**\n   ```bash\n   docker-compose up -d\n   ```\n\n4. **Access GraphQL endpoint**\n\n   Your GraphQL endpoint will be available at: `http://localhost:10000/graphql`\n\n#### Option 2: Local Development\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/excalibase/excalibase-graphql.git\n   cd excalibase-graphql\n   ```\n\n2. **Configure your database**\n\n   Edit `src/main/resources/application.yaml`:\n   ```yaml\n   spring:\n     datasource:\n       url: jdbc:postgresql://localhost:5432/your_database\n       username: your_username\n       password: your_password\n   \n   app:\n     allowed-schema: your_schema\n     database-type: postgres\n   ```\n\n3. **Build and run**\n   ```bash\n   mvn clean install\n   mvn spring-boot:run\n   ```\n\n4. **Access GraphQL endpoint**\n\n   Your GraphQL endpoint will be available at: `http://localhost:10000/graphql`\n\n## 🐳 Docker Support\n\n### Docker Compose Setup\n\nThe project includes a `docker-compose.yml` file for easy setup:\n\n```yaml\nversion: '3.8'\nservices:\n  app:\n    build: .\n    ports:\n      - \"10000:10000\"\n    environment:\n      - DB_HOST=postgres\n      - DB_PORT=5432\n      - DB_NAME=your_database\n      - DB_USERNAME=your_username\n      - DB_PASSWORD=your_password\n      - DATABASE_SCHEMA=your_schema\n      # CDC Configuration (optional - defaults shown)\n      - APP_CDC_ENABLED=true\n      - APP_CDC_SLOT_NAME=cdc_slot\n      - APP_CDC_PUBLICATION_NAME=cdc_publication\n      - APP_CDC_CREATE_SLOT_IF_NOT_EXISTS=true\n      - APP_CDC_CREATE_PUBLICATION_IF_NOT_EXISTS=true\n    depends_on:\n      - postgres\n  \n  postgres:\n    image: postgres:15-alpine\n    environment:\n      - POSTGRES_DB=your_database\n      - POSTGRES_USER=your_username\n      - POSTGRES_PASSWORD=your_password\n    ports:\n      - \"5432:5432\"\n```\n\n### Available Docker Commands\n\n**Production Setup (Easy for Users):**\n```bash\n# Start all services\ndocker-compose up -d\n\n# View logs\ndocker-compose logs -f excalibase-app\n\n# Stop all services\ndocker-compose down\n```\n\n**E2E Testing Setup:**\n```bash\n# Use Makefile for complete testing workflow\nmake e2e           # Complete e2e test (build image + test + cleanup)\nmake dev           # Start services for development\nmake test-only     # Run tests against running services\nmake clean         # Stop and cleanup\n```\n\n**Development:**\n```bash\n# Rebuild and restart\ndocker-compose up -d --build\n\n# Run tests in container (production setup)\ndocker-compose exec excalibase-app mvn test\n\n# Run tests in container (using make command)\nmake test-only\n\n# Access application shell\ndocker-compose exec excalibase-app /bin/bash\n```\n\n### Environment Variables\n\nConfigure the application using environment variables:\n\n| Variable | Description | Default | Example |\n|----------|-------------|---------|---------|\n| `SPRING_DATASOURCE_URL` | JDBC connection URL | `jdbc:postgresql://localhost:5432/hana` | `jdbc:postgresql://postgres:5432/hana` |\n| `SPRING_DATASOURCE_USERNAME` | Database username | `hana001` | `hana001` |\n| `SPRING_DATASOURCE_PASSWORD` | Database password | `password123` | `password123` |\n| `APP_ALLOWED_SCHEMA` | Database schema to introspect | `hana` | `hana` |\n| `APP_DATABASE_TYPE` | Database type | `postgres` | `postgres` |\n| `SERVER_PORT` | Application port | `10000` | `10000` |\n| `APP_CDC_ENABLED` | Enable CDC for real-time subscriptions | `true` | `true` |\n| `APP_CDC_SLOT_NAME` | Replication slot name | `cdc_slot` | `cdc_slot` |\n| `APP_CDC_PUBLICATION_NAME` | Publication name | `cdc_publication` | `cdc_publication` |\n| `APP_CDC_CREATE_SLOT_IF_NOT_EXISTS` | Auto-create replication slot | `true` | `true` |\n| `APP_CDC_CREATE_PUBLICATION_IF_NOT_EXISTS` | Auto-create publication | `true` | `true` |\n\n**Legacy Environment Variables (Docker Compose):**\n- `DB_HOST`, `DB_PORT`, `DB_NAME` - Still supported for backward compatibility\n\n## 🧪 End-to-End Testing\n\nExcalibase GraphQL includes a comprehensive E2E testing suite that validates the complete GraphQL API using Docker Compose with unique ports to avoid conflicts.\n\n### Quick Start E2E Testing\n\n```bash\n# Run complete E2E test suite (builds, starts services, runs tests, cleans up)\nmake e2e\n\n# Start development environment (keeps services running)\nmake dev\n\n# Run only tests (against already running services)\nmake test-only\n\n# See all available commands\nmake help\n```\n\n\u003e **Note**: We use a `Makefile` for streamlined development workflow. All e2e testing operations are handled through `make` commands for consistency and ease of use.\n\n### E2E Test Configuration\n\nThe E2E setup uses unique ports to avoid conflicts:\n- **GraphQL API**: `http://localhost:10001/graphql` (unique port 10001)\n- **PostgreSQL**: `localhost:5433` (unique port 5433)\n\n### E2E Test Coverage\n\nThe test suite includes **25+ comprehensive tests** covering:\n\n#### **Schema \u0026 Introspection**\n- ✅ GraphQL schema introspection\n- ✅ Query and Mutation type validation\n- ✅ Field availability verification\n\n#### **Basic GraphQL Operations**\n- ✅ Query all customers\n- ✅ Filtering with WHERE clauses\n- ✅ OR operations with multiple conditions\n- ✅ Pagination (limit, offset)\n- ✅ Ordering (ASC/DESC)\n\n#### **Enhanced PostgreSQL Types** 🆕\n- ✅ JSON/JSONB column operations\n- ✅ Array types (INTEGER[], TEXT[])\n- ✅ Enhanced datetime (TIMESTAMPTZ, TIMETZ, INTERVAL)\n- ✅ Network types (INET, CIDR, MACADDR)\n- ✅ Binary and XML types\n\n#### **Relationships \u0026 Views**\n- ✅ Foreign key relationship traversal\n- ⚠️ **Important**: Include foreign key fields in queries for relationships to work\n- ✅ PostgreSQL views (read-only queries)\n- ✅ Materialized views\n- ✅ Complex relationship queries\n\n#### **CRUD Operations**\n- ✅ Create mutations\n- ✅ Update mutations\n- ✅ Data validation\n\n#### **Advanced Features**\n- ✅ Cursor-based pagination (connections)\n- ✅ Complex filtering (date ranges, string operations)\n- ✅ Boolean and array filters\n- ✅ Error handling validation\n- ✅ Performance testing (\u003c 1000ms response times)\n\n### Sample Data \u0026 Schema\n\nThe application includes comprehensive sample data in the `hana` schema:\n\n#### **Demo Tables (Great for Documentation \u0026 Learning)**\n```sql\n-- Blog-style schema for demos and learning\nusers: 3 sample users (john_doe, jane_smith, bob_wilson)\nposts: 4 sample blog posts with rich content\ncomments: 4 sample comments showing relationships\n```\n\n#### **Test Tables (Comprehensive Testing Coverage)**\n```sql\n-- Customer table (12 records)\ncustomer: MARY SMITH, PATRICIA JOHNSON, etc.\n\n-- Enhanced types table (3 records with full PostgreSQL type coverage)\nenhanced_types: JSON objects, arrays, network addresses, XML documents\n\n-- Orders table (5 records with foreign key relationships)\norders: Realistic order data linking to customers\n```\n\n#### **Views \u0026 Advanced Features**\n```sql\n-- Read-only views\nactive_customers: Filtered view of active customers\nenhanced_types_summary: Materialized view with JSON extraction\nposts_with_authors: Blog posts joined with author information\n```\n\n### Available Make Commands\n\n```bash\n# Main commands\nmake e2e            # Complete e2e test (build + test + cleanup)\nmake dev            # Start services for development (no cleanup)\nmake test-only      # Run tests against running services\nmake clean          # Stop services and cleanup\n\n# Development workflow\nmake test-quick     # Quick test (skip build)\nmake restart        # Restart services\nmake rebuild        # Full rebuild and restart\n\n# Monitoring and debugging\nmake logs           # Show all service logs\nmake logs-app       # Show application logs only\nmake status         # Show service status\n\n# Database operations\nmake db-shell       # Connect to PostgreSQL shell\nmake db-reset       # Reset database with fresh data\n\n# Sample queries (both demo and test data)\nmake query-users           # Query demo users table\nmake query-posts           # Query demo posts with relationships\nmake query-customers       # Query test customer data\nmake query-enhanced-types  # Query enhanced PostgreSQL types\nmake query-schema          # Query GraphQL schema introspection\n```\n\n### Manual Testing After E2E\n\nIf you use `make dev`, you can manually explore the API:\n\n```bash\n# Visit GraphQL endpoint in browser\nmake open-api\n\n# Test with built-in demo queries\nmake query-users            # Simple user data\nmake query-posts            # Blog posts with relationships\n\n# Test with comprehensive test data  \nmake query-customers        # Customer data with advanced filtering\nmake query-enhanced-types   # PostgreSQL advanced types (JSON, arrays, etc.)\n\n# Or test with curl directly\ncurl -X POST http://localhost:10001/graphql \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\": \"{ users { id username email first_name } }\"}'\n\n# Cleanup when done\nmake clean\n```\n\n### Sample GraphQL Queries\n\n**Demo Data Queries (Great for Learning):**\n```graphql\n# Query blog users\n{\n  users {\n    id\n    username\n    email\n    first_name\n    last_name\n  }\n}\n\n# Query posts with author relationships\n{\n  posts {\n    id\n    title\n    published\n    author_id\n    users {\n      username\n      first_name\n      last_name\n    }\n  }\n}\n\n# Query comments with nested relationships\n{\n  comments {\n    id\n    content\n    post_id\n    posts {\n      title\n      users {\n        username\n      }\n    }\n  }\n}\n```\n\n**Test Data Queries (Advanced Features):**\n```graphql\n# Query customers with filtering\n{\n  customer(where: { active: { eq: true } }) {\n    customer_id\n    first_name\n    last_name\n    email\n  }\n}\n\n# Query enhanced PostgreSQL types\n{\n  enhanced_types {\n    id\n    name\n    json_col\n    jsonb_col\n    int_array\n    text_array\n    timestamptz_col\n    inet_col\n  }\n}\n\n# Query with relationships\n{\n  orders {\n    order_id\n    total_amount\n    customer_id\n    customer {\n      first_name\n      last_name\n      email\n    }\n  }\n}\n```\n\n## 🔑 Composite Key Support\n\nExcalibase GraphQL provides **complete support for composite primary keys** and **composite foreign keys**, following GraphQL industry best practices with input objects and structured returns.\n\n### 🎯 **Key Features**\n\n- **✅ Multi-Column Primary Keys**: Tables with composite primary keys fully supported\n- **✅ Multi-Column Foreign Keys**: Composite foreign key relationships automatically resolved\n- **✅ Industry Standard API**: Uses input objects for mutations (not individual parameters)\n- **✅ Rich Return Types**: Delete operations return the deleted object (following GraphQL.org recommendations)\n- **✅ Comprehensive CRUD**: Full Create, Read, Update, Delete support for composite keys\n- **✅ Relationship Navigation**: Automatic GraphQL relationship traversal\n\n### 📋 **Sample Database Schema**\n\n```sql\n-- Parent table with composite primary key\nCREATE TABLE parent_table (\n    parent_id1 INTEGER NOT NULL,\n    parent_id2 INTEGER NOT NULL,\n    name VARCHAR(255),\n    PRIMARY KEY (parent_id1, parent_id2)\n);\n\n-- Order items with composite primary key\nCREATE TABLE order_items (\n    order_id INTEGER NOT NULL REFERENCES orders(order_id),\n    product_id INTEGER NOT NULL REFERENCES products(product_id),\n    quantity INTEGER NOT NULL,\n    price DECIMAL(10,2),\n    PRIMARY KEY (order_id, product_id)\n);\n\n-- Child table with composite foreign key\nCREATE TABLE child_table (\n    child_id INTEGER PRIMARY KEY,\n    parent_id1 INTEGER NOT NULL,\n    parent_id2 INTEGER NOT NULL,\n    description TEXT,\n    FOREIGN KEY (parent_id1, parent_id2) REFERENCES parent_table(parent_id1, parent_id2)\n);\n```\n\n### 🚀 **GraphQL Operations**\n\n#### **Create with Composite Keys**\n```graphql\n# Create order item with composite primary key\nmutation {\n  createOrder_items(input: {\n    order_id: 3\n    product_id: 2\n    quantity: 5\n    price: 199.99\n  }) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n\n# Create child with composite foreign key\nmutation {\n  createChild_table(input: {\n    child_id: 10\n    parent_id1: 1\n    parent_id2: 2\n    description: \"Child with composite FK\"\n  }) {\n    child_id\n    parent_id1\n    parent_id2\n    description\n  }\n}\n```\n\n#### **Update with Composite Keys**\n```graphql\n# Update requires all primary key parts\nmutation {\n  updateOrder_items(input: {\n    order_id: 3          # Required: part of composite PK\n    product_id: 2        # Required: part of composite PK\n    quantity: 10         # Updated field\n    price: 299.99        # Updated field\n  }) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n```\n\n#### **Delete with Composite Keys**\n```graphql\n# Delete returns the deleted object (GraphQL industry standard)\nmutation {\n  deleteOrder_items(input: {\n    order_id: 3\n    product_id: 2\n  }) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n\n# Response includes the deleted record\n{\n  \"data\": {\n    \"deleteOrder_items\": {\n      \"order_id\": 3,\n      \"product_id\": 2,\n      \"quantity\": 10,\n      \"price\": 299.99\n    }\n  }\n}\n```\n\n#### **Query with Composite Key Filtering**\n```graphql\n# Filter by specific composite key\n{\n  order_items(where: {\n    order_id: { eq: 3 }\n    product_id: { eq: 2 }\n  }) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n\n# Complex filtering with OR conditions\n{\n  order_items(where: {\n    or: [\n      { order_id: { eq: 1 }, product_id: { eq: 1 } },\n      { order_id: { eq: 2 }, product_id: { eq: 3 } }\n    ]\n  }) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n```\n\n#### **Relationship Navigation**\n```graphql\n# Navigate relationships through composite foreign keys\n{\n  child_table {\n    child_id\n    parent_id1\n    parent_id2\n    description\n    parent_table {          # Automatic relationship resolution\n      parent_id1\n      parent_id2\n      name\n    }\n  }\n}\n```\n\n#### **Bulk Operations**\n```graphql\n# Bulk create with composite keys\nmutation {\n  createManyOrder_itemss(inputs: [\n    { order_id: 4, product_id: 1, quantity: 2, price: 99.98 },\n    { order_id: 4, product_id: 2, quantity: 1, price: 79.99 }\n  ]) {\n    order_id\n    product_id\n    quantity\n    price\n  }\n}\n```\n\n### 📊 **Schema Generation**\n\nThe GraphQL schema automatically generates appropriate input and output types:\n\n```graphql\n# Auto-generated input types for composite keys\ninput Order_itemsCreateInput {\n  order_id: Int!        # Required: part of composite PK\n  product_id: Int!      # Required: part of composite PK\n  quantity: Int!\n  price: Float!\n}\n\ninput Order_itemsUpdateInput {\n  order_id: Int!        # Required: part of composite PK\n  product_id: Int!      # Required: part of composite PK\n  quantity: Int\n  price: Float\n}\n\ninput Order_itemsDeleteInput {\n  order_id: Int!        # Required: part of composite PK\n  product_id: Int!      # Required: part of composite PK\n}\n\n# Auto-generated mutation fields\ntype Mutation {\n  createOrder_items(input: Order_itemsCreateInput!): Order_items\n  updateOrder_items(input: Order_itemsUpdateInput!): Order_items\n  deleteOrder_items(input: Order_itemsDeleteInput!): Order_items  # Returns deleted object\n  createManyOrder_itemss(inputs: [Order_itemsCreateInput!]!): [Order_items!]!\n}\n```\n\n### ✅ **Industry Best Practices**\n\nOur composite key implementation follows **GraphQL.org recommendations**:\n\n- **Input Objects**: All mutations use structured input objects (not individual parameters)\n- **Rich Returns**: Delete operations return the deleted object for UI updates and confirmation\n- **Type Safety**: Strongly typed GraphQL schema with proper validation\n- **Relationship Support**: Automatic foreign key relationship traversal\n- **Error Handling**: Comprehensive validation with clear error messages\n\n### Dependencies\n\nThe E2E tests require:\n- **Make** (usually pre-installed on macOS/Linux)\n- **Docker** and **Docker Compose**\n- **curl** (for HTTP requests)\n- **jq** (for JSON processing)\n- **Maven** (for building the application)\n\nUse `make check-deps` to verify all dependencies are installed, or `make install-deps` on macOS to auto-install missing tools.\n\n## 🔄 Real-Time Subscriptions\n\nExcalibase GraphQL provides **real-time data updates** through GraphQL subscriptions powered by PostgreSQL Change Data Capture (CDC) and WebSocket connections.\n\n### 🚀 Key Features\n\n\u003cdiv class=\"feature-grid\"\u003e\n\u003cdiv class=\"feature-card\"\u003e\n\u003ch3\u003e⚡ Change Data Capture\u003c/h3\u003e\n\u003cp\u003eUses PostgreSQL logical replication to capture INSERT, UPDATE, DELETE operations in real-time without polling.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"feature-card\"\u003e\n\u003ch3\u003e📡 WebSocket Transport\u003c/h3\u003e\n\u003cp\u003eStandards-compliant \u003ccode\u003egraphql-transport-ws\u003c/code\u003e protocol for reliable WebSocket connections.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"feature-card\"\u003e\n\u003ch3\u003e💓 Connection Management\u003c/h3\u003e\n\u003cp\u003eAutomatic heartbeat, reconnection, and graceful error handling for production reliability.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"feature-card\"\u003e\n\u003ch3\u003e🎯 Table-Specific Streams\u003c/h3\u003e\n\u003cp\u003eSubscribe to changes for specific tables with automatic data transformation and column mapping.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n### 📊 GraphQL Subscription Schema\n\nExcalibase automatically generates subscription types for each table:\n\n```graphql\n# Auto-generated subscription type\ntype Subscription {\n  # Subscribe to customer table changes\n  customerChanges: CustomerSubscriptionEvent!\n  \n  # Subscribe to orders table changes  \n  ordersChanges: OrdersSubscriptionEvent!\n  \n  # Subscribe to any table changes\n  usersChanges: UsersSubscriptionEvent!\n}\n\n# Event structure for table changes\ntype CustomerSubscriptionEvent {\n  table: String!           # Table name\n  schema: String!          # Database schema\n  operation: String!       # INSERT, UPDATE, DELETE, HEARTBEAT, ERROR\n  timestamp: String!       # ISO 8601 timestamp\n  lsn: String             # PostgreSQL Log Sequence Number\n  data: CustomerData      # Table row data (structure varies by operation)\n  error: String           # Error message (null if no error)\n}\n\n# Data payload varies by operation type\ntype CustomerData {\n  # For INSERT/DELETE: direct column values\n  customer_id: Int\n  first_name: String\n  last_name: String\n  email: String\n  \n  # For UPDATE: includes old and new values\n  old: Customer           # Previous values\n  new: Customer           # Updated values\n}\n```\n\n### 🔌 WebSocket Connection Setup\n\n**JavaScript/TypeScript (graphql-ws client):**\n```javascript\nimport { createClient } from 'graphql-ws';\n\nconst client = createClient({\n  url: 'ws://localhost:10000/graphql-ws',\n  connectionParams: {\n    // Add authentication headers if needed\n  }\n});\n\n// Subscribe to customer changes\nconst subscription = client.iterate({\n  query: `\n    subscription {\n      customerChanges {\n        table\n        operation\n        timestamp\n        data {\n          customer_id\n          first_name\n          last_name\n          email\n        }\n        error\n      }\n    }\n  `\n});\n\nfor await (const event of subscription) {\n  console.log('Customer change:', event.data.customerChanges);\n  \n  switch (event.data.customerChanges.operation) {\n    case 'INSERT':\n      console.log('New customer:', event.data.customerChanges.data);\n      break;\n    case 'UPDATE':\n      console.log('Updated customer:', {\n        old: event.data.customerChanges.data.old,\n        new: event.data.customerChanges.data.new\n      });\n      break;\n    case 'DELETE':\n      console.log('Deleted customer:', event.data.customerChanges.data);\n      break;\n    case 'HEARTBEAT':\n      console.log('Connection alive');\n      break;\n    case 'ERROR':\n      console.error('Subscription error:', event.data.customerChanges.error);\n      break;\n  }\n}\n```\n\n**curl Example (WebSocket simulation):**\n```bash\n# Connect to WebSocket endpoint\nwscat -c ws://localhost:10000/graphql-ws -s graphql-transport-ws\n\n# Send connection init\n{\"type\":\"connection_init\"}\n\n# Send subscription\n{\n  \"type\": \"subscribe\",\n  \"id\": \"customer-sub-1\",\n  \"payload\": {\n    \"query\": \"subscription { customerChanges { table operation timestamp data { customer_id first_name last_name email } error } }\"\n  }\n}\n\n# You'll receive real-time events like:\n{\n  \"type\": \"next\",\n  \"id\": \"customer-sub-1\", \n  \"payload\": {\n    \"data\": {\n      \"customerChanges\": {\n        \"table\": \"customer\",\n        \"operation\": \"INSERT\",\n        \"timestamp\": \"2024-01-15T10:30:45.123Z\",\n        \"data\": {\n          \"customer_id\": 123,\n          \"first_name\": \"John\",\n          \"last_name\": \"Doe\", \n          \"email\": \"john.doe@example.com\"\n        },\n        \"error\": null\n      }\n    }\n  }\n}\n```\n\n### 🔧 Configuration\n\n**Database Setup (Required for CDC):**\n```sql\n-- Enable logical replication (requires superuser)\nALTER SYSTEM SET wal_level = logical;\nALTER SYSTEM SET max_replication_slots = 10;\nALTER SYSTEM SET max_wal_senders = 10;\n\n-- Restart PostgreSQL server, then create publication\nCREATE PUBLICATION cdc_publication FOR ALL TABLES;\n\n-- Grant replication permissions to your user\nALTER USER your_username REPLICATION;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO your_username;\n```\n\n**Application Configuration:**\n```yaml\n# WebSocket configuration\nspring:\n  websocket:\n    enabled: true\n    heartbeat-interval: 30s\n\n# CDC configuration\napp:\n  cdc:\n    enabled: true                              # Enable CDC (Change Data Capture) for real-time subscriptions (default: true)\n    slot-name: \"cdc_slot\"                      # Replication slot name (default: cdc_slot)\n    publication-name: \"cdc_publication\"        # Publication name (default: cdc_publication)\n    create-slot-if-not-exists: true            # Create replication slot if it doesn't exist (default: true)\n    create-publication-if-not-exists: true     # Create publication if it doesn't exist (default: true)\n    heartbeat-interval: 30                     # Heartbeat interval in seconds\n```\n\n### 🚀 Automatic CDC Setup\n\nExcalibase GraphQL now features **automatic CDC setup** for seamless deployment:\n\n**New Auto-Configuration Features:**\n- **`create-slot-if-not-exists: true`** - Automatically creates PostgreSQL replication slots\n- **`create-publication-if-not-exists: true`** - Automatically creates publications for all tables\n- **Zero-configuration deployment** - Works out-of-the-box for development environments\n- **Production-safe** - Handles existing configurations gracefully without conflicts\n\n**Benefits:**\n- ✅ **No Manual Setup Required** - Skip complex PostgreSQL CDC configuration\n- ✅ **Development Friendly** - Instant setup for local development  \n- ✅ **Error Resilient** - Graceful handling of existing slots/publications\n- ✅ **Multi-Environment** - Same configuration works across dev/staging/prod\n\n### 📈 Performance \u0026 Scalability\n\n- **Low Latency**: ~50ms from database change to WebSocket delivery\n- **High Throughput**: Handles 1000+ concurrent subscriptions\n- **Memory Efficient**: Uses reactive streams with backpressure handling\n- **Connection Pooling**: Shared CDC connection across all table subscriptions\n- **Graceful Degradation**: Automatic error recovery and reconnection\n\n### 🛡️ Production Considerations\n\n**Security:**\n- WebSocket connections should use WSS (secure WebSocket) in production\n- Implement authentication/authorization for subscription access\n- Rate limiting for subscription requests\n\n**Monitoring:**\n- Monitor CDC lag using PostgreSQL replication slots\n- Track WebSocket connection counts and subscription metrics\n- Alert on CDC service failures or high latency\n\n**High Availability:**\n- CDC service automatically reconnects on connection failures\n- WebSocket clients should implement reconnection logic\n- Consider PostgreSQL replication for database redundancy\n\n### 🧪 Testing Subscriptions\n\nUse the E2E test suite to validate subscription functionality:\n\n```bash\n# Start development environment with subscriptions\nmake dev\n\n# Test WebSocket connectivity\nwscat -c ws://localhost:10001/graphql-ws -s graphql-transport-ws\n\n# Run subscription-specific tests\ncd modules/excalibase-graphql-postgres\nmvn test -Dtest=PostgresDatabaseSubscriptionImplementTest\n\n# Test CDC service functionality\nmvn test -Dtest=CDCServiceTest\n```\n\n## 🔄 CI/CD Pipeline\n\n### GitHub Actions Integration\n\nThe project includes automated CI/CD with GitHub Actions:\n\n#### **Build \u0026 Test Pipeline**\n- ✅ **Automated Testing**: Runs all 41+ test methods on every push\n- ✅ **Multi-Java Support**: Tests against Java 17, 21\n- ✅ **PostgreSQL Integration**: Uses PostgreSQL service for integration tests\n- ✅ **Security Scanning**: Automated dependency vulnerability checks\n- ✅ **Code Coverage**: Generates and reports test coverage metrics\n\n#### **Docker Pipeline**\n- ✅ **Container Building**: Builds Docker images for each release\n- ✅ **Multi-architecture**: Supports AMD64 and ARM64 architectures\n- ✅ **Registry Publishing**: Pushes images to container registries\n- ✅ **Automated Tagging**: Tags images with version and latest\n\n#### **Quality Gates**\n- ✅ **All tests must pass** before merge\n- ✅ **Code coverage above 90%**\n- ✅ **Security scans pass**\n- ✅ **Docker builds successfully**\n\n### Pipeline Configuration\n\nThe CI/CD pipeline runs on:\n- **Push to main**: Full pipeline with deployment\n- **Pull requests**: Build and test validation\n- **Release tags**: Docker image publishing\n- **Scheduled**: Nightly security scans\n\n## 🌟 Enhanced Filtering System\n\nExcalibase GraphQL features a modern, object-based filtering system that provides consistency with industry standards and PostgREST-style APIs:\n\n### 🎯 **Key Advantages**\n\n- **🗓️ Intelligent Date Handling**: Supports multiple date formats (`2023-12-25`, `2023-12-25 14:30:00`, ISO 8601) with automatic type conversion\n- **🔧 Rich Operator Support**: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `isNull`, `isNotNull`, `contains`, `startsWith`, `endsWith`, `like`, `ilike`\n- **🔗 Complex Logical Operations**: OR conditions with nested filtering\n- **⚡ Type-Safe**: Dedicated filter types for String, Int, Float, Boolean, and DateTime\n- **🔄 Backward Compatible**: Legacy filter syntax still supported\n- **📊 Production Ready**: 95% feature completeness with comprehensive test coverage (41+ test methods)\n- **🛡️ Security Focused**: SQL injection prevention with comprehensive security testing\n- **⚡ Performance Optimized**: Tested for large datasets (1000+ records) with sub-1s response times\n\n### 💡 **Modern Syntax Examples**\n\n**New Object-Based Syntax (Recommended):**\n```graphql\n{ \n  customer(where: { customer_id: { eq: 524 } }) {\n    customer_id\n    first_name\n    last_name\n  }\n}\n```\n\n**Date Range Filtering:**\n```graphql\n{ \n  users(where: { created_at: { gte: \"2023-01-01\", lt: \"2024-01-01\" } }) \n  { id name created_at } \n}\n```\n\n**Complex OR Conditions:**\n```graphql\n{ \n  users(or: [\n    { name: { startsWith: \"John\" } }, \n    { email: { endsWith: \"@admin.com\" } }\n  ]) { id name email } \n}\n```\n\n**Array Operations:**\n```graphql\n{ \n  users(where: { id: { in: [1, 2, 3, 4, 5] } }) \n  { id name } \n}\n```\n\n**Combined WHERE and OR:**\n```graphql\n{\n  customer(\n    where: { active: { eq: true } }\n    or: [\n      { customer_id: { lt: 10 } },\n      { customer_id: { gt: 600 } }\n    ]\n  ) { customer_id first_name last_name active }\n}\n```\n\n### 📚 **Comprehensive Documentation**\n\nFor detailed filtering documentation, examples, and migration guides, see:\n- **[GraphQL Filtering Guide](docs/filtering.md)** - Complete filtering reference\n- **[Test Coverage Documentation](docs/testing.md)** - Comprehensive test suite overview\n\n## Example Usage\n\nGiven this database table with custom PostgreSQL types:\n\n```sql\n-- Custom PostgreSQL enum and composite types\nCREATE TYPE user_status AS ENUM ('active', 'inactive', 'suspended');\nCREATE TYPE address AS (\n    street TEXT,\n    city TEXT,\n    state TEXT,\n    zip_code TEXT\n);\n\nCREATE TABLE users (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100) NOT NULL,\n    email VARCHAR(255) UNIQUE,\n    status user_status DEFAULT 'active',\n    address address,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\nCREATE TABLE posts (\n    id SERIAL PRIMARY KEY,\n    title VARCHAR(200) NOT NULL,\n    content TEXT,\n    author_id INTEGER REFERENCES users(id),\n    published_at TIMESTAMP\n);\n```\n\nYou can immediately query:\n\n```graphql\n# Get all users with custom types\nquery {\n  users {\n    id\n    name\n    email\n    status          # PostgreSQL enum type\n    address {       # PostgreSQL composite type\n      street\n      city\n      state\n      zip_code\n    }\n  }\n}\n\n# Get posts with authors\nquery {\n  posts {\n    id\n    title\n    content\n    user_id      # Foreign key required for relationship\n    users {      # Automatic relationship resolution\n      name\n      email\n    }\n  }\n}\n\n# Filtered query with pagination\nquery {\n  users(\n    name_contains: \"john\"\n    limit: 10\n    orderBy: { created_at: DESC }\n  ) {\n    id\n    name\n    email\n    created_at\n  }\n}\n\n# Cursor-based pagination\nquery {\n  usersConnection(\n    first: 10\n    orderBy: { id: ASC }\n  ) {\n    edges {\n      node {\n        id\n        name\n        email\n      }\n      cursor\n    }\n    pageInfo {\n      hasNextPage\n      endCursor\n    }\n    totalCount\n  }\n}\n\n# Enhanced filtering with new filter types\nquery {\n  users(\n    where: {\n      name: { startsWith: \"John\" }\n      email: { isNotNull: true }\n      id: { in: [1, 2, 3, 4, 5] }\n      created_at: { \n        gte: \"2023-01-01\",\n        lt: \"2024-01-01\" \n      }\n    }\n  ) {\n    id\n    name\n    email\n    created_at\n  }\n}\n\n# OR operations with enhanced filters\nquery {\n  users(\n    or: [\n      { name: { eq: \"Alice\" } },\n      { name: { eq: \"Bob\" } },\n      { email: { endsWith: \"@example.com\" } }\n    ]\n  ) {\n    id\n    name\n    email\n  }\n}\n\n# Complex date/timestamp filtering\nquery {\n  posts(\n    where: {\n      published_at: { \n        gte: \"2023-12-01 00:00:00\",\n        lt: \"2023-12-31 23:59:59\"\n      }\n      title: { contains: \"GraphQL\" }\n    }\n  ) {\n    id\n    title\n    published_at\n    users {\n      name\n    }\n  }\n}\n```\n\nAnd perform mutations:\n\n```graphql\n# Create a user with custom types\nmutation {\n  createUsers(input: {\n    name: \"Alice Johnson\"\n    email: \"alice@example.com\"\n    status: active\n    address: {\n      street: \"123 Main St\"\n      city: \"New York\"\n      state: \"NY\"\n      zip_code: \"10001\"\n    }\n  }) {\n    id\n    name\n    email\n    status\n    address {\n      street\n      city\n      state\n    }\n    created_at\n  }\n}\n\n# Update a user\nmutation {\n  updateUsers(input: {\n    id: 1\n    name: \"Alice Smith\"\n  }) {\n    id\n    name\n    email\n  }\n}\n\n# Create with relationships\nmutation {\n  createPostsWithRelations(input: {\n    title: \"Getting Started with GraphQL\"\n    content: \"GraphQL is amazing...\"\n    users_connect: { id: 1 }  # Connect to existing user\n  }) {\n    id\n    title\n    user_id    # Foreign key field\n    users {\n      name\n    }\n  }\n}\n```\n\n## Project Structure\n\n```\nsrc/main/java/io/github/excalibase/\n├── annotation/           # @ExcalibaseService for database-specific implementations\n├── config/              # Spring configuration classes\n├── constant/            # Constants and enums\n├── controller/          # REST controllers (GraphQL endpoint)\n├── exception/           # Custom exceptions\n├── model/               # Data models (TableInfo, ColumnInfo, etc.)\n├── schema/              # Core GraphQL schema handling\n│   ├── fetcher/         # Data fetchers for queries\n│   ├── generator/       # GraphQL schema generators\n│   ├── mutator/         # Mutation resolvers\n│   └── reflector/       # Database schema introspection\n└── service/             # Business services and utilities\n\nsrc/test/groovy/         # Spock-based tests with Testcontainers\n```\n\n## 🏗️ Architecture\n\nThe project uses a modular, database-agnostic design with two main phases:\n\n**Startup Phase (Schema Generation \u0026 Wiring):**\n```\n                    ServiceLookup ───► Database Implementations  \n                         │\n                         ▼\n                   GraphqlConfig ────────────────┐\n                    │   │   │                   │\n       ┌────────────┘   │   └─────────────┐     │\n       ▼                ▼                 ▼     ▼\n┌─────────────┐  ┌─────────────┐  ┌─────────────┐ ┌─────────────┐\n│  Database   │  │   Schema    │  │   Data      │ │  Mutators   │\n│  Reflector  │  │  Generator  │  │  Fetchers   │ │             │\n└─────────────┘  └─────────────┘  └─────────────┘ └─────────────┘\n       │                │                 │             │\n       └────────────────┼─────────────────┼─────────────┘\n                        ▼                 │\n                 ┌─────────────┐          │\n                 │  GraphQL    │◄─────────┘\n                 │   Schema    │  \n                 └─────────────┘\n```\n\n**Runtime Phase (Request Processing):**\n```\nHTTP Request ───► GraphQL Controller ───► GraphQL Engine ───► Resolvers ───► Database\n```\n\n**Key Components:**\n- **Schema Reflector**: Introspects database metadata (startup)\n- **Schema Generator**: Creates GraphQL types from database tables (startup)\n- **Data Fetchers**: Handle query resolution with optimizations (runtime)\n- **Mutators**: Process CRUD operations (runtime)\n- **Service Lookup**: Enables pluggable database-specific implementations\n- **GraphqlConfig**: Central orchestrator that wires data fetchers and mutators to specific GraphQL field coordinates for each table\n\n## Configuration Options\n\n### Database Configuration\n```yaml\nspring:\n  datasource:\n    url: jdbc:postgresql://localhost:5432/mydb\n    username: ${DB_USERNAME:myuser}\n    password: ${DB_PASSWORD:mypass}\n    hikari:\n      maximum-pool-size: 20\n      minimum-idle: 5\n\napp:\n  allowed-schema: ${DATABASE_SCHEMA:public}\n  database-type: postgres\n```\n\n### CDC Configuration\n```yaml\napp:\n  cdc:\n    enabled: true                              # Enable CDC (Change Data Capture) for real-time subscriptions (default: true)\n    slot-name: cdc_slot                        # Replication slot name (default: cdc_slot)\n    publication-name: cdc_publication          # Publication name (default: cdc_publication)\n    create-slot-if-not-exists: true            # Create replication slot if it doesn't exist (default: true)\n    create-publication-if-not-exists: true     # Create publication if it doesn't exist (default: true)\n    heartbeat-interval: 30                     # Heartbeat interval in seconds (default: 30)\n```\n\n### Server Configuration\n```yaml\nserver:\n  port: ${SERVER_PORT:10000}\n\nspring:\n  threads:\n    virtual:\n      enabled: true  # Java 21 virtual threads\n```\n\n### Logging\n\n```yaml\nlogging:\n  level:\n    io.github.excalibase: DEBUG\n    org.springframework.jdbc.core: DEBUG  # Show SQL queries\n```\n\n## 🧪 Testing\n\nThe project includes comprehensive tests using Spock, Spring Boot MockMvc, and Testcontainers:\n\n```bash\n# Run all tests (all modules from project root)\nmvn test\n\n# Run tests for specific modules (change to module directory)\ncd modules/excalibase-graphql-api \u0026\u0026 mvn test\ncd modules/excalibase-graphql-postgres \u0026\u0026 mvn test\ncd modules/excalibase-graphql-starter \u0026\u0026 mvn test\n\n# Run specific test classes (from module directory)\ncd modules/excalibase-graphql-api \u0026\u0026 mvn test -Dtest=GraphqlControllerTest\ncd modules/excalibase-graphql-postgres \u0026\u0026 mvn test -Dtest=PostgresDatabaseDataFetcherImplementTest\n\n# Run with coverage (from project root)\nmvn clean test jacoco:report\n```\n\n### Test Coverage\n\n**✅ Enhanced Date/Time Filtering Tests:**\n- Date equality, range, and comparison operations\n- Timestamp filtering with multiple format support\n- Cross-precision operations (date-only on timestamp columns)\n- OR operations with complex nested conditions\n- IN/NOT IN array operations\n- Null/Not null checks\n- Error handling for invalid date formats\n\n**✅ Controller Tests (MockMvc):**\n- GraphQL schema introspection validation\n- All filter types (StringFilter, IntFilter, DateTimeFilter, etc.)\n- Connection queries with enhanced filtering\n- Legacy filter syntax backward compatibility\n- Real PostgreSQL database integration\n\n**✅ Integration Tests:**\n- Automatic PostgreSQL container spin-up\n- Real database schema and data testing\n- Performance and edge case validation\n\n### Test Configuration\n\nTests use the same PostgreSQL configuration as the main application:\n- Database: `hana` on `localhost:5432`\n- Test server runs on port `10001`\n- Full feature parity with production environment\n\n## Supported Database Types\n\n| Database | Status | Version |\n|----------|--------|---------|\n| PostgreSQL | ✅ Supported | 15+ |\n| MySQL | 🚧 Planned | - |\n| Oracle | 🚧 Planned | - |\n| SQL Server | 🚧 Planned | - |\n\n## 🔍 Enhanced Filtering \u0026 Querying\n\n### Filter Types\n\nExcalibase GraphQL provides comprehensive filter types for all data types:\n\n#### **StringFilter**\n```graphql\n{\n  users(where: { \n    name: { \n      eq: \"John\",           # Exact match\n      neq: \"Jane\",          # Not equal\n      contains: \"oh\",       # Contains substring\n      startsWith: \"J\",      # Starts with\n      endsWith: \"n\",        # Ends with\n      like: \"J%n\",          # SQL LIKE pattern\n      ilike: \"j%N\",         # Case-insensitive LIKE\n      isNull: false,        # Null check\n      isNotNull: true,      # Not null check\n      in: [\"John\", \"Jane\"], # In array\n      notIn: [\"Bob\"]        # Not in array\n    }\n  }) { id name }\n}\n```\n\n#### **IntFilter / FloatFilter**\n```graphql\n{\n  users(where: { \n    age: { \n      eq: 25,               # Equal\n      neq: 30,              # Not equal\n      gt: 18,               # Greater than\n      gte: 21,              # Greater than or equal\n      lt: 65,               # Less than\n      lte: 64,              # Less than or equal\n      in: [25, 30, 35],     # In array\n      notIn: [40, 45],      # Not in array\n      isNull: false         # Null checks\n    }\n  }) { id name age }\n}\n```\n\n#### **DateTimeFilter**\nSupports multiple date formats with intelligent type conversion:\n\n```graphql\n{\n  users(where: { \n    created_at: { \n      eq: \"2023-12-25\",                    # Date only\n      gte: \"2023-01-01 00:00:00\",          # Timestamp\n      lt: \"2023-12-31T23:59:59.999Z\",      # ISO format\n      in: [\"2023-01-01\", \"2023-06-01\"]     # Date array\n    }\n  }) { id name created_at }\n}\n```\n\n**Supported Date Formats:**\n- `\"2023-12-25\"` (yyyy-MM-dd)\n- `\"2023-12-25 14:30:00\"` (yyyy-MM-dd HH:mm:ss)\n- `\"2023-12-25 14:30:00.123\"` (with milliseconds)\n- `\"2023-12-25T14:30:00Z\"` (ISO 8601)\n\n#### **BooleanFilter**\n```graphql\n{\n  users(where: { \n    is_active: { \n      eq: true,\n      isNull: false\n    }\n  }) { id name is_active }\n}\n```\n\n### OR Operations\n\nCombine multiple conditions with logical OR:\n\n```graphql\n{\n  users(\n    or: [\n      { name: { startsWith: \"John\" } },\n      { email: { endsWith: \"@admin.com\" } },\n      { age: { gte: 65 } }\n    ]\n  ) { id name email age }\n}\n```\n\n### Legacy Filter Support\n\nFor backward compatibility, the old filter syntax is still supported:\n\n```graphql\n{\n  users(filter: \"name='John' AND age\u003e25\") {\n    id name age\n  }\n}\n```\n\n### Pagination\n\n**Offset-based:**\n```graphql\nquery {\n  users(limit: 20, offset: 40, orderBy: { id: ASC }) {\n    id\n    name\n  }\n}\n```\n\n**Cursor-based (Relay spec):**\n```graphql\nquery {\n  usersConnection(first: 20, after: \"cursor\", orderBy: { id: ASC }) {\n    edges { node { id name } cursor }\n    pageInfo { hasNextPage endCursor }\n  }\n}\n```\n\n## 🤝 Contributing\n\nThis is a solo project in early development, but contributions are welcome!\n\n🚀 **Getting Started:**\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature/amazing-feature`\n3. Make your changes and add tests\n4. Ensure tests pass: `mvn test`\n5. Commit: `git commit -m 'Add amazing feature'`\n6. Push: `git push origin feature/amazing-feature`\n7. Open a Pull Request\n\n**Current Priority**: Complete PostgreSQL support and enhance GraphQL API features\n\n## Known Limitations\n\n- PostgreSQL only (for now)\n- No authentication/authorization (planned)\n- Limited error handling in some edge cases\n- Performance maybe not optimized for very large schemas\n\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## 🙋‍♂️ Support\n\n- **Issues**: [GitHub Issues](https://github.com/excalibase/excalibase-graphql/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/excalibase/excalibase-graphql/discussions)\n\n## ⭐ Show Your Support\n\nIf you find this project useful, please consider giving it a star ⭐ on GitHub!\n\n---\nMade with ❤️ by the [Excalibase Team](https://github.com/excalibase)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexcalibase%2Fexcalibase-graphql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexcalibase%2Fexcalibase-graphql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexcalibase%2Fexcalibase-graphql/lists"}