Skip to content

Latest commit

 

History

History
127 lines (92 loc) · 4.25 KB

File metadata and controls

127 lines (92 loc) · 4.25 KB

Npgquery - PostgreSQL Query Parser for .NET

A high-performance .NET library for parsing PostgreSQL queries using the official PostgreSQL parser via libpg_query.

Key Features

  • Query Validation & Utilities: Validate SQL and extract common query metadata
  • Query Normalization: Standardize queries for comparison
  • Query Fingerprinting: Generate unique identifiers for query patterns
  • Query Tokenization: Analyze SQL tokens and keywords
  • Statement Splitting: Split multi-statement SQL into individual statements
  • PL/pgSQL Support: Parse PL/pgSQL functions and procedures
  • Batch Processing: Process multiple queries efficiently
  • Parse SQL to AST: Convert PostgreSQL queries to JSON or Protobuf AST
  • AST Deparsing: Convert JSON or Protobuf ASTs back to SQL
  • Async Operations: Full async/await support
  • Cross-Platform: Works on Windows, Linux (macOS coming soon!)

Installation

Install Npgquery from NuGet with the .NET CLI:

dotnet add package Npgquery

Or with the NuGet Package Manager Console:

Install-Package Npgquery

The package includes the native libpg_query runtime assets for supported platforms. Application users should not install or build native parser libraries separately.

Then import the namespace in your application:

using Npgquery;

Quick Start

For simple one-off operations, use the static quick methods to parse PostgreSQL SQL into an abstract syntax tree (AST):

var result = Parser.QuickParse("SELECT * FROM users WHERE id = 1");
if (result.IsSuccess)
{
    Console.WriteLine(result.ParseTree?.RootElement.ToString());
}
else
{
    Console.WriteLine(result.Error);
}

The quick methods are available for the core capabilities:

var parseResult = Parser.QuickParse("SELECT now()");
var normalized = Parser.QuickNormalize("SELECT * FROM users WHERE id = 42");
var fingerprint = Parser.QuickFingerprint("SELECT * FROM users WHERE id = 42");
var split = Parser.QuickSplit("SELECT 1; SELECT 2;");
var scan = Parser.QuickScan("SELECT COUNT(*) FROM users");

For repeated parsing calls, advanced operations, or more granular lifecycle management, instantiate Parser directly and dispose it when finished:

using var parser = new Parser();

var first = parser.Parse("SELECT * FROM users WHERE id = 1");
var second = parser.Normalize("SELECT * FROM users WHERE id = 2");
var third = parser.Fingerprint("SELECT * FROM users WHERE id = 3");

Capability Examples

Normalize and fingerprint queries so structurally similar statements can be grouped even when literal values differ:

var normalized = Parser.QuickNormalize("SELECT * FROM users WHERE id = 42");
var first = Parser.QuickFingerprint("SELECT * FROM users WHERE id = 1");
var second = Parser.QuickFingerprint("SELECT * FROM users WHERE id = 2");

Console.WriteLine(normalized.NormalizedQuery);
Console.WriteLine(first.Fingerprint == second.Fingerprint); // True for the same query shape

Split multi-statement SQL and inspect individual statements:

var split = Parser.QuickSplit("SELECT 1; INSERT INTO audit_log(action) VALUES ('login');");
foreach (var statement in split.Statements ?? Array.Empty<SqlStatement>())
{
    Console.WriteLine(statement.Statement);
}

Tokenize SQL for lightweight analysis of keywords, identifiers, and token positions:

var scan = Parser.QuickScan("SELECT COUNT(*) FROM users");
foreach (var token in scan.Tokens ?? Array.Empty<SqlToken>())
{
    Console.WriteLine($"{token.TokenKind}: {token.Text}");
}

Use async helpers when integrating with asynchronous application code:

var asyncResult = await ParserAsync.QuickParseAsync("SELECT * FROM orders WHERE created_at > now() - interval '1 day'");
Console.WriteLine(asyncResult.IsSuccess);

Npgquery also exposes protobuf parsing/deparsing and PL/pgSQL parsing for advanced scenarios that need a managed representation of PostgreSQL parser output.

Documentation

Visit the GitHub repository for complete documentation, examples, and API reference.

License

MIT License - see LICENSE file for details.

This library is built on libpg_query, which embeds the official PostgreSQL parser.