@memberjunction/postgresql-dataprovider
v5.14.0
Published
MemberJunction: PostgreSQL Data Provider
Keywords
Readme
@memberjunction/postgresql-dataprovider
Overview
Full-featured PostgreSQL data provider for MemberJunction. This package implements DatabaseProviderBase from @memberjunction/core to provide a complete PostgreSQL backend for MemberJunction applications. It also includes a CodeGen provider for generating PostgreSQL-native database objects (views, PL/pgSQL functions, triggers, indexes, full-text search, and more).
Key capabilities:
- Connection pooling via
pg.Poolwith configurable min/max connections - Transaction support with BEGIN/COMMIT/ROLLBACK and variable dependencies between items
- Parameterized queries using PostgreSQL
$1, $2, ...positional parameters - Full CRUD operations through generated PL/pgSQL functions
- CodeGen provider that produces PostgreSQL-native DDL from MemberJunction metadata
- Type conversion for booleans, dates, UUIDs, numbers, and binary data
- Pluggable cache backend inherited from
GenericDatabaseProvider— default in-memory, with optional Redis support for shared, persistent caching
Architecture
Class Hierarchy
DatabaseProviderBase (@memberjunction/core)
└── PostgreSQLDataProvider
├── PGConnectionManager (connection pooling)
├── PGQueryParameterProcessor (type conversion)
└── PostgreSQLTransactionGroup (transaction support)
CodeGenDatabaseProvider (@memberjunction/codegen-lib)
└── PostgreSQLCodeGenProvider (DDL generation)
└── PostgreSQLCodeGenConnection (query execution)Source Files
| File | Purpose |
|------|---------|
| PostgreSQLDataProvider.ts | Main provider: CRUD, queries, view execution, dataset handling, caching |
| pgConnectionManager.ts | Connection pool lifecycle with pg.Pool, shared pool support |
| queryParameterProcessor.ts | Boolean, date, UUID, number, and binary type conversion |
| types.ts | PostgreSQLProviderConfigData and PostgreSQLProviderConfigOptions interfaces |
| PostgreSQLTransactionGroup.ts | BEGIN/COMMIT/ROLLBACK with variable dependencies between transaction items |
| codegen/PostgreSQLCodeGenProvider.ts | CodeGen: views, CRUD functions, triggers, indexes, FTS, permissions |
| codegen/PostgreSQLCodeGenConnection.ts | Translates @ParamName notation to $N positional parameters |
Configuration
Connection Configuration
interface PGConnectionConfig {
Host: string;
Port?: number; // Default: 5432
Database: string;
User: string;
Password: string;
SSL?: boolean | pg.ConnectionConfig['ssl'];
MaxConnections?: number; // Default: 20
MinConnections?: number; // Default: 2
IdleTimeoutMillis?: number; // Default: 30000
ConnectionTimeoutMillis?: number; // Default: 30000
MJCoreSchemaName?: string; // Default: '__mj'
}Provider Configuration
The PostgreSQLProviderConfigData class wraps the connection config and adds MemberJunction-specific options:
const configData = new PostgreSQLProviderConfigData(
connectionConfig, // PGConnectionConfig
'__mj', // MJCoreSchemaName (default: '__mj')
0, // CheckRefreshIntervalSeconds (0 = disabled)
['public', '__mj'], // includeSchemas (optional)
[], // excludeSchemas (optional)
true // ignoreExistingMetadata (default: true)
);Environment Variables
For CodeGen shell execution (psql):
PGHOST-- PostgreSQL server hostPGPORT-- PostgreSQL server portPGDATABASE-- Database namePGUSER-- UsernamePGPASSWORD-- Password (or use.pgpassfile)
Usage
Basic Setup
import { PostgreSQLDataProvider } from '@memberjunction/postgresql-dataprovider';
const provider = new PostgreSQLDataProvider();
await provider.Config(new PostgreSQLProviderConfigData(
{
Host: 'localhost',
Port: 5432,
Database: 'memberjunction',
User: 'mj_user',
Password: 'secret',
MJCoreSchemaName: '__mj'
},
'__mj'
));Running Queries
// Execute raw SQL with positional parameters
const result = await provider.ExecuteSQL<MyType>(
'SELECT * FROM __mj."User" WHERE "ID" = $1',
[$userId]
);
// Run views (MJ pattern)
const results = await provider.InternalRunView<UserEntity>({
EntityName: 'Users',
ExtraFilter: "Status='Active'",
OrderBy: 'Name',
MaxRows: 100
});Transactions
const txGroup = await provider.CreateTransactionGroup();
// Add operations to the transaction group...
await txGroup.Submit(); // Executes all items in a single BEGIN/COMMIT blockThe PostgreSQLTransactionGroup supports variable dependencies between transaction items, allowing later items to reference values produced by earlier items in the same transaction.
Connection Pool Sharing
The PGConnectionManager supports shared pools for scenarios where multiple provider instances need to share a single connection pool (e.g., per-request providers):
// Primary provider creates the pool
const primary = new PGConnectionManager();
await primary.Initialize(config);
// Per-request providers share the pool (won't close it on Close())
const perRequest = new PGConnectionManager();
perRequest.InitializeWithExistingPool(primary.Pool, config);CodeGen Provider
What It Generates
The PostgreSQLCodeGenProvider generates PostgreSQL-native database objects during the MemberJunction code generation process:
- Base Views --
CREATE OR REPLACE VIEWwith joins and soft-delete filtering - CRUD Functions -- PL/pgSQL functions (not stored procedures) with
RETURNINGclause - Timestamp Triggers -- PL/pgSQL trigger functions for automatic
__mj_UpdatedAtmaintenance - Foreign Key Indexes --
CREATE INDEX IF NOT EXISTSwith 63-character name limit enforcement - Full-Text Search -- tsvector columns, GIN indexes, PL/pgSQL trigger for auto-update, and search functions
- Cascade Deletes -- Recursive delete/update-to-NULL operations for related records
- Permissions -- GRANT statements per entity role
- Drop Guards --
DROP ... IF EXISTS ... CASCADEstatements before object creation
Key PostgreSQL-Specific Patterns
- Uses PL/pgSQL
CREATE OR REPLACE FUNCTIONinstead of SQL Server stored procedures - Functions return query results via
RETURNS TABLE(...)orRETURNS SETOF - Uses dollar-quoted strings (
$$...$$) for function bodies - Implements
LATERALjoins instead of SQL Server'sOUTER APPLY - Full-text search uses
tsvector/tsquerywith GIN indexes (notCONTAINSTABLE) - Index names are truncated to 63 characters to respect the PostgreSQL identifier limit
- Boolean columns use native
true/falseinstead of SQL Server's1/0 - Uses
LIMIT/OFFSETfor pagination instead ofTOP/OFFSET-FETCH - Identifier quoting uses
"double quotes"instead of SQL Server's[brackets]
Registration
The CodeGen provider is registered via the MemberJunction class factory:
@RegisterClass(CodeGenDatabaseProvider, 'PostgreSQLCodeGenProvider')
export class PostgreSQLCodeGenProvider extends CodeGenDatabaseProvider { ... }Relationship to Other Packages
@memberjunction/sql-dialect
- Provides
PostgreSQLDialectfor identifier quoting, pagination syntax, and type mapping - Used by both
PostgreSQLDataProviderandPostgreSQLCodeGenProvider - Zero-dependency abstraction layer shared across all database-specific code
@memberjunction/codegen-lib
- Provides
CodeGenDatabaseProviderabstract base class with ~55 methods PostgreSQLCodeGenProviderimplements all abstract methods with PostgreSQL-native SQL- The CodeGen orchestration layer calls these methods to generate DDL during code generation runs
@memberjunction/core
- Provides
DatabaseProviderBaseabstract class defining the full MJ data provider contract PostgreSQLDataProviderimplements CRUD, view execution, dataset operations, and metadata access
@memberjunction/global
- Provides
@RegisterClassfor class factory registration PostgreSQLCodeGenProviderregisters itself so the CodeGen system can discover it at runtime
Dependencies
| Package | Purpose |
|---------|---------|
| @memberjunction/core | Base provider interfaces and entity framework |
| @memberjunction/codegen-lib | CodeGen base class and orchestration types |
| @memberjunction/sql-dialect | SQL dialect abstraction (quoting, pagination, types) |
| @memberjunction/global | Class registration via @RegisterClass |
| pg | PostgreSQL Node.js driver (connection pooling, queries) |
Testing
cd packages/PostgreSQLDataProvider
npm run test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportTests use Vitest with mocked database connections (no live database required).
Platform Key
The provider identifies itself with PlatformKey: 'postgresql', which is used throughout MemberJunction to select the correct SQL dialect, CodeGen templates, and runtime behavior for PostgreSQL deployments.
