All skills
clickhouse avatar

/chdb-datastore

@46ef08c official
by clickhouseclickhouse/agent-skills543 stars
39

Use when the user has tabular data (pandas DataFrame, parquet, csv, Arrow, json) and wants to filter, group, aggregate, join, or speed up slow pandas. Provides chDB DataStore — same pandas API, ClickHouse engine underneath. Also handles reading from S3, MySQL, PostgreSQL, MongoDB, ClickHouse Cloud, Iceberg, Delta Lake as DataFrames and joining across sources. TRIGGER when: user mentions DataFrame, parquet, csv, "fast pandas", "speed up pandas", or cross-source DataFrame joins; user imports `chdb.datastore` or `from datastore import DataStore`. SKIP this skill for raw SQL syntax (use chdb-sql instead), ClickHouse server administration, or non-Python DataStore API work.

Use this Skill: https://skilld.dev/gh/clickhouse/agent-skills/chdb-datastore

This session only. Nothing lands on disk.

examplesexamples.md

≈2.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

DataStore Examples

All examples are self-contained and runnable. Expected output is shown in comments.

Table of Contents

  1. Pandas Replacement: One Import Change
  2. Analyze Local Files
  3. Cross-Source Join: MySQL + Parquet
  4. Cross-Source Join: S3 + PostgreSQL
  5. Three-Way Join: File + Database + Cloud
  6. Data Lake Formats: Iceberg, Delta, Hudi
  7. URI Shorthand Access
  8. Cloud Storage Variants (S3/GCS/Azure/HDFS)
  9. Cross-Source Write
  10. Explore Remote Schema
  11. Common Errors & Fixes

1. Pandas Replacement: One Import Change

The simplest way to use chdb — change one line, keep everything else:

# Before (standard pandas):
# import pandas as pd

# After (chdb-accelerated):
import chdb.datastore as pd

df = pd.DataStore({"name": ["Alice", "Bob", "Carol", "Dave"],
                   "dept": ["Eng", "Sales", "Eng", "Sales"],
                   "salary": [95000, 72000, 110000, 68000]})

# Same pandas API — everything works
result = (df[df["salary"] > 70000]
    .groupby("dept")
    .agg({"salary": ["mean", "count"]})
    .sort_values("mean", ascending=False))

print(result)
# Expected output:
#     dept  mean  count
# 0    Eng  102500    2
# 1  Sales   72000    1

Why it's faster: Operations compile to ClickHouse SQL and execute as a single optimized query, instead of step-by-step Python evaluation.


2. Analyze Local Files

from datastore import DataStore

# Parquet — pandas-style analysis
ds = DataStore.from_file("sales.parquet")
top_products = (ds[ds['revenue'] > 0]
    .groupby('product')
    .agg({'revenue': 'sum', 'quantity': 'sum'})
    .sort_values('revenue', ascending=False)
    .head(10))
print(top_products)

# CSV with filtering
ds = DataStore.from_file("employees.csv")
senior = ds[(ds['years'] > 5) & (ds['dept'] == 'Engineering')]
print(senior[['name', 'title', 'salary']].sort_values('salary', ascending=False))

# Glob pattern — query all matching files at once
ds = DataStore.from_file("logs/2024-*.csv")
errors = ds[ds['level'] == 'ERROR'].groupby('module')['message'].count()
print(errors.sort_values(ascending=False))

# See the SQL behind any query
print(top_products.to_sql())

3. Cross-Source Join: MySQL + Parquet

from datastore import DataStore

customers = DataStore.from_mysql(
    host="db:3306", database="crm", table="customers",
    user="reader", password="pass")

orders = DataStore.from_file("orders.parquet")

result = (customers
    .join(orders, left_on="id", right_on="customer_id", how="inner")
    .groupby("country")
    .agg({"amount": ["sum", "mean"], "order_id": "count"})
    .sort_values("sum", ascending=False))

print(result)
# Expected: country-level order summary with total, average, and count

print(result.to_sql())
# Shows the cross-source SQL generated by chdb

4. Cross-Source Join: S3 + PostgreSQL

from datastore import DataStore

events = DataStore.from_s3(
    "s3://analytics/events/2024-*.parquet",
    access_key_id="AKIA...", secret_access_key="secret...")

profiles = DataStore.from_postgresql(
    host="pg.example.com:5432", database="users",
    table="profiles", user="analyst", password="pass")

result = (events
    .join(profiles, left_on="user_id", right_on="id")
    .filter(events['event_type'] == 'purchase')
    .groupby(["country", "age_group"])
    .agg({"amount": "sum", "event_id": "count"})
    .sort_values("sum", ascending=False))

print(result)
# Expected: purchase events aggregated by country and age group

