jrunner/CLAUDE.md
Paul Trowbridge 8cdd88d053 rename app module to jrunner for consistency
Changes:
- Rename app/ directory to jrunner/ (preserves git history)
- Update settings.gradle to reference jrunner module
- Update readme.md with new paths (jrunner/build/, /opt/jrunner)
- Update CLAUDE.md documentation with new file paths

Build outputs now named jrunner.zip, jrunner.jar, bin/jrunner instead
of generic "app" names. This makes the project structure clearer and
aligns module name with project name.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-06 21:53:08 -05:00

3.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

jrunner is a Java CLI tool for migrating data between databases. It reads data from a source database using SQL queries and writes it to a destination table, batching inserts for performance. The tool supports multiple database types via JDBC drivers including PostgreSQL, IBM AS/400, and Microsoft SQL Server.

Build and Test Commands

Build the project:

gradle build
# or use wrapper
./gradlew build

Run tests:

gradle test
# or use wrapper
./gradlew test

Build distribution package:

gradle build
# Creates jrunner/build/distributions/jrunner.zip

Deploy to /opt (as documented in readme.md):

sudo unzip jrunner/build/distributions/jrunner.zip -d /opt/
sudo ln -sf /opt/jrunner/bin/jrunner /usr/local/bin/jrunner

Architecture

Single-File Design

The entire application logic resides in jrunner/src/main/java/jrunner/jrunner.java. This is a monolithic command-line tool with no abstraction layers or separate modules.

Data Flow

  1. Parse command-line arguments (-scu, -scn, -scp for source; -dcu, -dcn, -dcp for destination)
  2. Read SQL query from file specified by -sq flag
  3. Connect to source and destination databases via JDBC
  4. Execute source query and fetch results (fetch size: 10,000 rows)
  5. Build batched INSERT statements (250 rows per batch)
  6. Execute batches against destination table specified by -dt flag
  7. Optionally clear target table before insert if -c flag is set

Type Handling

The tool includes explicit handling for different SQL data types in a switch statement (lines 229-312). Supported types include VARCHAR, TEXT, CHAR, CLOB, DATE, TIME, TIMESTAMP, and BIGINT. String types get quote escaping and optional trimming.

Database Drivers

JDBC drivers are configured in jrunner/build.gradle:

  • PostgreSQL: org.postgresql:postgresql:42.5.0
  • IBM AS/400 (JT400): net.sf.jt400:jt400:11.0
  • Microsoft SQL Server: com.microsoft.sqlserver:mssql-jdbc:9.2.0.jre8
  • SQL Server Integrated Auth: com.microsoft.sqlserver:mssql-jdbc_auth:9.2.0.x64

The AS/400 driver requires explicit Class.forName() registration (line 144).

Configuration

The project uses a YAML configuration format (run.yml) to specify database connections, SQL script paths, and runtime options. However, the main application currently uses command-line arguments instead of parsing this YAML file.

Command-line flags:

  • -scu - source JDBC URL
  • -scn - source username
  • -scp - source password
  • -dcu - destination JDBC URL
  • -dcn - destination username
  • -dcp - destination password
  • -sq - path to source SQL query file
  • -dt - fully qualified destination table name
  • -t - trim text fields (default: true)
  • -c - clear target table before insert (default: true)

Key Implementation Details

Batch Size

INSERT statements are batched at 250 rows (hardcoded at line 324). When the batch threshold is reached, sql is prepended with "INSERT INTO {table} VALUES" and executed.

Error Handling

SQLException handling prints stack trace and exits immediately with System.exit(0). There is no transaction rollback or partial failure recovery.

Performance Considerations

  • Result set fetch size is set to 10,000 rows (line 173)
  • Progress counter prints with carriage return for real-time updates
  • Timestamps captured at start (line 174) and end (line 368) for duration tracking