Skip to main content

pg_ext: PostgreSQL Compatibility Library

Overview

The pg_ext library provides a minimal reimplementation of PostgreSQL internal APIs, enabling Springtail to execute functions from PostgreSQL extensions without requiring a full PostgreSQL backend. It creates a compatible runtime environment for extension code that expects PostgreSQL’s data types, memory management, and function call interface. Location: Source files in src/pg_ext/, Headers in include/pg_ext/ Purpose:
  • Provide PostgreSQL-compatible data structures (Datum, text, arrays, etc.)
  • Implement function call interface (DirectFunctionCall*())
  • Emulate PostgreSQL memory context system
  • Support extension-defined types and operators

Architecture

Core Components

Components:
  • fmgr: Function manager (DirectFunctionCall* wrappers)
  • memory: Memory contexts (palloc, pfree, TopMemoryContext)
  • string: Text type and string utilities
  • array: PostgreSQL array handling
  • numeric: Numeric type support
  • date: Date/time types
  • jsonb: JSONB type support
  • error: Error reporting (ereport, elog)
  • node: PostgreSQL node types
  • hash: Hash functions
  • list: PostgreSQL list structures
  • parser: libpg_query integration
  • heaptuple: Heap tuple representation
  • pqformat: Wire protocol formatting
  • bit: Bit string operations
  • float: Float type utilities
  • guc: GUC (configuration) stubs
  • extn_registry: Extension registry (covered separately)
  • extn_parser: Extension SQL parsing

Function Manager (fmgr)

Overview

Provides macros and functions for calling PostgreSQL functions with a compatible calling convention. Files: src/pg_ext/fmgr.cc, include/pg_ext/fmgr.hh

Key Macros

LOCAL_FCINFO()

Allocates stack-local FunctionCallInfo structure:
Usage:

InitFunctionCallInfoData()

Initialize FunctionCallInfo structure:

DirectFunctionCall Family

Convenience functions for calling PostgreSQL functions:

DirectFunctionCall1()

Implementation:
Example:

DirectFunctionCall2()

Example:

DirectFunctionCall3()

Collation Variants

For functions that require collation (string operations):
Example:

Datum Type Conversions

Macros for converting between C types and Datum:

Memory Management

Overview

PostgreSQL uses a memory context system for allocation tracking and bulk deallocation. pg_ext provides a simplified implementation. Files: src/pg_ext/memory.cc, include/pg_ext/memory.hh

MemoryContext Class

Global Memory Context

The global TopMemoryContext is the root of all memory contexts:

Allocation Functions

palloc()

Allocate memory from a memory context:
Implementation:
Example:

pfree()

Free memory allocated by palloc:

repalloc()

Reallocate memory:

Memory Blocks

Internal structure for memory management:

Usage Notes

  • Extension functions expect palloc() for allocations
  • Memory contexts are simplified compared to PostgreSQL
  • No support for memory context switching or hierarchies
  • All allocations go to TopMemoryContext

String and Text Types

Overview

PostgreSQL’s text type is a variable-length binary string with a 4-byte header. Files: src/pg_ext/string.cc, include/pg_ext/string.hh

Text Structure

String Utilities

cstring_to_text()

Convert C string to PostgreSQL text:
Implementation:
Example:

cstring_to_text_auto()

Wrapper that handles const correctness:

text_to_cstring()

Convert text to C string:
Implementation:
Example:

Macros


Array Support

Overview

Support for PostgreSQL’s array type. Files: src/pg_ext/array.cc, include/pg_ext/array.hh

ArrayType Structure

Array Functions


Numeric Type

Overview

PostgreSQL’s arbitrary-precision numeric type. Files: src/pg_ext/numeric.cc, include/pg_ext/numeric.hh

Numeric Structure

Numeric Functions


Date and Time Types

Overview

PostgreSQL date/time types and operations. Files: src/pg_ext/date.cc, include/pg_ext/date.hh

Types

Date/Time Functions


Error Handling

Overview

PostgreSQL error reporting system. Files: src/pg_ext/error.cc, include/pg_ext/error.hh

Error Levels

ereport Macro

Usage:

elog Macro

Usage:

StringInfo (pqformat)

Overview

Dynamic string buffer for building messages. Files: src/pg_ext/pqformat.cc, include/pg_ext/pqformat.hh

StringInfoData Structure

StringInfo Functions

Example:

Node Types

Overview

PostgreSQL’s node type system for parse trees and plans. Files: src/pg_ext/node.cc, include/pg_ext/node.hh

Node Structure

Node Functions


List Support

Overview

PostgreSQL’s doubly-linked list implementation. Files: src/pg_ext/list.cc, include/pg_ext/list.hh

List Structure

List Functions

Example:

Integration with Springtail

Type System Integration

Extension types are stored in Springtail’s type system through create_usertype():

Comparator Integration

Extension operators are used in Springtail comparisons:

Limitations

Not Implemented

PostgreSQL features NOT implemented in pg_ext:
  1. Transaction Management: No MVCC, snapshot isolation
  2. Catalog Access: No pg_catalog queries
  3. SPI (Server Programming Interface): No SQL execution from C functions
  4. Triggers: No trigger mechanism
  5. Full Memory Context Tree: Simplified single-level context
  6. Signal Handling: No PostgreSQL signal handlers
  7. Shared Memory: No PostgreSQL shared memory segments
  8. TOAST: No out-of-line storage for large values
  9. Vacuum: No MVCC cleanup
  10. Write-Ahead Log: No WAL integration

Compatibility Notes

  • Extension functions must not rely on PostgreSQL backend state
  • SPI-using extensions will NOT work
  • Trigger-based extensions will NOT work
  • Extensions accessing pg_catalog may fail
  • Extension functions assuming PostgreSQL memory semantics may leak memory

Adding New pg_ext Support

To add support for a new PostgreSQL feature:
  1. Identify Required APIs: Determine what PostgreSQL functions the extension uses
  2. Create Stub Implementation: Add stubs in appropriate src/pg_ext/*.cc file
  3. Add Type Definitions: Add necessary structs/types in include/pg_ext/*.hh
  4. Implement Core Logic: Implement minimal functionality needed by extensions
  5. Test with Extension: Verify extension functions work correctly
Example: Adding Support for Range Types
  1. Create header file include/pg_ext/range.hh:
  1. Create source file src/pg_ext/range.cc: