Skip to main content

sql_dialect_fmt_hover/
data.rs

1use crate::HoverKind;
2
3pub const CREATE_PROCEDURE_DOCS: &str =
4    "https://docs.snowflake.com/en/sql-reference/sql/create-procedure";
5pub const CREATE_TASK_DOCS: &str = "https://docs.snowflake.com/en/sql-reference/sql/create-task";
6pub const DATA_TYPES_DOCS: &str = "https://docs.snowflake.com/en/sql-reference/data-types";
7
8pub(crate) const ROUTINE_OPTION_STOPS: &[&str] = &[
9    "AS",
10    "ARTIFACT_REPOSITORY",
11    "CALLED",
12    "COMMENT",
13    "COPY",
14    "EXECUTE",
15    "EXTERNAL_ACCESS_INTEGRATIONS",
16    "HANDLER",
17    "IMMUTABLE",
18    "IMPORTS",
19    "LANGUAGE",
20    "MEMOIZABLE",
21    "NULL",
22    "PACKAGES",
23    "RETURNS",
24    "RUNTIME_VERSION",
25    "SECRETS",
26    "SECURE",
27    "STRICT",
28    "TARGET_PATH",
29    "VOLATILE",
30];
31
32#[derive(Clone, Copy)]
33pub(crate) struct StaticHover {
34    pub(crate) kind: HoverKind,
35    pub(crate) title: &'static str,
36    pub(crate) body: &'static str,
37    pub(crate) docs_url: Option<&'static str>,
38}
39
40pub(crate) fn type_info(text: &str) -> Option<(&'static str, &'static str)> {
41    let item = [
42        (
43            &["NUMBER", "DECIMAL", "NUMERIC", "INT", "INTEGER", "BIGINT"][..],
44            "NUMBER",
45            "Exact fixed-point numeric type. Use precision and scale for stable financial or identifier-like values.",
46        ),
47        (
48            &["FLOAT", "DOUBLE", "REAL"][..],
49            "FLOAT",
50            "Approximate floating-point numeric type. Prefer NUMBER when exact decimal behavior matters.",
51        ),
52        (
53            &["VARCHAR", "STRING", "TEXT", "CHAR"][..],
54            "VARCHAR",
55            "Variable-length character data. STRING and TEXT are Snowflake aliases for VARCHAR.",
56        ),
57        (&["BOOLEAN"][..], "BOOLEAN", "TRUE/FALSE logical value."),
58        (
59            &["VARIANT"][..],
60            "VARIANT",
61            "Semi-structured value that can hold JSON-like OBJECT, ARRAY, scalar, or SQL NULL distinctions.",
62        ),
63        (
64            &["OBJECT"][..],
65            "OBJECT",
66            "Semi-structured key/value object. Common with JSON ingestion and colon path access.",
67        ),
68        (
69            &["ARRAY"][..],
70            "ARRAY",
71            "Semi-structured ordered collection. Use bracket indexing and FLATTEN/TABLE for traversal.",
72        ),
73        (
74            &["MAP"][..],
75            "MAP",
76            "Structured key/value collection type. Useful when key and value types are part of the schema.",
77        ),
78        (
79            &["VECTOR"][..],
80            "VECTOR",
81            "Vector type for embeddings and similarity workloads; keep element type and dimension explicit.",
82        ),
83        (
84            &["DATE"][..],
85            "DATE",
86            "Calendar date without time of day.",
87        ),
88        (
89            &["TIME"][..],
90            "TIME",
91            "Time of day without date.",
92        ),
93        (
94            &["TIMESTAMP", "TIMESTAMP_NTZ", "TIMESTAMP_LTZ", "TIMESTAMP_TZ"][..],
95            "TIMESTAMP",
96            "Timestamp family. NTZ has no time zone, LTZ uses the session time zone, and TZ stores an explicit offset.",
97        ),
98        (&["BINARY"][..], "BINARY", "Variable-length binary data."),
99        (
100            &["GEOGRAPHY", "GEOMETRY"][..],
101            "GEOSPATIAL",
102            "Geospatial data for spherical geography or planar geometry operations.",
103        ),
104    ]
105    .into_iter()
106    .find(|(aliases, _, _)| aliases.iter().any(|alias| text.eq_ignore_ascii_case(alias)))?;
107
108    Some((item.1, item.2))
109}
110
111pub(crate) fn language_template(text: &str) -> Option<StaticHover> {
112    if text.eq_ignore_ascii_case("JAVASCRIPT") {
113        Some(StaticHover {
114            kind: HoverKind::Language,
115            title: "LANGUAGE JAVASCRIPT",
116            body: "JavaScript stored procedure body. The handler is the body itself; SQL argument names can need careful case handling inside JavaScript.",
117            docs_url: Some(CREATE_PROCEDURE_DOCS),
118        })
119    } else if text.eq_ignore_ascii_case("PYTHON") {
120        Some(StaticHover {
121            kind: HoverKind::Language,
122            title: "LANGUAGE PYTHON",
123            body: "Snowpark Python stored procedure. HANDLER names the Python function; RUNTIME_VERSION pins Python; PACKAGES, IMPORTS, EXTERNAL_ACCESS_INTEGRATIONS, and SECRETS describe the runtime environment.",
124            docs_url: Some(CREATE_PROCEDURE_DOCS),
125        })
126    } else if text.eq_ignore_ascii_case("JAVA") {
127        Some(StaticHover {
128            kind: HoverKind::Language,
129            title: "LANGUAGE JAVA",
130            body: "Java stored procedure. HANDLER names a class and method; RUNTIME_VERSION, PACKAGES, IMPORTS, and TARGET_PATH describe the JVM runtime and staged artifact.",
131            docs_url: Some(CREATE_PROCEDURE_DOCS),
132        })
133    } else if text.eq_ignore_ascii_case("SCALA") {
134        Some(StaticHover {
135            kind: HoverKind::Language,
136            title: "LANGUAGE SCALA",
137            body: "Snowpark Scala stored procedure. HANDLER names the Scala entry point; RUNTIME_VERSION, PACKAGES, IMPORTS, and TARGET_PATH describe the JVM runtime and staged artifact.",
138            docs_url: Some(CREATE_PROCEDURE_DOCS),
139        })
140    } else if text.eq_ignore_ascii_case("SQL") {
141        Some(StaticHover {
142            kind: HoverKind::Language,
143            title: "LANGUAGE SQL",
144            body: "Snowflake Scripting stored procedure body. Use SQL procedural constructs such as DECLARE, BEGIN, RETURN, loops, and EXCEPTION handlers.",
145            docs_url: Some(CREATE_PROCEDURE_DOCS),
146        })
147    } else {
148        None
149    }
150}
151
152pub(crate) fn property_template(text: &str) -> Option<StaticHover> {
153    PROPERTIES
154        .iter()
155        .copied()
156        .find(|property| text.eq_ignore_ascii_case(property.title))
157}
158
159pub(crate) fn keyword_template(text: &str) -> Option<StaticHover> {
160    if text.eq_ignore_ascii_case("PROCEDURE") {
161        Some(StaticHover {
162            kind: HoverKind::Procedure,
163            title: "Stored procedure",
164            body: "Schema object that can be called with CALL. Procedures support SQL, JavaScript, Python, Java, and Scala handlers.",
165            docs_url: Some(CREATE_PROCEDURE_DOCS),
166        })
167    } else if text.eq_ignore_ascii_case("TASK") {
168        Some(StaticHover {
169            kind: HoverKind::Task,
170            title: "Task",
171            body: "Schema object that executes SQL on a schedule or as part of a task graph. Newly created tasks start suspended.",
172            docs_url: Some(CREATE_TASK_DOCS),
173        })
174    } else {
175        None
176    }
177}
178
179const PROPERTIES: &[StaticHover] = &[
180    StaticHover {
181        kind: HoverKind::Property,
182        title: "RETURNS",
183        body: "Declares a procedure result type. It can be a scalar type or RETURNS TABLE(...), depending on the procedure language and support level.",
184        docs_url: Some(CREATE_PROCEDURE_DOCS),
185    },
186    StaticHover {
187        kind: HoverKind::Property,
188        title: "LANGUAGE",
189        body: "Selects the stored procedure handler language: SQL, JAVASCRIPT, PYTHON, JAVA, or SCALA.",
190        docs_url: Some(CREATE_PROCEDURE_DOCS),
191    },
192    StaticHover {
193        kind: HoverKind::Property,
194        title: "HANDLER",
195        body: "Names the external-language entry point, such as a Python function or JVM method.",
196        docs_url: Some(CREATE_PROCEDURE_DOCS),
197    },
198    StaticHover {
199        kind: HoverKind::Property,
200        title: "PACKAGES",
201        body: "Declares runtime packages available to Snowpark Java, Scala, or Python procedure handlers.",
202        docs_url: Some(CREATE_PROCEDURE_DOCS),
203    },
204    StaticHover {
205        kind: HoverKind::Property,
206        title: "IMPORTS",
207        body: "Adds staged files that the stored procedure handler can read at runtime.",
208        docs_url: Some(CREATE_PROCEDURE_DOCS),
209    },
210    StaticHover {
211        kind: HoverKind::Property,
212        title: "RUNTIME_VERSION",
213        body: "Pins the language runtime version for Java, Python, or Scala procedure handlers.",
214        docs_url: Some(CREATE_PROCEDURE_DOCS),
215    },
216    StaticHover {
217        kind: HoverKind::Property,
218        title: "TARGET_PATH",
219        body: "Stage path for the compiled Java or Scala procedure artifact. Use it when Snowflake should write the generated handler artifact to a stage.",
220        docs_url: Some(CREATE_PROCEDURE_DOCS),
221    },
222    StaticHover {
223        kind: HoverKind::Property,
224        title: "ARTIFACT_REPOSITORY",
225        body: "Selects an artifact repository for resolving supported external-language dependencies.",
226        docs_url: Some(CREATE_PROCEDURE_DOCS),
227    },
228    StaticHover {
229        kind: HoverKind::Property,
230        title: "EXTERNAL_ACCESS_INTEGRATIONS",
231        body: "Allows an external-language procedure to use one or more external access integrations for outbound network access.",
232        docs_url: Some(CREATE_PROCEDURE_DOCS),
233    },
234    StaticHover {
235        kind: HoverKind::Property,
236        title: "SECRETS",
237        body: "Maps Snowflake secrets to names the external-language handler can use at runtime.",
238        docs_url: Some(CREATE_PROCEDURE_DOCS),
239    },
240    StaticHover {
241        kind: HoverKind::Property,
242        title: "STRICT",
243        body: "Alias for RETURNS NULL ON NULL INPUT: Snowflake does not call the handler when any input argument is NULL.",
244        docs_url: Some(CREATE_PROCEDURE_DOCS),
245    },
246    StaticHover {
247        kind: HoverKind::Property,
248        title: "CALLED",
249        body: "Part of CALLED ON NULL INPUT: Snowflake calls the procedure even when an input argument is NULL.",
250        docs_url: Some(CREATE_PROCEDURE_DOCS),
251    },
252    StaticHover {
253        kind: HoverKind::Property,
254        title: "IMMUTABLE",
255        body: "Declares that the result depends only on inputs and not on database state or side effects.",
256        docs_url: Some(CREATE_PROCEDURE_DOCS),
257    },
258    StaticHover {
259        kind: HoverKind::Property,
260        title: "VOLATILE",
261        body: "Declares that the procedure can depend on state or side effects; this is the conservative behavior for procedural code.",
262        docs_url: Some(CREATE_PROCEDURE_DOCS),
263    },
264    StaticHover {
265        kind: HoverKind::Property,
266        title: "EXECUTE",
267        body: "Controls whether a procedure or task runs with owner, caller, restricted caller, or user execution context.",
268        docs_url: Some(CREATE_PROCEDURE_DOCS),
269    },
270    StaticHover {
271        kind: HoverKind::Property,
272        title: "WAREHOUSE",
273        body: "Virtual warehouse that supplies compute for a task run. Omit it only when using serverless task sizing.",
274        docs_url: Some(CREATE_TASK_DOCS),
275    },
276    StaticHover {
277        kind: HoverKind::Property,
278        title: "USER_TASK_MANAGED_INITIAL_WAREHOUSE_SIZE",
279        body: "Initial serverless task size. Snowflake can manage task compute after enough run history exists.",
280        docs_url: Some(CREATE_TASK_DOCS),
281    },
282    StaticHover {
283        kind: HoverKind::Property,
284        title: "SCHEDULE",
285        body: "Task schedule. Snowflake accepts interval strings or USING CRON expressions with a time zone.",
286        docs_url: Some(CREATE_TASK_DOCS),
287    },
288    StaticHover {
289        kind: HoverKind::Property,
290        title: "AFTER",
291        body: "Creates a task graph dependency; this task runs after one or more predecessor tasks.",
292        docs_url: Some(CREATE_TASK_DOCS),
293    },
294    StaticHover {
295        kind: HoverKind::Property,
296        title: "WHEN",
297        body: "Boolean task condition evaluated before the task body runs. Common with stream checks such as SYSTEM$STREAM_HAS_DATA.",
298        docs_url: Some(CREATE_TASK_DOCS),
299    },
300    StaticHover {
301        kind: HoverKind::Property,
302        title: "FINALIZE",
303        body: "Marks a task as a finalizer for a task graph root.",
304        docs_url: Some(CREATE_TASK_DOCS),
305    },
306    StaticHover {
307        kind: HoverKind::Property,
308        title: "TASK_AUTO_RETRY_ATTEMPTS",
309        body: "Configures automatic retries for failed task graph runs.",
310        docs_url: Some(CREATE_TASK_DOCS),
311    },
312];