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
5 changes: 5 additions & 0 deletions sqlglot/dialects/dialect.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,11 @@ class Dialect(metaclass=_Dialect):
Whether ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks
"""

SUPPORTS_LIMIT_ALL = False
"""
Whether LIMIT ALL is supported (equivalent to no limit) as in Postgres.
"""

PROJECTION_ALIASES_SHADOW_SOURCE_NAMES = False
"""
Whether projection alias names can shadow table/source names in GROUP BY and HAVING clauses.
Expand Down
1 change: 1 addition & 0 deletions sqlglot/dialects/duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class DuckDB(Dialect):
CONCAT_COALESCE = True
CONCAT_WS_COALESCE = True
SUPPORTS_ORDER_BY_ALL = True
SUPPORTS_LIMIT_ALL = True
SUPPORTS_FIXED_SIZE_ARRAYS = True
STRICT_JSON_PATH_SYNTAX = False
NUMBERS_CAN_BE_UNDERSCORE_SEPARATED = True
Expand Down
1 change: 1 addition & 0 deletions sqlglot/dialects/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Postgres(Dialect):
CONCAT_COALESCE = True
CONCAT_WS_COALESCE = True
NULL_ORDERING = "nulls_are_large"
SUPPORTS_LIMIT_ALL = True
Comment thread
georgesittas marked this conversation as resolved.
TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'"
TABLESAMPLE_SIZE_IS_PERCENT = True
TABLES_REFERENCEABLE_AS_COLUMNS = True
Expand Down
1 change: 1 addition & 0 deletions sqlglot/dialects/presto.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Presto(Dialect):
TYPED_DIVISION = True
TABLESAMPLE_SIZE_IS_PERCENT = True
LOG_BASE_FIRST: bool | None = None
SUPPORTS_LIMIT_ALL = True
SUPPORTS_VALUES_DEFAULT = False
LEAST_GREATEST_IGNORES_NULLS = False
UUID_IS_STRING_TYPE = False
Expand Down
1 change: 1 addition & 0 deletions sqlglot/dialects/spark.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

class Spark(Spark2):
SUPPORTS_ORDER_BY_ALL = True
SUPPORTS_LIMIT_ALL = True
SUPPORTS_NULL_TYPE = True
ARRAY_FUNCS_PROPAGATES_NULLS = True
EXPRESSION_METADATA = EXPRESSION_METADATA.copy()
Expand Down
20 changes: 20 additions & 0 deletions sqlglot/generators/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ def _generated_to_auto_increment(expression: exp.Expr) -> exp.Expr:
return expression


def _offset_to_limit(expression: exp.Expr) -> exp.Expr:
Comment thread
georgesittas marked this conversation as resolved.
if not isinstance(expression, exp.Select):
return expression

offset = expression.args.get("offset")

if offset and not expression.args.get("limit"):
expression.limit(-1, copy=False)

return expression


class SQLiteGenerator(generator.Generator):
SELECT_KINDS: tuple[str, ...] = ()
TRY_SUPPORTED = False
Expand Down Expand Up @@ -152,6 +164,7 @@ class SQLiteGenerator(generator.Generator):
exp.Rand: rename_func("RANDOM"),
exp.Select: transforms.preprocess(
[
_offset_to_limit,
transforms.eliminate_distinct_on,
transforms.eliminate_qualify,
transforms.eliminate_semi_and_anti_joins,
Expand Down Expand Up @@ -182,6 +195,13 @@ class SQLiteGenerator(generator.Generator):

LIMIT_FETCH = "LIMIT"

def insert_sql(self, expression: exp.Insert) -> str:
if expression.args.get("ignore"):
expression.set("ignore", False)
expression.set("alternative", "IGNORE")

Comment on lines +199 to +202
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hmm... this is fine for now, but looks like a code smell to me. Having two ways to represent the IGNORE semantics doesn't look right. Perhaps something to clean up in the future...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good catch here. let me think about a better way to do this

Copy link
Copy Markdown
Collaborator

@georgesittas georgesittas May 25, 2026

Choose a reason for hiding this comment

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

This is fine for now, let's not deal with it in this PR. Just wanted to leave a note for future reference.

return super().insert_sql(expression)

def bitwiseandagg_sql(self, expression: exp.BitwiseAndAgg) -> str:
self.unsupported("BITWISE_AND aggregation is not supported in SQLite")
return self.function_fallback_sql(expression)
Expand Down
3 changes: 3 additions & 0 deletions sqlglot/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5488,6 +5488,9 @@ def _parse_limit(
self._match_r_paren()

else:
if self.dialect.SUPPORTS_LIMIT_ALL and self._match(TokenType.ALL):
return this

# Parsing LIMIT x% (i.e x PERCENT) as a term leads to an error, since
# we try to build an exp.Mod expr. For that matter, we backtrack and instead
# consume the factor plus parse the percentage separately
Expand Down
12 changes: 12 additions & 0 deletions tests/dialects/test_dialect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2747,6 +2747,18 @@ def test_safediv(self):
)

def test_limit(self):
self.validate_identity("WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all")
self.validate_all(
"WITH t AS (SELECT 1 AS all) SELECT 1 FROM t",
read={
"databricks": "WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all",
"duckdb": "WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all",
"presto": "WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all",
"postgres": "WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all",
"spark": "WITH t AS (SELECT 1 AS all) SELECT 1 FROM t LIMIT all",
},
)

self.validate_all(
"SELECT * FROM data LIMIT 10, 20",
write={"sqlite": "SELECT * FROM data LIMIT 20 OFFSET 10"},
Expand Down
7 changes: 7 additions & 0 deletions tests/dialects/test_sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ def test_sqlite(self):
"postgres": "SELECT JSON_OBJECT_AGG(name, value) FROM t",
},
)
self.validate_all(
"INSERT OR IGNORE INTO foo (x, y) VALUES (1, 2)",
read={
"mysql": "INSERT IGNORE INTO foo (x, y) VALUES (1, 2)",
"sqlite": "INSERT OR IGNORE INTO foo (x, y) VALUES (1, 2)",
},
)
self.validate_all(
"CURRENT_DATE",
read={
Expand Down
Loading