Skip to content

Conversation

@DaxServer
Copy link
Owner

This commit introduces a new LowercaseConversionService that provides
functionality to perform lowercase conversion operations on a specified
table and column. The key changes are:

  • Implement the LowercaseConversionService class that extends the
    ColumnOperationService base class
  • Provide the performOperation method to execute the lowercase
    conversion on the specified table and column
  • Implement the buildParameterizedUpdateQuery method to construct a
    parameterized UPDATE query for the lowercase conversion
  • Implement the countAffectedRows method to count the number of rows
    that would be affected by the lowercase conversion

These changes enable the application to perform efficient and safe
lowercase conversion operations on database columns.

This commit introduces a new `LowercaseConversionService` that provides
functionality to perform lowercase conversion operations on a specified
table and column. The key changes are:

- Implement the `LowercaseConversionService` class that extends the
  `ColumnOperationService` base class
- Provide the `performOperation` method to execute the lowercase
  conversion on the specified table and column
- Implement the `buildParameterizedUpdateQuery` method to construct a
  parameterized UPDATE query for the lowercase conversion
- Implement the `countAffectedRows` method to count the number of rows
  that would be affected by the lowercase conversion

These changes enable the application to perform efficient and safe
lowercase conversion operations on database columns.
@coderabbitai
Copy link

coderabbitai bot commented Sep 29, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added lowercase conversion for column data, including a new API endpoint and a functional “To lowercase” menu action with success/warning feedback and completion events.
  • Documentation

    • Updated route documentation to include tags for consistency.
  • Tests

    • Added comprehensive tests for the lowercase conversion API and service, covering success, validation errors, edge cases, and no-op scenarios.
    • Minor formatting adjustments to existing uppercase tests.

Walkthrough

Adds a lowercase conversion feature across backend and frontend: new POST route /api/project/:projectId/lowercase, a LowercaseConversionService, comprehensive API and service tests, and a frontend menu handler to invoke the operation. Minor doc/tag tweak on uppercase route and trivial formatting in existing uppercase code/tests.

Changes

Cohort / File(s) Summary
Backend API routes
backend/src/api/project/index.ts
Adds POST /:projectId/lowercase endpoint: validates column, invokes LowercaseConversionService.performOperation, returns { affectedRows }; adds tags to uppercase route doc; imports new service.
Backend services (lower/upper)
backend/src/services/lowercase-conversion.service.ts, backend/src/services/uppercase-conversion.service.ts
New LowercaseConversionService extending ColumnOperationService; builds parameterized UPDATE using LOWER() and counts affected rows. Uppercase service unchanged except trailing newline.
Backend API tests
backend/tests/api/project/lowercase.test.ts, backend/tests/api/project/uppercase.test.ts
New lowercase API test suite covering success, validation (400/422), mixed-case scenarios, no-op cases. Uppercase test minor assertion formatting only.
Backend service tests
backend/tests/services/lowercase-conversion.service.test.ts, backend/tests/services/uppercase-conversion.service.test.ts
New comprehensive tests for lowercase service (mixed/empty/null/unicode/special chars, missing table/column). Uppercase service tests reflowed formatting and import order only.
Frontend column menu
frontend/src/features/data-processing/components/ColumnHeaderMenu.vue
Adds handleLowerCase to call API, show success/warning messages, and emit replaceCompleted when changes occur; wires “To lowercase” menu to new handler.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as ColumnHeaderMenu.vue
  participant API as POST /api/project/:projectId/lowercase
  participant SVC as LowercaseConversionService
  participant DB as Database

  UI->>API: Request { projectId, column }
  API->>API: Validate projectId, column, column existence
  alt Column missing
    API-->>UI: 400 ApiError { message: "Column not found" }
  else Valid
    API->>SVC: performOperation({ table, column })
    SVC->>DB: UPDATE table SET col=LOWER(col) WHERE col IS NOT NULL AND col != LOWER(col)
    SVC->>DB: SELECT COUNT(*) of affected rows (or use update result)
    SVC-->>API: affectedRows
    API-->>UI: 200 { affectedRows }
  end
