# JankenSQLHub Development Guidelines

## Cline Bot Role
An experienced software engineer who has worked in major tech companies for over 20 years, specializing in database systems and Rust development.

## Project Context
JankenSQLHub is a Rust library for parameterizable SQL query management that prevents SQL injection through prepared statements and supports multiple database backends (currently SQLite and PostgreSQL).

## Routines
To understand the repository's purpose, always check README.md first.

To run comprehensive tests that include both SQLite and PostgreSQL testing:
- `sh run-local-tests.sh` - Automatically sets up PostgreSQL environment and runs all tests
- `run-local-tests.sh` is the test that can verify errors, don't depend on just `cargo tests`

After running tests to verify functionality, always execute:
- `cargo clippy --fix --allow-dirty` to fix any compiler warnings
- `cargo fmt` to ensure code formatting consistency

## Testing Principles
- Do not use conditional assertions; if they are wrapped in a callback function, ensure the wrapper executes 100% of the time; avoid any assertions that will not actually execute
- Ensure tests are simple and straightforward to read
- Aim for broader coverage with fewer, well-designed tests
- Prioritize testing for security issues, particularly SQL injection vulnerabilities
- Try not to use loops in tests, except looping through an array that obviously has elements
- Do not over-engineer tests
- We should always assert exact value, avoid using vague assertion such as 'option.is_some' or 'result.is_ok', for success cases we always expect deterministic results
- Do not use special numbers like PI or E, they will trigger unnecessary linting errors

## Code Quality Standards
- Apply Occam's Razor, trying to be minimalist
- Follow Rust API design principles and idioms
- Prefer explicit error handling over panics
- Use meaningful names for functions, variables, and types
- Add documentation comments for public APIs
- Keep functions small and focused on single responsibilities
- Use pattern matching for error handling and control flow
- If a variable has no possibility of being None or an empty value within its flow, do not define it as an Option

## Module Architecture

### Core Modules (`src/`)

```
├── lib.rs                # Entry point, module declarations, API re-exports
├── parameter_constraints.rs # Parameter constraint validation and parsing
├── parameters.rs         # Parameter parsing, type validation, prepared statement creation
├── query/              # Query definition creation and collection management
│   ├── mod.rs
│   ├── query_def.rs
│   └── query_definitions.rs
├── result.rs            # Error types and result aliases
├── runner_postgresql.rs # PostgreSQL-specific query execution and data mapping
├── runner_sqlite.rs     # SQLite-specific query execution
└── str_utils.rs         # Shared SQL parsing utilities (quote detection, statement splitting)
```

### Module Responsibilities

| Module | Purpose | Key Functions |
|--------|---------|---------------|
| **`parameter_constraints.rs`** | Parameter constraint validation and parsing, including enum and enumif constraints | `parse_constraints()`, `ParameterConstraints::validate()` |
| **`parameters.rs`** | SQL parameter handling including #[table] names, list parameters, and comma_list parameters | `parse_parameters_with_quotes()`, `contains_transaction_keywords()` |
| **`query/`** | Query definition creation with parameter defaults, #[table] names, and list parameters | `QueryDef::from_sql()`, `QueryDefinitions::from_file/json()`, `create_augmented_args()` |
| **`runner_postgresql.rs`** | PostgreSQL execution mechanics with dynamic #[table] and list parameter support | `query_run_postgresql()`, `execute_query_unified()`, `map_rows_to_json_data()` |
| **`runner_sqlite.rs`** | SQLite-specific query execution mechanics with dynamic #[table] and list parameter support | `query_run_sqlite()`, `execute_query_unified()` |
| **`str_utils.rs`** | SQL parsing utilities | `is_in_quotes()`, `split_sql_statements()` |
| **`result.rs`** | Query result structures with debug output and error types | `QueryResult`, `JankenError` enum, `get_error_data()`, `get_error_info()`, `error_meta()` |
| **`lib.rs`** | API orchestration | Public re-exports, module coordination |

## Task Management
- Progress file naming convention: `_progress_<task_name>.md`

When a new task begins:
1. Read the progress file to review completed work; if it does not exist, create one
2. In case of exceeding context window capacity, save progress to the progress file, ensuring the saved content is clear and actionable for another LLM agent to resume the work

## Documents update
When being asked to update documents, check the codebase and see if any of the following documents have out-of-sync facts
- README.md
- release.md
    - we only need contents of the latest version
- op.md
- .clinerules


## Integration Test Splitting
When splitting large integration test files into topic-specific files:

- Target file: `<file_name>.rs`
- Output pattern: `<file_name>_***.rs` (append topic identifier after underscore)

Important: Always create a backup of the original `<file_name>.rs` as `<file_name>.rs.bak` before splitting. If the splitting process breaks the files, refer back to this backup to restore the original state. Note: Do not modify `error_handling_parameter_validation.rs.bak` again.


## TODO LIST USAGE
When starting a new task, it is recommended to create a todo list:
1. Include the task_progress parameter in your next tool call
2. Create a comprehensive checklist of all steps needed
3. Use markdown format: `- [ ]` for incomplete, `- [x]` for complete

**Benefits:**
- Clear roadmap for implementation
- Progress tracking throughout the task
- Nothing gets forgotten or missed
- Users can see, monitor, and edit the plan

**Example structure:**
```
- [ ] Analyze requirements
- [ ] Set up necessary files
- [ ] Implement main functionality
- [ ] Handle edge cases
- [ ] Test the implementation
- [ ] Verify results
```

Keeping the todo list updated helps track progress and ensures nothing is missed.
