Skip to content

Commit 3ce5083

Browse files
committed
Basic volume client setup
1 parent 3463b12 commit 3ce5083

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
class StringUtil:
2+
@staticmethod
3+
def escape_string_literal(s: str) -> str:
4+
"""Escapes single quotes in a string for safe SQL usage."""
5+
if s is None:
6+
return None
7+
return s.replace("'", "''")
8+
9+
@staticmethod
10+
def get_volume_path(catalog: str, schema: str, volume: str) -> str:
11+
"""
12+
Constructs and escapes the volume path in the form of /Volumes/catalog/schema/volume/
13+
"""
14+
path = f"/Volumes/{catalog}/{schema}/{volume}/"
15+
return StringUtil.escape_string_literal(path)
16+
17+
@staticmethod
18+
def get_object_full_path(
19+
catalog: str, schema: str, volume: str, object_path: str
20+
) -> str:
21+
"""
22+
Returns the full escaped object path by appending the escaped object name to the volume path.
23+
"""
24+
return StringUtil.get_volume_path(
25+
catalog, schema, volume
26+
) + StringUtil.escape_string_literal(object_path)
27+
28+
@staticmethod
29+
def create_get_object_query(
30+
catalog: str, schema: str, volume: str, object_path: str, local_path: str
31+
) -> str:
32+
"""
33+
Returns the SQL GET command for retrieving an object to a local path.
34+
"""
35+
return f"GET '{StringUtil.get_object_full_path(catalog, schema, volume, object_path)}' TO '{StringUtil.escape_string_literal(local_path)}'"
36+
37+
@staticmethod
38+
def create_get_object_query_for_input_stream(
39+
catalog: str, schema: str, volume: str, object_path: str
40+
) -> str:
41+
"""
42+
Constructs a GET query that writes the retrieved object to an input stream placeholder.
43+
"""
44+
full_path = StringUtil.get_object_full_path(
45+
catalog, schema, volume, object_path
46+
)
47+
return f"GET '{full_path}' TO '__input_stream__'"
48+
49+
@staticmethod
50+
def create_put_object_query(
51+
catalog: str,
52+
schema: str,
53+
volume: str,
54+
object_path: str,
55+
local_path: str,
56+
overwrite: bool,
57+
) -> str:
58+
escaped_local_path = StringUtil.escape_string_literal(local_path)
59+
full_remote_path = StringUtil.get_object_full_path(
60+
catalog, schema, volume, object_path
61+
)
62+
overwrite_clause = " OVERWRITE" if overwrite else ""
63+
return f"PUT '{escaped_local_path}' INTO '{full_remote_path}'{overwrite_clause}"
64+
65+
@staticmethod
66+
def create_put_object_query_for_input_stream(
67+
catalog: str, schema: str, volume: str, object_path: str, to_overwrite: bool
68+
) -> str:
69+
"""
70+
Constructs a PUT query that uploads from an input stream to a volume path.
71+
Appends 'OVERWRITE' if to_overwrite is True.
72+
"""
73+
full_remote_path = StringUtil.get_object_full_path(
74+
catalog, schema, volume, object_path
75+
)
76+
overwrite_clause = " OVERWRITE" if to_overwrite else ""
77+
return f"PUT '__input_stream__' INTO '{full_remote_path}'{overwrite_clause}"
78+
79+
@staticmethod
80+
def get_object_query(
81+
catalog: str, schema: str, volume: str, object_path: str, local_path: str
82+
) -> str:
83+
"""
84+
Public entry point to create GET object query.
85+
Equivalent to: String getObjectQuery = createGetObjectQuery(...)
86+
"""
87+
return StringUtil.create_get_object_query(
88+
catalog, schema, volume, object_path, local_path
89+
)
90+
91+
@staticmethod
92+
def create_delete_object_query(
93+
catalog: str, schema: str, volume: str, object_path: str
94+
) -> str:
95+
"""
96+
Returns the SQL REMOVE command for deleting an object from a volume.
97+
"""
98+
return f"REMOVE '{StringUtil.get_object_full_path(catalog, schema, volume, object_path)}'"
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from typing import BinaryIO
2+
3+
from databricks.sql.utils.string_util import StringUtil
4+
5+
6+
class VolumeClient:
7+
"""
8+
Databricks Volume Client
9+
"""
10+
11+
def __init__(self, conn):
12+
"""
13+
Initialize the VolumeClient with a connection object.
14+
15+
:param conn: Connection object to Databricks.
16+
"""
17+
self.conn = conn
18+
19+
def get_object(
20+
self, catalog: str, schema: str, volume: str, object_path: str, local_path: str
21+
) -> bool:
22+
get_object_query = StringUtil.create_get_object_query(
23+
catalog, schema, volume, object_path, local_path
24+
)
25+
return True
26+
27+
def get_object(
28+
self, catalog: str, schema: str, volume: str, object_path: str
29+
) -> BinaryIO:
30+
get_object_query = StringUtil.create_get_object_query_for_input_stream(
31+
catalog, schema, volume, object_path
32+
)
33+
return True
34+
35+
def put_object(
36+
self,
37+
catalog: str,
38+
schema: str,
39+
volume: str,
40+
object_path: str,
41+
local_path: str,
42+
to_overwrite: bool,
43+
) -> bool:
44+
put_object_query = StringUtil.create_put_object_query(
45+
catalog, schema, volume, object_path, local_path, to_overwrite
46+
)
47+
return True
48+
49+
def put_object(
50+
self,
51+
catalog: str,
52+
schema: str,
53+
volume: str,
54+
object_path: str,
55+
input_stream: BinaryIO,
56+
content_length: int,
57+
to_overwrite: bool,
58+
) -> bool:
59+
put_object_query_for_input_stream = (
60+
StringUtil.create_put_object_query_for_input_stream(
61+
catalog, schema, volume, object_path, to_overwrite
62+
)
63+
)
64+
return True
65+
66+
def delete_object(
67+
self, catalog: str, schema: str, volume: str, object_path: str
68+
) -> bool:
69+
delete_object_query = StringUtil.create_delete_object_query(
70+
catalog, schema, volume, object_path
71+
)
72+
return True

0 commit comments

Comments
 (0)