Skip to content

Raw Queries

Master direct SQL execution and RPC function calls in PGRestify for complex queries, stored procedures, and advanced database operations.

Overview

While PGRestify's query builder covers most use cases, sometimes you need the full power of SQL. Raw queries in PGRestify are implemented through PostgreSQL stored procedures and functions (RPCs - Remote Procedure Calls), allowing you to execute complex SQL logic while maintaining security and type safety.

RPC Function Calls

Basic RPC Usage

typescript
// Call a simple function without parameters
const result = await client
  .rpc('get_current_timestamp')
  .execute();

// Call function with parameters
const userStats = await client
  .rpc('calculate_user_statistics', {
    user_id: 123,
    start_date: '2024-01-01',
    end_date: '2024-12-31'
  })
  .execute();

// Call function with complex parameters
const searchResults = await client
  .rpc('advanced_product_search', {
    search_criteria: {
      keyword: 'laptop',
      category_ids: [1, 2, 3],
      price_range: { min: 500, max: 2000 },
      in_stock_only: true
    }
  })
  .execute();

Creating PostgreSQL Functions

sql
-- Simple function returning a table
CREATE OR REPLACE FUNCTION get_user_dashboard_data(p_user_id INT)
RETURNS TABLE (
  user_name TEXT,
  total_orders BIGINT,
  total_spent NUMERIC,
  favorite_category TEXT,
  last_order_date DATE
) AS $$
BEGIN
  RETURN QUERY
  SELECT 
    u.name,
    COUNT(o.id),
    COALESCE(SUM(o.total_amount), 0),
    (SELECT c.name 
     FROM categories c 
     JOIN products p ON c.id = p.category_id
     JOIN order_items oi ON p.id = oi.product_id
     JOIN orders o2 ON oi.order_id = o2.id
     WHERE o2.customer_id = p_user_id
     GROUP BY c.name
     ORDER BY COUNT(*) DESC
     LIMIT 1),
    MAX(o.created_at)::DATE
  FROM users u
  LEFT JOIN orders o ON u.id = o.customer_id
  WHERE u.id = p_user_id
  GROUP BY u.id, u.name;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

Complex RPC Functions

sql
-- Function with complex business logic
CREATE OR REPLACE FUNCTION process_order_workflow(
  p_order_data JSONB,
  p_user_id INT,
  p_apply_discounts BOOLEAN DEFAULT true
)
RETURNS JSONB AS $$
DECLARE
  v_order_id INT;
  v_total_amount NUMERIC := 0;
  v_discount_amount NUMERIC := 0;
  v_item JSONB;
  v_result JSONB;
BEGIN
  -- Start transaction
  -- Create order
  INSERT INTO orders (customer_id, status, created_at)
  VALUES (p_user_id, 'pending', NOW())
  RETURNING id INTO v_order_id;
  
  -- Process order items
  FOR v_item IN SELECT * FROM jsonb_array_elements(p_order_data->'items')
  LOOP
    INSERT INTO order_items (order_id, product_id, quantity, unit_price)
    VALUES (
      v_order_id,
      (v_item->>'product_id')::INT,
      (v_item->>'quantity')::INT,
      (v_item->>'unit_price')::NUMERIC
    );
    
    v_total_amount := v_total_amount + 
      ((v_item->>'quantity')::INT * (v_item->>'unit_price')::NUMERIC);
  END LOOP;
  
  -- Apply discounts if requested
  IF p_apply_discounts THEN
    SELECT calculate_user_discount(p_user_id, v_total_amount) INTO v_discount_amount;
    v_total_amount := v_total_amount - v_discount_amount;
  END IF;
  
  -- Update order total
  UPDATE orders 
  SET total_amount = v_total_amount,
      discount_amount = v_discount_amount
  WHERE id = v_order_id;
  
  -- Return result
  SELECT jsonb_build_object(
    'order_id', v_order_id,
    'total_amount', v_total_amount,
    'discount_applied', v_discount_amount,
    'status', 'created'
  ) INTO v_result;
  
  RETURN v_result;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

Calling Complex Functions

