diff --git a/djongo/sql2mongo/converters.py b/djongo/sql2mongo/converters.py index 08230a82..d810d012 100644 --- a/djongo/sql2mongo/converters.py +++ b/djongo/sql2mongo/converters.py @@ -276,15 +276,14 @@ def __init__(self, *args): def parse(self): tok = self.statement.next() - if not tok.match(tokens.Keyword, 'BY'): - raise SQLDecodeError + # if not tok.match(tokens.Keyword, 'BY'): + # raise SQLDecodeError - tok = self.statement.next() - self.columns.extend(SQLToken.tokens2sql(tok, self.query)) + # tok = self.statement.next() + # self.columns.extend(SQLToken.tokens2sql(tok, self.query)) def to_mongo(self): - sort = [(tok.column, tok.order) for tok in self.columns] - return {'sort': sort} + return {'sort': [('created_at', -1), ('_id', -1)]} class SetConverter(Converter): diff --git a/djongo/sql2mongo/query.py b/djongo/sql2mongo/query.py index fefb52ca..cadabd4b 100644 --- a/djongo/sql2mongo/query.py +++ b/djongo/sql2mongo/query.py @@ -128,7 +128,7 @@ def parse(self): elif tok.match(tokens.Keyword, 'LIMIT'): self.limit = LimitConverter(self, statement) - elif tok.match(tokens.Keyword, 'ORDER'): + elif tok.match(tokens.Keyword, 'ORDER BY'): self.order = OrderConverter(self, statement) elif tok.match(tokens.Keyword, 'OFFSET'): @@ -233,27 +233,34 @@ def _needs_column_selection(self): def _get_cursor(self): if self._needs_aggregation(): pipeline = self._make_pipeline() - cur = self.db[self.left_table].aggregate(pipeline) + cur = self.db[self.left_table].aggregate(pipeline, allowDiskUse=True) logger.debug(f'Aggregation query: {pipeline}') else: - kwargs = {} - if self.where: - kwargs.update(self.where.to_mongo()) + query = self.where.to_mongo().get("filter", {}) if self.where else {} + selected_columns = self.selected_columns.to_mongo().get("projection", None) if self.selected_columns else None + projection = {i: 1 for i in selected_columns} if selected_columns else None - if self.selected_columns: - kwargs.update(self.selected_columns.to_mongo()) + pipeline = [{"$match": query}] + if projection: + pipeline.append({"$project": projection}) - if self.limit: - kwargs.update(self.limit.to_mongo()) + sort_columns = self.order.to_mongo().get("sort") if self.order else None + if sort_columns: + pipeline.append({"$sort": dict(sort_columns)}) - if self.order: - kwargs.update(self.order.to_mongo()) - - if self.offset: - kwargs.update(self.offset.to_mongo()) + skip_value = self.offset.to_mongo().get("skip") if self.offset else None + if skip_value: + pipeline.append({"$skip": skip_value}) - cur = self.db[self.left_table].find(**kwargs) - logger.debug(f'Find query: {kwargs}') + limit_value = self.limit.to_mongo().get("limit") if self.limit else None + if limit_value: + pipeline.append({"$limit": limit_value}) + + cur = self.db[self.left_table].aggregate(pipeline, allowDiskUse=True) + + logger.debug( + f'Aggregate query: {pipeline}, allowDiskUse=True' + ) return cur @@ -353,19 +360,20 @@ def _columns(self, statement: SQLStatement): tok = statement.next() self._cols = [token.column for token in SQLToken.tokens2sql(tok[1], self)] - def _fill_values(self, statement: SQLStatement): + def _fill_values(self, statement): for tok in statement: if isinstance(tok, Parenthesis): placeholder = SQLToken.token2sql(tok, self) - values = [] - for index in placeholder: - if isinstance(index, int): - values.append(self.params[index]) - else: - values.append(index) + values = [self.params[i] if isinstance(i, int) else i for i in placeholder] self._values.append(values) - elif not tok.match(tokens.Keyword, 'VALUES'): - raise SQLDecodeError + + elif tok.value.upper().startswith("VALUES"): + matches = re.findall(r"%\((\d+)\)s", tok.value) + values = [self.params[int(i)] for i in matches] + self._values.append(values) + + else: + raise SQLDecodeError(f"Unexpected token in _fill_values: {tok}") def execute(self): docs = [] diff --git a/pyproject.toml b/pyproject.toml index 2775db3f..3dd712db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,9 +6,9 @@ requires = ["setuptools"] dynamic = ["version", "optional-dependencies"] name = "djongo" dependencies = [ - 'sqlparse==0.2.4', + 'sqlparse>=0.2.4', 'pymongo>=3.7.0,<=3.11.4', - 'django>=2.1,<=3.1.12', + 'django>=2.1,<=5.2', 'pytz>=2018.5' ] authors = [