5. Three-Way Join: File + Database + Cloud

from datastore import DataStore

products = DataStore.from_file("products.csv")
orders = DataStore.from_mysql(
    host="db:3306", database="shop", table="orders",
    user="root", password="pass")
reviews = DataStore.from_s3("s3://feedback/reviews.parquet", nosign=True)

result = (orders
    .join(products, left_on="product_id", right_on="id")
    .join(reviews, left_on="product_id", right_on="product_id")
    .groupby("category")
    .agg({"amount": "sum", "rating": "mean", "review_id": "count"})
    .sort_values("sum", ascending=False))

print(result)
# Expected: category-level summary combining order amounts, review ratings, and counts

6. Data Lake Formats: Iceberg, Delta, Hudi

from datastore import DataStore

# Apache Iceberg on S3
ds = DataStore.from_iceberg(
    "s3://warehouse/iceberg/events",
    access_key_id="KEY", secret_access_key="SECRET")
print(ds.head(10))

# Delta Lake
ds = DataStore.from_delta(
    "s3://warehouse/delta/transactions",
    access_key_id="KEY", secret_access_key="SECRET")
summary = (ds.groupby("category")
    .agg({"amount": "sum"})
    .sort_values("sum", ascending=False))
print(summary)

# Hudi
ds = DataStore.from_hudi(
    "s3://warehouse/hudi/logs",
    access_key_id="KEY", secret_access_key="SECRET")
errors = ds[ds['level'] == 'ERROR']
print(errors.head(20))

7. URI Shorthand Access

from datastore import DataStore

# One-liner for any source
ds = DataStore.uri("sales.parquet")
ds = DataStore.uri("s3://public-data/dataset.parquet?nosign=true")
ds = DataStore.uri("mysql://root:pass@localhost:3306/shop/orders")
ds = DataStore.uri("postgresql://analyst:pass@pg:5432/analytics/events")
ds = DataStore.uri("clickhouse://ch:9440/analytics/hits?user=reader&password=pass")
ds = DataStore.uri("mongodb://user:pass@mongo:27017/logs.app_events")
ds = DataStore.uri("sqlite:///data/local.db?table=users")
ds = DataStore.uri("deltalake:///data/delta/events")

# After creating from any source, same pandas API
result = (ds[ds['value'] > 100]
    .groupby('category')
    .sum()
    .sort_values('value', ascending=False))
print(result)

8. Cloud Storage Variants

from datastore import DataStore

# AWS S3 (private)
ds = DataStore.from_s3("s3://my-bucket/data.parquet",
    access_key_id="AKIA...", secret_access_key="secret...")

# AWS S3 (public)
ds = DataStore.from_s3("s3://public-data/dataset.parquet", nosign=True)

# Google Cloud Storage
ds = DataStore.from_gcs("gs://my-bucket/data.parquet",
    hmac_key="KEY", hmac_secret="SECRET")
ds = DataStore.from_gcs("gs://public-bucket/data.parquet", nosign=True)

# Azure Blob Storage
ds = DataStore.from_azure(
    connection_string="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...",
    container="data", path="analytics/events.parquet")

# HDFS
ds = DataStore.from_hdfs("hdfs://namenode:9000/warehouse/events/*.parquet")

9. Cross-Source Write

from datastore import DataStore

# Read from MySQL, transform, write to Parquet
source = DataStore.from_mysql(
    host="db:3306", database="shop", table="orders",
    user="root", password="pass")
target = DataStore("file", path="output/orders_summary.parquet", format="Parquet")

target.insert_into("category", "total_revenue", "order_count").select_from(
    source
        .groupby("category")
        .select("category", "sum(amount) AS total_revenue", "count() AS order_count")
        .filter(source['amount'] > 0)
).execute()

# Read from S3, filter, write to local file
source = DataStore.from_s3("s3://logs/events.parquet", nosign=True)
target = DataStore("file", path="filtered_events.parquet", format="Parquet")

target.insert_into("user_id", "event_type", "ts").select_from(
    source.select("user_id", "event_type", "ts")
          .filter(source['event_type'] == 'error')
).execute()

10. Explore Remote Schema

from datastore import DataStore

# Connect to MySQL and browse the schema
mysql_ds = DataStore.from_mysql(
    host="db:3306", database="ecommerce",
    user="analyst", password="pass")

print(mysql_ds.databases())       # list all databases
print(mysql_ds.tables("ecommerce"))  # list tables in a database

# Quick preview of a specific table
orders = DataStore.from_mysql(
    host="db:3306", database="ecommerce",
    table="orders", user="analyst", password="pass")