typescript
// Process order with complex logic
const orderResult = await client
  .rpc('process_order_workflow', {
    p_order_data: {
      items: [
        { product_id: 1, quantity: 2, unit_price: 99.99 },
        { product_id: 5, quantity: 1, unit_price: 149.99 }
      ],
      shipping_address: {
        street: '123 Main St',
        city: 'New York',
        zip: '10001'
      }
    },
    p_user_id: 456,
    p_apply_discounts: true
  })
  .execute();

console.log('Order created:', orderResult.data);
// { order_id: 789, total_amount: 349.97, discount_applied: 25.00, status: 'created' }

Advanced SQL Patterns

Window Functions and Analytics

sql
-- Advanced analytics function
CREATE OR REPLACE FUNCTION get_sales_analytics(
  p_start_date DATE,
  p_end_date DATE,
  p_group_by TEXT DEFAULT 'month'
)
RETURNS TABLE (
  period TEXT,
  revenue NUMERIC,
  order_count BIGINT,
  avg_order_value NUMERIC,
  running_total NUMERIC,
  growth_rate NUMERIC
) AS $$
DECLARE
  v_date_format TEXT;
BEGIN
  -- Set date format based on grouping
  CASE p_group_by
    WHEN 'day' THEN v_date_format := 'YYYY-MM-DD';
    WHEN 'week' THEN v_date_format := 'YYYY-"W"WW';
    WHEN 'month' THEN v_date_format := 'YYYY-MM';
    WHEN 'year' THEN v_date_format := 'YYYY';
    ELSE v_date_format := 'YYYY-MM';
  END CASE;

  RETURN QUERY
  WITH sales_data AS (
    SELECT 
      TO_CHAR(created_at, v_date_format) as period,
      SUM(total_amount) as revenue,
      COUNT(*) as order_count,
      AVG(total_amount) as avg_order_value
    FROM orders
    WHERE created_at >= p_start_date 
      AND created_at <= p_end_date
      AND status = 'completed'
    GROUP BY TO_CHAR(created_at, v_date_format)
  ),
  analytics_data AS (
    SELECT 
      sd.*,
      SUM(sd.revenue) OVER (ORDER BY sd.period) as running_total,
      LAG(sd.revenue) OVER (ORDER BY sd.period) as prev_revenue
    FROM sales_data sd
  )
  SELECT 
    ad.period,
    ad.revenue,
    ad.order_count,
    ad.avg_order_value,
    ad.running_total,
    CASE 
      WHEN ad.prev_revenue IS NULL THEN 0
      ELSE ((ad.revenue - ad.prev_revenue) / ad.prev_revenue * 100)
    END as growth_rate
  FROM analytics_data ad
  ORDER BY ad.period;
END;
$$ LANGUAGE plpgsql;

Complex Joins and Subqueries

sql
-- Multi-table complex query function
CREATE OR REPLACE FUNCTION get_customer_insights(
  p_customer_segment TEXT DEFAULT 'all',
  p_min_orders INT DEFAULT 1
)
RETURNS TABLE (
  customer_id INT,
  customer_name TEXT,
  total_orders BIGINT,
  total_spent NUMERIC,
  avg_order_value NUMERIC,
  favorite_category TEXT,
  last_order_days_ago INT,
  customer_segment TEXT,
  lifetime_value_score NUMERIC
) AS $$
BEGIN
  RETURN QUERY
  WITH customer_stats AS (
    SELECT 
      c.id,
      c.name,
      COUNT(o.id) as total_orders,
      COALESCE(SUM(o.total_amount), 0) as total_spent,
      COALESCE(AVG(o.total_amount), 0) as avg_order_value,
      MAX(o.created_at) as last_order_date
    FROM customers c
    LEFT JOIN orders o ON c.id = o.customer_id AND o.status = 'completed'
    GROUP BY c.id, c.name
    HAVING COUNT(o.id) >= p_min_orders
  ),
  customer_categories AS (
    SELECT DISTINCT ON (cs.id)
      cs.id,
      cat.name as favorite_category
    FROM customer_stats cs
    LEFT JOIN orders o ON cs.id = o.customer_id
    LEFT JOIN order_items oi ON o.id = oi.order_id
    LEFT JOIN products p ON oi.product_id = p.id
    LEFT JOIN categories cat ON p.category_id = cat.id
    WHERE o.status = 'completed'
    ORDER BY cs.id, COUNT(*) DESC
  )
  SELECT 
    cs.id,
    cs.name,
    cs.total_orders,
    cs.total_spent,
    cs.avg_order_value,
    COALESCE(cc.favorite_category, 'Unknown'),
    COALESCE(EXTRACT(DAY FROM NOW() - cs.last_order_date)::INT, -1),
    CASE 
      WHEN cs.total_spent > 1000 AND cs.total_orders > 10 THEN 'VIP'
      WHEN cs.total_spent > 500 AND cs.total_orders > 5 THEN 'Premium' 
      WHEN cs.total_orders > 2 THEN 'Regular'
      ELSE 'New'
    END as segment,
    (cs.total_spent * 0.7 + cs.total_orders * 50 + 
     CASE WHEN cs.last_order_date > NOW() - INTERVAL '30 days' THEN 100 ELSE 0 END) as ltv_score
  FROM customer_stats cs
  LEFT JOIN customer_categories cc ON cs.id = cc.id
  WHERE (p_customer_segment = 'all' OR 
         (p_customer_segment = 'vip' AND cs.total_spent > 1000) OR
         (p_customer_segment = 'premium' AND cs.total_spent > 500) OR
         (p_customer_segment = 'new' AND cs.total_orders <= 2))
  ORDER BY ltv_score DESC;
