You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug: SUBSTRING() incorrectly evaluates 0 and negative start indices
Description
The current implementation of the SUBSTRING() function evaluates 0 and negative start indices incorrectly compared to both standard ANSI SQL and popular dialects like MySQL.
This was highlighted during a documentation PR review, which documented the current behavior where 0 acts as the last character of the string.
Environment Details
To help us debug, please provide:
AlaSQL Version: (e.g., is this happening in a newer release or does it exist in versions earlier than early AlaSQL releases?)
Compatibility Options Selected: (e.g., have you set any specific dialects in alasql.options, like alasql.options.mysql = true or alasql.options.postgres = true?)
Current Behavior
Currently, AlaSQL counts backwards from the right, but incorrectly treats 0 as the last character:
```sql
SELECT SUBSTRING('abcd', 0); -- Returns 'd'
SELECT SUBSTRING('abcd', -1); -- Returns 'cd'
```
Expected Behavior
Depending on which SQL dialect compatibility option AlaSQL is currently targeting, the behavior should be:
Option A: ANSI SQL Standard (e.g., PostgreSQL, SQL Server)
Indices are treated mathematically on a number line. 0 and negative numbers represent logical positions before the start of the 1-indexed string.
SELECT SUBSTRING('abcd', 0, 2); -> Starts at index 0 (empty), takes 2 characters (index 0 and index 1). Returns 'a'.
Option B: MySQL / SQLite Standard (Negative Wrap-around)
Negative numbers count backwards from the end of the string, where -1 is the last character. 0 generally returns an empty string.
Because AlaSQL maps SQL's 1-based indexing to JavaScript's 0-based methods (like String.prototype.slice()), there appears to be an off-by-one mapping error when evaluating non-positive integers.
If the JS index calculation for backwards wrapping is implemented similarly to string.length + start - 1, then:
Passing 0 results in length - 1 (the JS index of the last character).
Passing -1 results in length - 2 (the JS index of the second-to-last character).
Proposed Action Items
Investigate how the SUBSTRING logic handles different alasql.options compatibility flags.
Refactor the SUBSTRING logic in the JavaScript source to map start <= 0 correctly based on the active compatibility standard.
Add unit tests covering 0, negative indices, and out-of-bounds start/length combinations across different compatibility modes.
Update the SUBSTRING.md documentation to reflect the correct behavior based on the chosen dialect.
Let me know if I can help. I could at least take the suggested last step. After all, I did it once.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi!
I found that the
SUBSTRINGdocumentation was wrong and I made a fix and added some more examples.HTH.