print(orders.columns)      # → ['id', 'customer_id', 'amount', ...]
print(orders.dtypes)        # → {'id': 'UInt64', 'amount': 'Float64', ...}
print(orders.describe())    # → statistics for numeric columns
print(orders.head(5))       # → first 5 rows

11. Common Errors & Fixes

File not found

from datastore import DataStore

# Error: file not found
ds = DataStore.from_file("nonexistent.parquet")
# → Exception: FILE_NOT_FOUND

# Fix: check the path
import os
print(os.path.exists("nonexistent.parquet"))  # → False
ds = DataStore.from_file("data/sales.parquet")  # use correct path

Database host without port

# Error: connection timeout / refused
ds = DataStore.from_mysql(host="db", database="shop", table="orders",
    user="root", password="pass")
# → Connection refused

# Fix: include port in host string
ds = DataStore.from_mysql(host="db:3306", database="shop", table="orders",
    user="root", password="pass")

Join key type mismatch

# Error: join returns empty or wrong results
users = DataStore({"id": [1, 2, 3], "name": ["Alice", "Bob", "Carol"]})     # id is Int
orders = DataStore({"user_id": ["1", "2", "3"], "amount": [100, 200, 300]}) # user_id is String

result = users.join(orders, left_on="id", right_on="user_id")
print(result)  # → empty or incorrect

# Fix: ensure matching types — use .to_sql() to diagnose
print(result.to_sql())  # reveals the type mismatch in the JOIN condition
# Cast in source data, or use assign() to convert types before joining

Debugging with .to_sql()

from datastore import DataStore

ds = DataStore.from_file("sales.parquet")
result = (ds[ds['revenue'] > 1000]
    .groupby('product')
    .agg({'revenue': 'sum'})
    .sort_values('revenue', ascending=False)
    .head(10))

# See exactly what SQL will execute
print(result.to_sql())
# Output:
# SELECT "product", sum("revenue") AS "revenue"
# FROM file('sales.parquet', Parquet)
# WHERE "revenue" > 1000
# GROUP BY "product"
# ORDER BY "revenue" DESC
# LIMIT 10

Source: SKILL.md on GitHub

No alerts17d4 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill is a legitimate tool provided by ClickHouse Inc to use the chdb DataStore API, which is an optimized, ClickHouse-backed replacement for the pandas library. It allows users to perform high-performance data analysis on various sources including local files (CSV, Parquet), cloud storage (S3, GCS), and databases (MySQL, PostgreSQL). The analysis found no evidence of malicious behavior, prompt injection, or unauthorized data exfiltration. All external resources and packages trace back to the official vendor infrastructure.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 46ef08c. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated 4 months ago
compatibility
Requires Python 3.9+, macOS or Linux. pip install chdb.
Other metadata
metadata
{
  "author": "chdb-io",
  "version": "4.1",
  "homepage": "https://clickhouse.com/docs/chdb"
}
  • chdb
  • clickhouse
  • pandas
  • dataframe
  • parquet
  • csv
  • s3
  • mysql
  • postgresql
  • mongodb
  • lazy-evaluation
  • sql
  • data-analysis

README badge

README badge for clickhouse/agent-skills/chdb-datastore

Provides chdb DataStore, a ClickHouse-backed pandas replacement with the same API but lazy evaluation and SQL compilation underneath. Load tabular data from files, S3, MySQL, PostgreSQL, MongoDB, or other sources as DataFrames, then filter, group, aggregate, and join across sources using familiar pandas syntax — typically faster than pandas for large datasets.

Generated from the current SKILL.md.

Does DataStore work with my existing pandas code?
Yes. DataStore implements the pandas API — you can often replace `import pandas as pd` with `import chdb.datastore as pd` and keep the rest of your code unchanged. Operations are lazy and compile to SQL under the hood.
What data sources does DataStore support?
DataStore connects to 16+ sources including local files (parquet, csv, json, arrow, orc, avro, tsv, xml), MySQL, PostgreSQL, MongoDB, ClickHouse Cloud, S3, Iceberg, and Delta Lake. Use `.from_file()`, `.from_mysql()`, `.from_s3()`, or the `.uri()` shorthand to auto-detect the source.
Can I join data across different sources?
Yes. Create separate DataStore instances for each source and use `.join()` to combine them. The skill includes examples of joining data from MySQL, parquet files, and S3 in a single query.
What Python versions does this require?
Python 3.9+, and only works on macOS or Linux. Install with `pip install chdb`.
Should I use this skill for raw SQL queries?
No. Use the chdb-sql skill instead. This skill is for the DataStore pandas-compatible API. If you need raw SQL syntax, switch to chdb-sql.

Generated from the current SKILL.md. These answers refresh after source changes.