Skip to content

Commit

Permalink
Allow keywords prefixed with @ in Fusion grammars
Browse files Browse the repository at this point in the history
  • Loading branch information
kesmit13 committed Jul 17, 2024
1 parent 2ad377e commit 001861b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
1 change: 1 addition & 0 deletions docs/src/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This document outlines features and improvements from each release.
v1.4.4 - July 12, 2024
----------------------
* Add ``USE WORKSPACE`` Fusion command
* Add ``vector_data_format=`` to connection options to specify JSON or BINARY for vector data

v1.4.3 - July 10, 2024
----------------------
Expand Down
26 changes: 17 additions & 9 deletions singlestoredb/fusion/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import abc
import functools
import re
import sys
import textwrap
from typing import Any
from typing import Callable
Expand Down Expand Up @@ -102,15 +103,15 @@ def json_unescape(s: str) -> str:

def get_keywords(grammar: str) -> Tuple[str, ...]:
"""Return all all-caps words from the beginning of the line."""
m = re.match(r'^\s*((?:[A-Z0-9_]+)(\s+|$|;))+', grammar)
m = re.match(r'^\s*((?:[@A-Z0-9_]+)(\s+|$|;))+', grammar)
if not m:
return tuple()
return tuple(re.split(r'\s+', m.group(0).replace(';', '').strip()))


def is_bool(grammar: str) -> bool:
"""Determine if the rule is a boolean."""
return bool(re.match(r'^[A-Z0-9_\s*]+$', grammar))
return bool(re.match(r'^[@A-Z0-9_\s*]+$', grammar))


def process_optional(m: Any) -> str:
Expand All @@ -137,8 +138,9 @@ def process_repeats(m: Any) -> str:

def lower_and_regex(m: Any) -> str:
"""Lowercase and convert literal to regex."""
sql = m.group(1)
return f'~"{sql.lower()}"i'
start = m.group(1) or ''
sql = m.group(2)
return f'~"{start}{sql.lower()}"i'


def split_unions(grammar: str) -> str:
Expand Down Expand Up @@ -415,7 +417,7 @@ def process_grammar(
sql = re.sub(r'\]\s+\[', r' | ', sql)

# Lower-case keywords and make them case-insensitive
sql = re.sub(r'\b([A-Z0-9]+)\b', lower_and_regex, sql)
sql = re.sub(r'(\b|@+)([A-Z0-9]+)\b', lower_and_regex, sql)

# Convert literal strings to 'qs'
sql = re.sub(r"'[^']+'", r'qs', sql)
Expand Down Expand Up @@ -479,10 +481,16 @@ def process_grammar(
cmds = ' / '.join(x for x in rules if x.endswith('_cmd'))
cmds = f'init = ws* ( {cmds} ) ws* ";"? ws*\n'

return (
Grammar(cmds + CORE_GRAMMAR + '\n'.join(out)), command_key,
rule_info, syntax_txt, help_txt,
)
grammar = cmds + CORE_GRAMMAR + '\n'.join(out)

try:
return (
Grammar(grammar), command_key,
rule_info, syntax_txt, help_txt,
)
except ParseError:
print(grammar, file=sys.stderr)
raise


def flatten(items: Iterable[Any]) -> List[Any]:
Expand Down
15 changes: 11 additions & 4 deletions singlestoredb/fusion/handlers/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@

class UseWorkspaceHandler(SQLHandler):
"""
USE WORKSPACE workspace [ with_database ];
USE WORKSPACE [ workspace ] [ with_database ];
# Workspace
workspace = { workspace_id | workspace_name }
workspace = { workspace_id | workspace_name | current_workspace }
# ID of workspace
workspace_id = ID '<workspace-id>'
# Name of workspace
workspace_name = '<workspace-name>'
# Current workspace
current_workspace = @CURRENT
# Name of database
with_database = WITH DATABASE 'database-name'
Expand All @@ -40,6 +43,8 @@ class UseWorkspaceHandler(SQLHandler):
Remarks
-------
* If you want to specify a database in the current workspace,
the workspace name can be specified as @CURRENT.
* Specify the ``WITH DATABASE`` clause to select a default
database for the session.
* This command only works in a notebook session in the
Expand All @@ -55,11 +60,13 @@ class UseWorkspaceHandler(SQLHandler):
"""
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
from singlestoredb.notebook import portal
if params.get('with_database'):
if params.get('workspace') and params.get('with_database'):
portal.connection = params['workspace']['workspace_name'], \
params['with_database']
else:
elif params.get('workspace'):
portal.workspace = params['workspace']['workspace_name']
else:
portal.default_database = params['workspace']['with_database']
return None


Expand Down

0 comments on commit 001861b

Please sign in to comment.