Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
415 changes: 415 additions & 0 deletions documentation/pgwire/c-and-cpp.md

Large diffs are not rendered by default.

202 changes: 108 additions & 94 deletions documentation/pgwire/c-sharp.md

Large diffs are not rendered by default.

81 changes: 47 additions & 34 deletions documentation/pgwire/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Go PGWire Guide
description:
Go clients for QuestDB PGWire protocol. Learn how to use the PGWire
protocol with Go for querying data.
protocol with Go for querying data.
---

QuestDB is tested with the following Go client:
Expand Down Expand Up @@ -87,23 +87,23 @@ import (
func main() {
// Connection string
connString := "postgres://admin:quest@localhost:8812/qdb"

// Create a context
ctx := context.Background()

// Connect to QuestDB
conn, err := pgx.Connect(ctx, connString)
if err != nil {
log.Fatalf("Unable to connect to database: %v", err)
}
defer conn.Close(ctx)

// Verify connection
err = conn.Ping(ctx)
if err != nil {
log.Fatalf("Unable to ping database: %v", err)
}

fmt.Println("Successfully connected to QuestDB!")
}
```
Expand Down Expand Up @@ -166,24 +166,24 @@ func main() {
log.Fatalf("Unable to connect to database: %v", err)
}
defer conn.Close(ctx)

rows, err := conn.Query(ctx, "SELECT * FROM trades LIMIT 10")
if err != nil {
log.Fatalf("Query failed: %v", err)
}
defer rows.Close()

for rows.Next() {
// Create a map to hold the row data
values, err := rows.Values()
if err != nil {
log.Fatalf("Error scanning row: %v", err)
}

// Print the row data
fmt.Println(values)
}

if err := rows.Err(); err != nil {
log.Fatalf("Error iterating rows: %v", err)
}
Expand Down Expand Up @@ -221,14 +221,14 @@ func main() {
log.Fatalf("Unable to connect to database: %v", err)
}
defer conn.Close(ctx)

// Execute a query
rows, err := conn.Query(ctx, "SELECT ts, symbol, price, amount FROM trades LIMIT 10")
if err != nil {
log.Fatalf("Query failed: %v", err)
}
defer rows.Close()

// Collect results
var trades []Trade
for rows.Next() {
Expand All @@ -238,12 +238,12 @@ func main() {
}
trades = append(trades, t)
}

// Check for errors from iterating over rows
if err := rows.Err(); err != nil {
log.Fatalf("Error iterating rows: %v", err)
}

// Print trades
for _, t := range trades {
fmt.Printf("Timestamp: %s, Symbol: %s, Price: %.2f, Amount: %.6f\n",
Expand Down Expand Up @@ -412,14 +412,14 @@ func main() {

// SAMPLE BY query (time-based downsampling)
sampleByQuery := `
SELECT
ts,
symbol,
avg(price) as avg_price,
min(price) as min_price,
max(price) as max_price
FROM trades
WHERE ts >= dateadd('d', -7, now())
SELECT
ts,
symbol,
avg(price) as avg_price,
min(price) as min_price,
max(price) as max_price
FROM trades
WHERE ts >= dateadd('d', -7, now())
SAMPLE BY 1h
`

Expand Down Expand Up @@ -519,10 +519,10 @@ func (c *QuestDBClient) Close() {
// GetRecentTrades fetches recent trades for a given symbol
func (c *QuestDBClient) GetRecentTrades(ctx context.Context, symbol string, limit int) ([]Trade, error) {
query := `
SELECT ts, symbol, price, amount
FROM trades
WHERE symbol = $1
ORDER BY ts DESC
SELECT ts, symbol, price, amount
FROM trades
WHERE symbol = $1
ORDER BY ts DESC
LIMIT $2
`

Expand Down Expand Up @@ -551,14 +551,14 @@ func (c *QuestDBClient) GetRecentTrades(ctx context.Context, symbol string, limi
// GetSampledData fetches downsampled price data
func (c *QuestDBClient) GetSampledData(ctx context.Context, symbol string, days int) ([]PriceSample, error) {
query := `
SELECT
ts,
symbol,
avg(price) as avg_price,
min(price) as min_price,
max(price) as max_price
FROM trades
WHERE symbol = $1 AND ts >= dateadd('d', $2, now())
SELECT
ts,
symbol,
avg(price) as avg_price,
min(price) as min_price,
max(price) as max_price
FROM trades
WHERE symbol = $1 AND ts >= dateadd('d', $2, now())
SAMPLE BY 1h
`

Expand Down Expand Up @@ -842,6 +842,19 @@ SELECT *
FROM trades LATEST ON timestamp PARTITION BY symbol
```

## Highly-Available Reads with QuestDB Enterprise

QuestDB Enterprise supports running [multiple replicas](https://questdb.com/docs/operations/replication/) to serve queries.
Client applications can specify **multiple hosts** in the connection string. This ensures that initial connections
succeed even if a node is down. If the connected node fails later, the application should catch the error, reconnect to
another host, and retry the read.

See our blog post for background and the companion repository for a minimal example:

- Blog: [Highly-available reads with QuestDB](https://questdb.com/blog/highly-available-reads-with-questdb/)
- Example: [questdb/questdb-ha-reads](https://github.com/questdb/questdb-ha-reads)


## Troubleshooting

### Connection Issues
Expand Down Expand Up @@ -872,4 +885,4 @@ For data ingestion, it's recommended to use QuestDB's first-party clients with t
high-throughput data insertion.

QuestDB's SQL extensions for time-series data, such as `SAMPLE BY` and `LATEST ON`, provide powerful tools for analyzing
time-series data that can be easily accessed through pgx.
time-series data that can be easily accessed through pgx.
17 changes: 15 additions & 2 deletions documentation/pgwire/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Java PGWire Guide
description:
Java clients for QuestDB PGWire protocol. Learn how to use the PGWire
protocol with Java for querying data.
protocol with Java for querying data.
---

QuestDB is tested with the following Java clients:
Expand Down Expand Up @@ -1214,6 +1214,19 @@ SELECT *
FROM trades LATEST ON timestamp PARTITIONED BY symbol
```

## Highly-Available Reads with QuestDB Enterprise

QuestDB Enterprise supports running [multiple replicas](https://questdb.com/docs/operations/replication/) to serve queries.
Client applications can specify **multiple hosts** in the connection string. This ensures that initial connections
succeed even if a node is down. If the connected node fails later, the application should catch the error, reconnect to
another host, and retry the read.

See our blog post for background and the companion repository for a minimal example:

- Blog: [Highly-available reads with QuestDB](https://questdb.com/blog/highly-available-reads-with-questdb/)
- Example: [questdb/questdb-ha-reads](https://github.com/questdb/questdb-ha-reads)


## Troubleshooting

### Connection Issues
Expand Down Expand Up @@ -1250,4 +1263,4 @@ For data ingestion, consider using QuestDB's first-party clients with the Influx
throughput.

Remember that QuestDB is optimized for time-series data, so make the most of its specialized time-series functions like
`SAMPLE BY` and `LATEST ON` for efficient queries.
`SAMPLE BY` and `LATEST ON` for efficient queries.
48 changes: 30 additions & 18 deletions documentation/pgwire/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: JavaScript PGWire Guide
description:
JavaScript clients for QuestDB PGWire protocol. Learn how to use the PGWire
protocol with JavaScript for querying data.
protocol with JavaScript for querying data.
---

QuestDB is tested with the following JavaScript clients:
Expand Down Expand Up @@ -134,7 +134,7 @@ queryData()
```

:::note
**Note**: The `pg` client uses the system timezone by default. QuestDB always sends timestamp in UTC.
**Note**: The `pg` client uses the system timezone by default. QuestDB always sends timestamp in UTC.
To set the timezone to UTC, you can set the `TZ` environment variable before running your script.
This is important for time-series data to ensure consistent timestamps.
:::
Expand Down Expand Up @@ -349,7 +349,7 @@ app.get('/api/stats', async (req, res) => {

try {
const result = await pool.query(`
SELECT
SELECT
symbol,
COUNT(*) as trade_count,
AVG(price) as avg_price,
Expand Down Expand Up @@ -501,10 +501,10 @@ async function parameterizedQuery() {

// Parameters are automatically sanitized
const trades = await sql`
SELECT * FROM trades
WHERE symbol = ${symbol}
AND ts >= ${startDate}
ORDER BY ts DESC
SELECT * FROM trades
WHERE symbol = ${symbol}
AND ts >= ${startDate}
ORDER BY ts DESC
LIMIT 10
`

Expand Down Expand Up @@ -602,15 +602,15 @@ app.get('/api/trades', async (req, res) => {

if (symbol) {
trades = await sql`
SELECT * FROM trades
WHERE symbol = ${symbol}
ORDER BY ts DESC
SELECT * FROM trades
WHERE symbol = ${symbol}
ORDER BY ts DESC
LIMIT ${limit}
`
} else {
trades = await sql`
SELECT * FROM trades
ORDER BY ts DESC
SELECT * FROM trades
ORDER BY ts DESC
LIMIT ${limit}
`
}
Expand All @@ -628,7 +628,7 @@ app.get('/api/stats', async (req, res) => {

try {
const stats = await sql`
SELECT
SELECT
symbol,
COUNT(*) as trade_count,
AVG(price) as avg_price,
Expand Down Expand Up @@ -692,7 +692,7 @@ async function sampleByQuery() {
await client.connect()

const result = await client.query(`
SELECT
SELECT
ts,
symbol,
avg(price) as avg_price,
Expand All @@ -703,7 +703,7 @@ async function sampleByQuery() {
SAMPLE BY 1h
`)
console.log(`Got ${result.rows.length} hourly samples`)

for (const row of result.rows) {
console.log(`${row.ts} - ${row.symbol}: Avg: ${row.avg_price}, Range: ${row.min_price} - ${row.max_price}`)
}
Expand Down Expand Up @@ -756,6 +756,18 @@ async function latestByQuery() {
latestByQuery()
```

## Highly-Available Reads with QuestDB Enterprise

QuestDB Enterprise supports running [multiple replicas](https://questdb.com/docs/operations/replication/) to serve queries.
Client applications can specify **multiple hosts** in the connection string. This ensures that initial connections
succeed even if a node is down. If the connected node fails later, the application should catch the error, reconnect to
another host, and retry the read.

See our blog post for background and the companion repository for a minimal example:

- Blog: [Highly-available reads with QuestDB](https://questdb.com/blog/highly-available-reads-with-questdb/)
- Example: [questdb/questdb-ha-reads](https://github.com/questdb/questdb-ha-reads)


## Troubleshooting

Expand All @@ -774,15 +786,15 @@ For query-related errors:

1. Verify that the table you're querying exists
2. Check the syntax of your SQL query
3. Ensure that you're using the correct data types for parameters, this can be tricky with JavaScript where
all numbers are floats. You may need to cast them explicitly in your SQL query.
3. Ensure that you're using the correct data types for parameters, this can be tricky with JavaScript where
all numbers are floats. You may need to cast them explicitly in your SQL query.

## Conclusion

QuestDB's support for the PostgreSQL Wire Protocol allows you to use standard JavaScript PostgreSQL clients for querying
time-series data. Both `pg` and `postgres` clients offer good performance and features for working with QuestDB.

We recommend the `pg` client for querying.
We recommend the `pg` client for querying.
For data ingestion, consider QuestDB's first-party clients with the InfluxDB Line Protocol (ILP) for maximum
throughput.

Expand Down
13 changes: 13 additions & 0 deletions documentation/pgwire/pgwire-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,16 @@ The PostgreSQL wire protocol has different implementations and options. When you
client library allows, prefer the Extended Query Protocol over the Simple Query Protocol. Additionally, for optimal
performance and type fidelity, choose clients that support BINARY encoding for data transfer over TEXT encoding
whenever possible. The specifics of how to configure this will vary by client library.


### Highly-Available Reads with QuestDB Enterprise

QuestDB Enterprise supports running [multiple replicas](https://questdb.com/docs/operations/replication/) to serve queries.
Many client libraries allow specifying **multiple hosts** in the connection string. This ensures that initial connections
succeed even if a node is unavilable. If the connected node fails later, the application should catch the error, reconnect to
another host, and retry the read.

For background and code samples in multiple languages, see:

- Blog: [Highly-available reads with QuestDB](https://questdb.com/blog/highly-available-reads-with-questdb/)
- Examples: [questdb/questdb-ha-reads](https://github.com/questdb/questdb-ha-reads)
Loading