END;
$$ LANGUAGE plpgsql;

Calling Advanced Functions

typescript
// Get sales analytics
const salesAnalytics = await client
  .rpc('get_sales_analytics', {
    p_start_date: '2024-01-01',
    p_end_date: '2024-12-31',
    p_group_by: 'month'
  })
  .execute();

// Get customer insights
const customerInsights = await client
  .rpc('get_customer_insights', {
    p_customer_segment: 'vip',
    p_min_orders: 5
  })
  .execute();

Data Manipulation Functions

Batch Operations

sql
-- Batch update function
CREATE OR REPLACE FUNCTION batch_update_product_prices(
  p_updates JSONB
)
RETURNS JSONB AS $$
DECLARE
  v_update JSONB;
  v_updated_count INT := 0;
  v_failed_updates JSONB := '[]'::JSONB;
  v_result JSONB;
BEGIN
  FOR v_update IN SELECT * FROM jsonb_array_elements(p_updates)
  LOOP
    BEGIN
      UPDATE products 
      SET 
        price = (v_update->>'new_price')::NUMERIC,
        updated_at = NOW()
      WHERE id = (v_update->>'product_id')::INT;
      
      IF FOUND THEN
        v_updated_count := v_updated_count + 1;
      ELSE
        v_failed_updates := v_failed_updates || jsonb_build_object(
          'product_id', v_update->>'product_id',
          'reason', 'Product not found'
        );
      END IF;
    EXCEPTION WHEN OTHERS THEN
      v_failed_updates := v_failed_updates || jsonb_build_object(
        'product_id', v_update->>'product_id',
        'reason', SQLERRM
      );
    END;
  END LOOP;
  
  SELECT jsonb_build_object(
    'updated_count', v_updated_count,
    'failed_updates', v_failed_updates,
    'total_processed', jsonb_array_length(p_updates)
  ) INTO v_result;
  
  RETURN v_result;
END;
$$ LANGUAGE plpgsql;

Data Validation Functions

sql
-- Data validation and cleanup function
CREATE OR REPLACE FUNCTION validate_and_clean_user_data(
  p_user_data JSONB
)
RETURNS JSONB AS $$
DECLARE
  v_cleaned_data JSONB;
  v_validation_errors TEXT[] := ARRAY[]::TEXT[];