Loading
sequenceDiagram
  autonumber
  participant User as User
  participant UI as ColumnHeaderMenu.vue
  participant API as /project/:id/lowercase

  User->>UI: Click "To lowercase"
  UI->>API: POST { column }
  alt Success (affectedRows > 0)
    API-->>UI: { affectedRows }
    UI->>User: Show success message
    UI->>UI: emit("replaceCompleted")
  else Success (0 rows)
    API-->>UI: { affectedRows: 0 }
    UI->>User: Show no-changes warning
  end
  opt Validation/Error
    API-->>UI: 4xx/5xx ApiError
    UI->>User: Show error message
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The pull request title "feat(uppercase-conversion): Implement lowercase conversion service" contains an incorrect prefix. The title uses "uppercase-conversion" but the entire changeset is about implementing lowercase conversion functionality, including the LowercaseConversionService class, lowercase API endpoint, and related tests. This appears to be a copy-paste error where the prefix was not updated from a similar uppercase feature. While the second part of the title ("Implement lowercase conversion service") correctly describes the main change, the misleading prefix makes the title confusing and could cause issues when scanning commit history. Update the title prefix from "feat(uppercase-conversion)" to "feat(lowercase-conversion)" to accurately reflect the feature being implemented. The corrected title should be "feat(lowercase-conversion): Implement lowercase conversion service" to properly describe this changeset and maintain consistency in the commit history.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed The pull request description accurately describes the main changes in this PR. It explains the introduction of the LowercaseConversionService class, its extension of ColumnOperationService, and the key methods implemented (performOperation, buildParameterizedUpdateQuery, and countAffectedRows). While the description focuses primarily on the backend service implementation and doesn't mention the API endpoint, frontend changes, or comprehensive test suite additions, it does cover the core functionality being added. The description is related to and representative of the changeset's primary purpose.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lowercase-conversion-service

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Tip

🧪 Early access (models): enabled

We are currently testing Sonnet 4.5 code review models, which should lead to better review quality. However, this model may result in higher noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
backend/src/services/lowercase-conversion.service.ts (1)

4-42: Optional: Consider abstracting case-conversion logic.

LowercaseConversionService and UppercaseConversionService share near-identical structure, differing only in the SQL function (LOWER vs UPPER). If additional case transformations are planned (e.g., title case), consider a parameterized base class or factory.

This is a nice-to-have refactor—the current approach is clear and maintainable.

backend/src/api/project/index.ts (1)

730-733: Consider extracting the column existence check into a shared helper.

The column existence validation is duplicated across multiple endpoints (replace, trim_whitespace, uppercase, and now lowercase). Extracting this into a reusable function or middleware would reduce duplication and centralize the validation logic.

Example approach:

// In a shared utilities file
async function validateColumnExists(
  db: DuckDBConnection,
  table: string,
  column: string
): Promise<boolean> {
  const reader = await db.runAndReadAll(
    'SELECT 1 FROM information_schema.columns WHERE table_name = ? AND column_name = ?',
    [table, column]
  )
  return reader.getRows().length > 0
}

Then in each endpoint:

-      const columnExistsReader = await db().runAndReadAll(
-        'SELECT 1 FROM information_schema.columns WHERE table_name = ? AND column_name = ?',
-        [table, column],
-      )
-
-      if (columnExistsReader.getRows().length === 0) {
+      if (!(await validateColumnExists(db(), table, column))) {
         return status(
           400,
           ApiErrorHandler.validationErrorWithData('Column not found', [

This refactor can be deferred to a future PR focused on reducing duplication across the codebase.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a44a8a1 and e26e1dd.

📒 Files selected for processing (8)
  • backend/src/api/project/index.ts (2 hunks)
  • backend/src/services/lowercase-conversion.service.ts (1 hunks)
  • backend/src/services/uppercase-conversion.service.ts (1 hunks)
  • backend/tests/api/project/lowercase.test.ts (1 hunks)
  • backend/tests/api/project/uppercase.test.ts (1 hunks)
  • backend/tests/services/lowercase-conversion.service.test.ts (1 hunks)
  • backend/tests/services/uppercase-conversion.service.test.ts (7 hunks)
  • frontend/src/features/data-processing/components/ColumnHeaderMenu.vue (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
backend/tests/services/lowercase-conversion.service.test.ts (2)
backend/src/services/lowercase-conversion.service.ts (1)
  • LowercaseConversionService (4-43)
backend/src/plugins/database.ts (3)
  • initializeDb (8-48)
  • getDb (50-55)
  • closeDb (57-63)
backend/tests/api/project/lowercase.test.ts (1)
backend/src/plugins/database.ts (2)
  • initializeDb (8-48)
  • closeDb (57-63)
backend/src/services/lowercase-conversion.service.ts (1)
backend/src/services/column-operation.service.ts (1)
  • ColumnOperationParams (3-6)
backend/src/api/project/index.ts (4)
backend/src/types/error-handler.ts (1)
  • ApiErrorHandler (6-211)
backend/src/services/lowercase-conversion.service.ts (1)
  • LowercaseConversionService (4-43)
backend/src/api/project/schemas.ts (2)
  • ColumnNameSchema (54-59)
  • AffectedRowsSchema (61-63)
backend/src/types/error-schemas.ts (2)
  • ApiErrors (20-26)
  • ApiErrors (27-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (28)
backend/src/services/uppercase-conversion.service.ts (1)

43-43: LGTM! Trailing newline added.

Standard formatting—no functional impact.

backend/tests/services/uppercase-conversion.service.test.ts (2)

1-1: LGTM! Import reordering.

Formatting adjustment with no functional impact.


42-47: LGTM! Formatting adjustments.

Multi-line formatting of assertions and single-line runAndReadAll calls improve consistency. No logic changes.

Also applies to: 50-50, 79-84, 87-87, 123-123, 172-177, 202-207, 210-210, 242-247, 250-250

backend/tests/api/project/uppercase.test.ts (1)

114-122: LGTM! Formatting adjustment.

Multi-line formatting of the assertion improves readability. No functional change.

frontend/src/features/data-processing/components/ColumnHeaderMenu.vue (2)

67-85: LGTM! Lowercase handler follows established pattern.

The handleLowerCase implementation mirrors the existing handleUpperCase and handleTrimWhitespace handlers: proper error handling, user feedback based on affectedRows, and emits replaceCompleted to refresh the UI.


145-145: LGTM! Menu item wired to handler.

The "To lowercase" menu item now invokes handleLowerCase instead of a placeholder, completing the frontend integration.

backend/src/services/lowercase-conversion.service.ts (4)

1-3: LGTM! Standard imports.

Imports the base class and interface correctly.


4-14: LGTM! performOperation delegates to base class infrastructure.

The method correctly destructures params and delegates to executeColumnOperation with the query builder and row counter closures. Pattern matches UppercaseConversionService.


19-28: LGTM! Query logic is correct.

The UPDATE query uses LOWER() and correctly filters out NULL and already-lowercase values to minimize unnecessary writes. Identifier interpolation with double quotes is appropriate for DuckDB.

Minor comment nuance: The comment mentions "parameterized" query, but table/column are interpolated (not bound parameters). This is correct for identifiers—params would only apply to data values. The same pattern exists in UppercaseConversionService.


33-42: LGTM! Row counter matches UPDATE logic.

The countAffectedRows query uses the same WHERE clause as the UPDATE, ensuring accurate preview of changes. Consistent with UppercaseConversionService.

backend/src/api/project/index.ts (3)

14-14: LGTM!

The import is correctly placed and follows the established pattern for service imports.


718-720: LGTM!

Good addition for API documentation consistency. The tags attribute aligns this route's OpenAPI metadata with the other endpoints.


724-781: LGTM!

The lowercase endpoint implementation is solid and follows the established patterns for column operations (uppercase, trim). Column validation, service instantiation, error handling, and response schemas are all correctly implemented.

backend/tests/services/lowercase-conversion.service.test.ts (9)

1-19: LGTM!

The test suite setup is well-structured with proper initialization and cleanup. Using an in-memory database for tests is appropriate and follows the existing test patterns.


21-58: LGTM!

The test correctly validates basic lowercase conversion with mixed-case data. The expected affected row count (4 out of 5) is accurate since 'bob johnson' is already lowercase and should not be affected.


60-94: LGTM!

The test properly validates that empty strings are handled correctly and remain empty after the operation. The affected row count expectation is accurate.


96-130: LGTM!

The test correctly validates NULL value handling. NULLs are properly excluded from the operation, which aligns with the service's WHERE clause filtering.


132-144: LGTM!

The test correctly validates error handling for non-existent columns. The expected error message aligns with the service implementation.


146-150: LGTM!

The test correctly validates that attempting to operate on a non-existent table results in an error. The less-specific error check is appropriate since the database error message may vary.


152-178: LGTM!

The test correctly validates the no-op scenario where all data is already lowercase. The expectation of 0 affected rows is accurate.


180-220: LGTM!

Excellent test coverage for special characters, numbers, and various naming conventions. The test validates that the LOWER function correctly handles punctuation, digits, and special characters.


222-258: LGTM!

Excellent test for internationalization support. The test validates that DuckDB's LOWER function correctly handles unicode and accented characters, which is crucial for global data processing.

backend/tests/api/project/lowercase.test.ts (6)

1-60: LGTM!

The test suite setup is well-structured. The use of treaty for type-safe API testing and proper initialization/cleanup patterns are appropriate. The helper function importTestData promotes code reuse.


61-87: LGTM!

The test correctly validates the basic lowercase conversion flow, including both the affected row count and the actual data transformation. The verification approach using expect.arrayContaining is appropriate.


89-104: LGTM!

The test correctly validates error handling for non-existent columns. The error response structure verification is thorough and matches the API's error handling pattern.


106-123: LGTM!

The test correctly validates schema-level validation for missing required fields. The 422 status code and error structure expectations are accurate.


125-187: LGTM!

The test correctly validates the mixed-case scenario where some data is already lowercase. Creating a new project for this test avoids conflicts, and the expected affected row count (3) is accurate. The data verification confirms the correct transformation behavior.


189-233: LGTM!

The test correctly validates the no-op scenario where all data is already lowercase. Creating a new project for this test is appropriate, and the expectation of 0 affected rows is accurate.

@DaxServer DaxServer merged commit b49c52f into main Sep 29, 2025
5 of 6 checks passed
@DaxServer DaxServer deleted the lowercase-conversion-service branch September 29, 2025 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants