Skip to content
Merged
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ clickhouse/
├── materialized_views/ # Materialized view definitions
├── queries/ # Saved queries
└── seed/ # Seed data / INSERT statements
postgres/
├── tables/ # Table definitions (CREATE TABLE ...)
├── views/ # View definitions (CREATE VIEW ...)
├── functions/ # Function / procedure definitions (CREATE FUNCTION ...)
├── queries/ # Saved queries
└── seed/ # Seed data / INSERT statements
```

### Running queries
Expand Down
64 changes: 56 additions & 8 deletions crates/clickhousectl/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub fn project_dir() -> PathBuf {
.join("clickhouse")
}

pub fn postgres_project_dir() -> PathBuf {
std::env::current_dir()
.expect("failed to get current directory")
.join("postgres")
}

pub fn is_initialized() -> bool {
local_dir().exists()
}
Expand All @@ -28,17 +34,21 @@ pub fn init() -> Result<()> {
eprintln!("Initialized ClickHouse project in {}", dir.display());
}

create_project_scaffold()?;
create_project_scaffold(
project_dir(),
&["tables", "materialized_views", "queries", "seed"],
)?;
create_project_scaffold(
postgres_project_dir(),
&["tables", "views", "functions", "queries", "seed"],
)?;

Ok(())
}

fn create_project_scaffold() -> Result<()> {
let dir = project_dir();
let subdirs = ["tables", "materialized_views", "queries", "seed"];

fn create_project_scaffold(dir: PathBuf, subdirs: &[&str]) -> Result<()> {
let mut created = false;
for subdir in &subdirs {
for subdir in subdirs {
let path = dir.join(subdir);
if !path.exists() {
std::fs::create_dir_all(&path)?;
Expand All @@ -49,8 +59,9 @@ fn create_project_scaffold() -> Result<()> {

if created {
eprintln!(
"Created project scaffold in {}/ (tables, materialized_views, queries, seed)",
dir.display()
"Created project scaffold in {}/ ({})",
dir.display(),
subdirs.join(", ")
);
}

Expand All @@ -61,3 +72,40 @@ fn create_project_scaffold() -> Result<()> {
pub fn server_flags() -> Vec<String> {
vec!["--".into(), "--path=./".into()]
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn scaffold_creates_subdirs_with_gitkeep() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().join("postgres");
let subdirs = ["tables", "materialized_views", "queries", "seed"];

create_project_scaffold(dir.clone(), &subdirs).unwrap();

for subdir in &subdirs {
let path = dir.join(subdir);
assert!(path.is_dir(), "{} should be a directory", path.display());
assert!(
path.join(".gitkeep").is_file(),
"{}/.gitkeep should exist",
path.display()
);
}
}

#[test]
fn scaffold_is_idempotent() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().join("clickhouse");
let subdirs = ["tables", "queries"];

create_project_scaffold(dir.clone(), &subdirs).unwrap();
// Running again over an existing scaffold must not error.
create_project_scaffold(dir.clone(), &subdirs).unwrap();

assert!(dir.join("tables").join(".gitkeep").is_file());
}
}
7 changes: 4 additions & 3 deletions crates/clickhousectl/src/local/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ CONTEXT FOR AGENTS:
/// Initialize a project-local ClickHouse configuration
#[command(after_help = "\
CONTEXT FOR AGENTS:
Creates a .clickhouse/ directory (runtime data, git-ignored) and a clickhouse/ project
scaffold with subdirs: tables/, materialized_views/, queries/, seed/ (each with .gitkeep).
The clickhouse/ directory is meant to be committed — organize your SQL files there.
Creates a .clickhouse/ directory (runtime data, git-ignored) plus clickhouse/ and postgres/
project scaffolds (each subdir has a .gitkeep). clickhouse/: tables/, materialized_views/,
queries/, seed/. postgres/: tables/, views/, functions/, queries/, seed/. The clickhouse/ and
postgres/ directories are meant to be committed — organize your SQL files there.
Related: `clickhousectl local server start` to start a server with project-local data.")]
Init,

Expand Down