BEGIN
  -- Initialize cleaned data
  v_cleaned_data := p_user_data;
  
  -- Validate email
  IF NOT (p_user_data->>'email' ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$') THEN
    v_validation_errors := array_append(v_validation_errors, 'Invalid email format');
  END IF;
  
  -- Clean and validate phone number
  IF p_user_data ? 'phone' THEN
    -- Remove non-digits from phone
    v_cleaned_data := jsonb_set(
      v_cleaned_data, 
      '{phone}', 
      to_jsonb(regexp_replace(p_user_data->>'phone', '[^0-9]', '', 'g'))
    );
    
    -- Validate phone length
    IF length(v_cleaned_data->>'phone') < 10 THEN
      v_validation_errors := array_append(v_validation_errors, 'Phone number too short');
    END IF;
  END IF;
  
  -- Validate age
  IF (p_user_data->>'age')::INT < 13 THEN
    v_validation_errors := array_append(v_validation_errors, 'User must be at least 13 years old');
  END IF;
  
  -- Return result with cleaned data and any validation errors
  RETURN jsonb_build_object(
    'cleaned_data', v_cleaned_data,
    'validation_errors', to_jsonb(v_validation_errors),
    'is_valid', array_length(v_validation_errors, 1) IS NULL
  );
END;
$$ LANGUAGE plpgsql;

Calling Data Manipulation Functions

typescript
// Batch update prices
const priceUpdates = await client
  .rpc('batch_update_product_prices', {
    p_updates: [
      { product_id: 1, new_price: 99.99 },
      { product_id: 2, new_price: 149.99 },
      { product_id: 3, new_price: 199.99 }
    ]
  })
  .execute();

console.log('Update result:', priceUpdates.data);
// { updated_count: 2, failed_updates: [{ product_id: 3, reason: "Product not found" }], total_processed: 3 }

// Validate user data
const validationResult = await client
  .rpc('validate_and_clean_user_data', {
    p_user_data: {
      email: 'user@example.com',
      phone: '(555) 123-4567',
      age: 25,
      name: 'John Doe'
    }
  })
  .execute();

if (validationResult.data.is_valid) {
  // Use cleaned data
  console.log('Clean data:', validationResult.data.cleaned_data);
} else {
  console.log('Validation errors:', validationResult.data.validation_errors);
}

Dynamic SQL Generation

Query Builder Functions

sql
-- Dynamic query builder function
CREATE OR REPLACE FUNCTION dynamic_product_search(
  p_filters JSONB,
  p_sort_by TEXT DEFAULT 'name',
  p_sort_order TEXT DEFAULT 'ASC',
  p_limit INT DEFAULT 20,
  p_offset INT DEFAULT 0
)
RETURNS JSONB AS $$
DECLARE
  v_query TEXT := 'SELECT row_to_json(t) FROM (SELECT * FROM products WHERE 1=1';
  v_count_query TEXT := 'SELECT COUNT(*) FROM products WHERE 1=1';
  v_where_clause TEXT := '';
  v_filter_key TEXT;
  v_filter_value JSONB;
  v_results JSONB;
  v_total_count INT;
BEGIN
  -- Build WHERE clause dynamically
  FOR v_filter_key, v_filter_value IN SELECT * FROM jsonb_each(p_filters)
  LOOP
    CASE v_filter_key
      WHEN 'name' THEN
        v_where_clause := v_where_clause || ' AND name ILIKE ' || quote_literal('%' || (v_filter_value #>> '{}') || '%');
      WHEN 'category_id' THEN
        v_where_clause := v_where_clause || ' AND category_id = ' || (v_filter_value #>> '{}')::INT;
      WHEN 'price_min' THEN
        v_where_clause := v_where_clause || ' AND price >= ' || (v_filter_value #>> '{}')::NUMERIC;
      WHEN 'price_max' THEN
        v_where_clause := v_where_clause || ' AND price <= ' || (v_filter_value #>> '{}')::NUMERIC;
      WHEN 'in_stock' THEN
        v_where_clause := v_where_clause || ' AND in_stock = ' || (v_filter_value #>> '{}')::BOOLEAN;
    END CASE;
  END LOOP;
  
  -- Add WHERE clause to queries
  v_query := v_query || v_where_clause;
  v_count_query := v_count_query || v_where_clause;
  
  -- Add ORDER BY and LIMIT
  v_query := v_query || ' ORDER BY ' || quote_ident(p_sort_by) || ' ' || p_sort_order;
  v_query := v_query || ' LIMIT ' || p_limit || ' OFFSET ' || p_offset || ') t';
  
  -- Execute count query
  EXECUTE v_count_query INTO v_total_count;
  
  -- Execute main query and collect results
  EXECUTE 'SELECT jsonb_agg(results) FROM (' || v_query || ') as results' INTO v_results;
  
  -- Return results with metadata
  RETURN jsonb_build_object(
    'data', COALESCE(v_results, '[]'::jsonb),
    'total_count', v_total_count,
    'limit', p_limit,
    'offset', p_offset,
    'generated_query', v_query
  );
END;
$$ LANGUAGE plpgsql;

Calling Dynamic Functions

typescript
// Dynamic product search with flexible filters
const dynamicSearch = await client
  .rpc('dynamic_product_search', {
    p_filters: {
      name: 'laptop',
      category_id: 1,
      price_min: 500,
      price_max: 2000,
      in_stock: true
    },
    p_sort_by: 'price',
    p_sort_order: 'DESC',
    p_limit: 10,
    p_offset: 0
  })
  .execute();

console.log('Search results:', dynamicSearch.data);
// {
//   data: [...products...],
//   total_count: 45,
//   limit: 10,
//   offset: 0,
//   generated_query: "SELECT row_to_json(t) FROM (SELECT * FROM products WHERE..."
// }

Error Handling and Security

Secure Function Creation

sql
-- Function with proper error handling and security
CREATE OR REPLACE FUNCTION secure_user_operation(
  p_user_id INT,
  p_operation TEXT,
  p_data JSONB DEFAULT '{}'::JSONB
)
RETURNS JSONB 
SECURITY DEFINER  -- Runs with creator's privileges
SET search_path = public, pg_catalog  -- Prevent search path attacks
AS $$
DECLARE
  v_result JSONB;
  v_user_exists BOOLEAN;
BEGIN
  -- Validate input parameters
  IF p_user_id IS NULL OR p_user_id <= 0 THEN
    RAISE EXCEPTION 'Invalid user ID: %', p_user_id;
  END IF;
  
  IF p_operation IS NULL OR p_operation = '' THEN
    RAISE EXCEPTION 'Operation cannot be empty';
  END IF;
  
  -- Check if user exists
  SELECT EXISTS(SELECT 1 FROM users WHERE id = p_user_id) INTO v_user_exists;
  IF NOT v_user_exists THEN
    RAISE EXCEPTION 'User with ID % does not exist', p_user_id;
  END IF;
  
  -- Perform operation based on type
  CASE p_operation
    WHEN 'get_profile' THEN
      SELECT row_to_json(u) INTO v_result 
      FROM (SELECT id, name, email, created_at FROM users WHERE id = p_user_id) u;
      
    WHEN 'update_preferences' THEN
      UPDATE users 
      SET preferences = p_data,
          updated_at = NOW()
      WHERE id = p_user_id;
      
      v_result := jsonb_build_object('success', true, 'message', 'Preferences updated');
      
    ELSE
      RAISE EXCEPTION 'Unknown operation: %', p_operation;
  END CASE;
  
  RETURN v_result;
  
EXCEPTION
  WHEN OTHERS THEN
    -- Log error (in real application, use proper logging)
    RAISE LOG 'Error in secure_user_operation: % %', SQLSTATE, SQLERRM;
    
    -- Return error information
    RETURN jsonb_build_object(
      'error', true,
      'error_code', SQLSTATE,
      'error_message', SQLERRM,
      'operation', p_operation,
      'user_id', p_user_id
    );
END;
$$ LANGUAGE plpgsql;

Calling Secure Functions

typescript
// Call secure function with error handling
const userOperation = async (userId: number, operation: string, data?: any) => {
  try {
    const result = await client
      .rpc('secure_user_operation', {
        p_user_id: userId,
        p_operation: operation,
        p_data: data || {}
      })
      .execute();
    
    if (result.data?.error) {
      throw new Error(`Database error: ${result.data.error_message}`);
    }
    
    return result.data;
  } catch (error) {
    console.error('RPC call failed:', error);
    throw error;
  }
};

// Usage
try {
  const profile = await userOperation(123, 'get_profile');
  console.log('User profile:', profile);
  
  const updateResult = await userOperation(123, 'update_preferences', {
    theme: 'dark',
    language: 'en',
    notifications: true
  });
  console.log('Update result:', updateResult);
} catch (error) {
  console.error('Operation failed:', error.message);
}

Performance Optimization

Efficient Function Design

sql
-- Optimized function with proper indexing hints
CREATE OR REPLACE FUNCTION get_user_dashboard_optimized(
  p_user_id INT
)
RETURNS JSONB AS $$
DECLARE
  v_result JSONB;
  v_user_info JSONB;
  v_order_stats JSONB;
  v_recent_activity JSONB;
BEGIN
  -- Use efficient queries with proper WHERE clauses for indexes
  
  -- Get user info (single query)
  SELECT to_jsonb(u) INTO v_user_info
  FROM (
    SELECT id, name, email, created_at, last_login
    FROM users 
    WHERE id = p_user_id
  ) u;
  
  -- Get order statistics (optimized aggregation)
  SELECT to_jsonb(stats) INTO v_order_stats
  FROM (
    SELECT 
      COUNT(*) as total_orders,
      COALESCE(SUM(total_amount), 0) as total_spent,
      MAX(created_at) as last_order_date
    FROM orders 
    WHERE customer_id = p_user_id AND status = 'completed'
  ) stats;
  
  -- Get recent activity (limited query)
  SELECT jsonb_agg(activity) INTO v_recent_activity
  FROM (
    SELECT type, description, created_at
    FROM user_activities
    WHERE user_id = p_user_id
    ORDER BY created_at DESC
    LIMIT 10
  ) activity;
  
  -- Combine results
  SELECT jsonb_build_object(
    'user_info', v_user_info,
    'order_stats', v_order_stats,
    'recent_activity', COALESCE(v_recent_activity, '[]'::jsonb)
  ) INTO v_result;
  
  RETURN v_result;
END;
$$ LANGUAGE plpgsql;

Function Caching Strategies

typescript
// Client-side caching for expensive RPC calls
class RPCManager {
  private cache = new Map<string, { data: any; expires: number }>();
  
  async callWithCache(
    functionName: string, 
    params: any = {}, 
    cacheSeconds = 300
  ) {
    const cacheKey = `${functionName}:${JSON.stringify(params)}`;
    const cached = this.cache.get(cacheKey);
    
    if (cached && cached.expires > Date.now()) {
      return { data: cached.data, fromCache: true };
    }
    
    const result = await client.rpc(functionName, params).execute();
    
    // Cache successful results
    if (!result.error) {
      this.cache.set(cacheKey, {
        data: result.data,
        expires: Date.now() + (cacheSeconds * 1000)
      });
    }
    
    return { data: result.data, fromCache: false };
  }
}

// Usage
const rpcManager = new RPCManager();
const dashboard = await rpcManager.callWithCache(
  'get_user_dashboard_optimized',
  { p_user_id: 123 },
  600 // Cache for 10 minutes
);

Common RPC Patterns

Utility Functions

typescript
// Common database utilities as RPC functions
const dbUtils = {
  async getTableStats(tableName: string) {
    return client.rpc('get_table_statistics', { table_name: tableName });
  },
  
  async cleanupOldRecords(tableName: string, daysOld: number) {
    return client.rpc('cleanup_old_records', { 
      table_name: tableName, 
      days_old: daysOld 
    });
  },
  
  async validateDataIntegrity() {
    return client.rpc('validate_data_integrity');
  },
  
  async getSystemHealth() {
    return client.rpc('get_system_health_status');
  }
};

Business Logic Functions

typescript
// Business logic encapsulated in RPC functions
const businessLogic = {
  async calculateShipping(orderData: any) {
    return client.rpc('calculate_shipping_cost', { order_data: orderData });
  },
  
  async applyPromotions(cartData: any, userId: number) {
    return client.rpc('apply_available_promotions', { 
      cart_data: cartData, 
      user_id: userId 
    });
  },
  
  async processRefund(orderId: number, reason: string) {
    return client.rpc('process_order_refund', { 
      order_id: orderId, 
      refund_reason: reason 
    });
  }
};

Summary

PGRestify's raw query capabilities through RPC functions provide:

  • Full SQL Power: Execute complex queries and stored procedures
  • Business Logic Encapsulation: Keep complex logic in the database
  • Type Safety: Structured input/output with PostgreSQL functions
  • Security: SECURITY DEFINER functions with proper validation
  • Performance: Optimized database operations with minimal network calls
  • Flexibility: Dynamic SQL generation and complex data processing
  • Error Handling: Comprehensive error management and logging
  • Caching: Client-side caching strategies for expensive operations

Master these raw query patterns to handle complex business requirements that go beyond standard CRUD operations while maintaining security and performance through PostgreSQL's powerful function system.

Released under the MIT License.