CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pg-native

A slightly nicer interface to Postgres over node-libpq providing both sync and async operations

88

1.20x

Quality

Pending

Does it follow best practices?

Impact

88%

1.20x

Average score across 10 eval scenarios

Overview
Eval results
Files

queries.mddocs/

Query Operations

Query execution functionality supporting both text queries and parameterized statements with async and sync interfaces for maximum flexibility.

Capabilities

Asynchronous Query Execution

Execute SQL queries asynchronously with optional parameter binding.

/**
 * Execute a SQL query asynchronously
 * @param text - SQL query text
 * @param callback - Callback function receiving results
 */
client.query(
  text: string, 
  callback: (err: Error | null, rows: any[], results?: QueryResult | QueryResult[]) => void
): void;

/**
 * Execute a parameterized SQL query asynchronously
 * @param text - SQL query text with $1, $2, etc. placeholders
 * @param values - Array of parameter values
 * @param callback - Callback function receiving results
 */
client.query(
  text: string,
  values: any[],
  callback: (err: Error | null, rows: any[], results?: QueryResult | QueryResult[]) => void
): void;

Usage Examples:

const client = new Client();
client.connectSync();

// Simple text query
client.query('SELECT NOW() AS current_time', function(err, rows) {
  if (err) throw err;
  console.log('Current time:', rows[0].current_time);
});

// Parameterized query for safety
client.query(
  'SELECT * FROM users WHERE age > $1 AND city = $2',
  [25, 'New York'],
  function(err, rows) {
    if (err) throw err;
    console.log('Found users:', rows);
  }
);

// Query with multiple result sets
client.query(
  'SELECT 1 as first; SELECT 2 as second',
  function(err, rows, results) {
    if (err) throw err;
    console.log('Multiple results:', results);
    // rows will be an array of arrays: [[{first: 1}], [{second: 2}]]
    // results will be an array of QueryResult objects
  }
);

Multiple Result Sets:

When a query contains multiple statements (separated by semicolons), the callback receives arrays:

  • rows: Array of row arrays, one for each statement
  • results: Array of QueryResult objects, one for each statement

For single statements:

  • rows: Simple array of row objects
  • results: Single QueryResult object (or undefined for simple queries)

Synchronous Query Execution

Execute SQL queries synchronously, returning results directly.

/**
 * Execute a SQL query synchronously
 * @param text - SQL query text
 * @param values - Optional array of parameter values
 * @returns Array of result rows
 * @throws Error if query fails
 */
client.querySync(text: string, values?: any[]): any[];

Usage Examples:

const client = new Client();
client.connectSync();

try {
  // Simple text query
  const rows = client.querySync('SELECT NOW() AS current_time');
  console.log('Current time:', rows[0].current_time);

  // Parameterized query
  const users = client.querySync(
    'SELECT name, email FROM users WHERE age > $1',
    [25]
  );
  console.log('Users over 25:', users);

  // Data modification query
  const insertResult = client.querySync(
    'INSERT INTO logs (message, created_at) VALUES ($1, NOW()) RETURNING id',
    ['Application started']
  );
  console.log('Inserted log ID:', insertResult[0].id);

} catch (err) {
  console.error('Query failed:', err.message);
}

Query Result Format

Query results are returned as arrays of objects by default, with each row as an object with column names as keys.

// Default object mode results
interface QueryResultRow {
  [columnName: string]: any;
}

// Array mode results (when arrayMode: true in constructor)
type QueryResultRowArray = any[];

Object Mode (Default):

const client = new Client();
const rows = client.querySync('SELECT id, name, age FROM users LIMIT 2');
console.log(rows);
// [
//   { id: 1, name: 'Alice', age: 30 },
//   { id: 2, name: 'Bob', age: 25 }
// ]

Array Mode:

const client = new Client({ arrayMode: true });
const rows = client.querySync('SELECT id, name, age FROM users LIMIT 2');
console.log(rows);
// [
//   [1, 'Alice', 30],
//   [2, 'Bob', 25]
// ]

Query Cancellation

Cancel a currently executing query.

/**
 * Cancel the currently executing query
 * @param callback - Required callback function
 */
client.cancel(callback: (err: Error | null) => void): void;

Usage Examples:

const client = new Client();
client.connectSync();

// Start a long-running query
client.query('SELECT pg_sleep(60)', function(err, rows) {
  if (err) {
    console.log('Query was cancelled:', err.message);
  } else {
    console.log('Query completed');
  }
});

// Cancel it after 1 second
setTimeout(function() {
  client.cancel(function(err) {
    if (err) {
      console.error('Cancel failed:', err.message);
    } else {
      console.log('Cancel request sent');
    }
  });
}, 1000);

String Escaping Utilities

Safely escape strings and identifiers for SQL queries.

/**
 * Escape a string literal for safe inclusion in SQL
 * @param value - String value to escape
 * @returns Escaped string literal with quotes
 */
client.escapeLiteral(value: string): string;

/**
 * Escape an identifier for safe inclusion in SQL
 * @param value - Identifier to escape
 * @returns Escaped identifier with quotes if needed
 */
client.escapeIdentifier(value: string): string;

Usage Examples:

const client = new Client();
client.connectSync();

const userInput = "Robert'; DROP TABLE students; --";
const tableName = "user data";

// Escape string literal
const escapedValue = client.escapeLiteral(userInput);
console.log(escapedValue); // 'Robert''; DROP TABLE students; --'

// Escape identifier
const escapedTable = client.escapeIdentifier(tableName);
console.log(escapedTable); // "user data"

// Use in queries (although parameterized queries are preferred)
const query = `SELECT * FROM ${escapedTable} WHERE name = ${escapedValue}`;

Error Handling

All query operations can throw or return PostgreSQL errors:

// Async error handling
client.query('INVALID SQL', function(err, rows) {
  if (err) {
    console.error('Query error:', err.message);
    // err.message contains PostgreSQL error details
  }
});

// Sync error handling
try {
  client.querySync('INVALID SQL');
} catch (err) {
  console.error('Query error:', err.message);
  // err.message contains PostgreSQL error details
}

Best Practices

  1. Use parameterized queries to prevent SQL injection
  2. Use async methods in web servers and event-driven applications
  3. Use sync methods in scripts and command-line tools
  4. Always handle errors appropriately for your use case
  5. Consider arrayMode for memory efficiency with large result sets

Install with Tessl CLI

npx tessl i tessl/npm-pg-native

docs

connection.md

copy-operations.md

index.md

prepared-statements.md

queries.md

tile.json