Skip to content

Commit 75ce4aa

Browse files
committed
Continued updating no-std support
1 parent f56bcf0 commit 75ce4aa

10 files changed

Lines changed: 246 additions & 137 deletions

File tree

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ CREATE TABLE users (
3434
```
3535
A rudimentary implementation can be generated with:
3636
```rust
37+
#![cfg(feature = "std")]
3738
use sql_docs::{GenericDialect,SqlDoc,error::DocError};
3839
use std::{env, fs};
3940

@@ -84,6 +85,47 @@ CREATE TABLE users (
8485
Ok(())
8586
}
8687
```
88+
89+
Or with no `std` and from a `String`:
90+
```rust
91+
use sql_docs::{GenericDialect,SqlDoc,error::DocError};
92+
93+
fn main() -> Result<(), DocError> {
94+
// Temporary directory and file created for demonstration purposes
95+
let example =
96+
r#"-- Table storing user accounts
97+
-- Contains all user values
98+
/* Rows generated at registration */
99+
CREATE TABLE users (
100+
/* Primary key for each user */
101+
id INTEGER PRIMARY KEY,
102+
-- The user's login name
103+
username VARCHAR(255) NOT NULL,
104+
/* User's email address */
105+
email VARCHAR(255) UNIQUE NOT NULL
106+
);"#;
107+
108+
// Extract documentation from a single file
109+
let docs = SqlDoc::from(&example)
110+
// Capture all valid comment lines preceding the statements directly
111+
.collect_all_leading()
112+
// Replace `\n` with a `str`
113+
.flatten_multiline_with(". ")
114+
// Finally build the `SqlDoc`
115+
.build::<GenericDialect>()?;
116+
// Or extract recursively from a directory
117+
// let docs = SqlDoc::from_dir(&base).build()?;
118+
119+
// Retrieve a specific table
120+
let users = docs.table("users", None)?;
121+
122+
// Table name
123+
assert_eq!(users.name(), "users");
124+
// Optional table-level documentation
125+
assert_eq!(users.doc(), Some("Table storing user accounts. Contains all user values. Rows generated at registration"));
126+
Ok(())
127+
}
128+
```
87129
## Primary Interface (Main API)
88130

89131
These are the primary entry points most users will interact with:

rustfmt.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ max_width = 100
33
use_small_heuristics = "Max"
44
reorder_imports = true
55
reorder_modules = true
6+
imports_granularity = "Crate"
7+
group_imports = "StdExternalCrate"

src/ast.rs

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
//!
33
//! This module does not interpret semantics; it only produces an AST + file metadata.
44
5+
use alloc::vec::Vec;
6+
57
use sqlparser::{
68
ast::Statement,
79
dialect::Dialect,
810
parser::{Parser, ParserError},
911
};
1012

11-
use alloc::vec::Vec;
12-
1313
use crate::source::SqlSource;
1414

1515
/// A single SQL Source (such as a file) plus all [`Statement`].
@@ -106,44 +106,45 @@ impl ParsedSqlSourceSet {
106106

107107
#[cfg(test)]
108108
mod tests {
109-
use alloc::borrow::ToOwned;
110-
use alloc::boxed::Box;
109+
use alloc::{borrow::ToOwned, boxed::Box};
110+
111111
use sqlparser::dialect::{GenericDialect, PostgreSqlDialect};
112-
use std::{env, fs};
113112

114113
use super::*;
115114
use crate::source::SqlSource;
116115

116+
#[cfg(feature = "std")]
117117
#[test]
118118
fn parsed_sql_file_parses_single_statement() -> Result<(), Box<dyn std::error::Error>> {
119-
let base = env::temp_dir().join("parsed_sql_file_single_stmt_test");
120-
let _ = fs::remove_dir_all(&base);
121-
fs::create_dir_all(&base)?;
119+
let base = std::env::temp_dir().join("parsed_sql_file_single_stmt_test");
120+
let _ = std::fs::remove_dir_all(&base);
121+
std::fs::create_dir_all(&base)?;
122122
let file_path = base.join("one.sql");
123123
let sql = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
124-
fs::write(&file_path, sql)?;
124+
std::fs::write(&file_path, sql)?;
125125
let sql_file = SqlSource::from_path(&file_path)?;
126126
let parsed = ParsedSqlSource::parse::<GenericDialect>(sql_file)?;
127127
assert_eq!(parsed.path(), Some(file_path.as_path()));
128128
assert_eq!(parsed.content(), sql);
129129
assert_eq!(parsed.statements().len(), 1);
130-
let _ = fs::remove_dir_all(&base);
130+
let _ = std::fs::remove_dir_all(&base);
131131
Ok(())
132132
}
133133

134+
#[cfg(feature = "std")]
134135
#[test]
135136
fn parsed_sql_file_set_parses_multiple_files() -> Result<(), Box<dyn std::error::Error>> {
136-
let base = env::temp_dir().join("parsed_sql_file_set_multi_test");
137-
let _ = fs::remove_dir_all(&base);
138-
fs::create_dir_all(&base)?;
137+
let base = std::env::temp_dir().join("parsed_sql_file_set_multi_test");
138+
let _ = std::fs::remove_dir_all(&base);
139+
std::fs::create_dir_all(&base)?;
139140
let sub = base.join("subdir");
140-
fs::create_dir_all(&sub)?;
141+
std::fs::create_dir_all(&sub)?;
141142
let file1 = base.join("one.sql");
142143
let file2 = sub.join("two.sql");
143144
let sql1 = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
144145
let sql2 = "CREATE TABLE posts (id INTEGER PRIMARY KEY);";
145-
fs::write(&file1, sql1)?;
146-
fs::write(&file2, sql2)?;
146+
std::fs::write(&file1, sql1)?;
147+
std::fs::write(&file2, sql2)?;
147148
let set = SqlSource::sql_sources(&base, &[])?;
148149
let parsed_set = ParsedSqlSourceSet::parse_all::<GenericDialect>(set)?;
149150
let existing_files = parsed_set.sources();
@@ -157,28 +158,29 @@ mod tests {
157158
}
158159
}
159160

160-
let _ = fs::remove_dir_all(&base);
161+
let _ = std::fs::remove_dir_all(&base);
161162
Ok(())
162163
}
163164

165+
#[cfg(feature = "std")]
164166
#[test]
165167
fn parsed_sql_file_path_into_path_buf_round_trips() -> Result<(), Box<dyn std::error::Error>> {
166-
let base = env::temp_dir().join("parsed_sql_file_path_into_path_buf_round_trips");
167-
let _ = fs::remove_dir_all(&base);
168-
fs::create_dir_all(&base)?;
168+
let base = std::env::temp_dir().join("parsed_sql_file_path_into_path_buf_round_trips");
169+
let _ = std::fs::remove_dir_all(&base);
170+
std::fs::create_dir_all(&base)?;
169171
let file_path = base.join("one.sql");
170172
let sql = "CREATE TABLE t (id INTEGER PRIMARY KEY);";
171-
fs::write(&file_path, sql)?;
173+
std::fs::write(&file_path, sql)?;
172174
let sql_file = SqlSource::from_path(&file_path)?;
173175
let parsed = ParsedSqlSource::parse::<GenericDialect>(sql_file)?;
174176
assert_eq!(parsed.path_into_path_buf(), Some(file_path));
175-
let _ = fs::remove_dir_all(&base);
177+
let _ = std::fs::remove_dir_all(&base);
176178
Ok(())
177179
}
178180

179181
#[test]
180182
fn parsed_sql_file_parse_postgres_handles_pg_function_syntax()
181-
-> Result<(), Box<dyn std::error::Error>> {
183+
-> Result<(), Box<dyn core::error::Error>> {
182184
let sql = r"
183185
CREATE OR REPLACE FUNCTION f()
184186
RETURNS SMALLINT
@@ -207,17 +209,18 @@ mod tests {
207209
Ok(())
208210
}
209211

212+
#[cfg(feature = "std")]
210213
#[test]
211214
fn parsed_sql_file_set_parse_all_uses_default_dialect() -> Result<(), Box<dyn std::error::Error>>
212215
{
213-
let base = env::temp_dir().join("parsed_sql_file_set_parse_all_default_dialect");
214-
let _ = fs::remove_dir_all(&base);
215-
fs::create_dir_all(&base)?;
216+
let base = std::env::temp_dir().join("parsed_sql_file_set_parse_all_default_dialect");
217+
let _ = std::fs::remove_dir_all(&base);
218+
std::fs::create_dir_all(&base)?;
216219

217220
let file1 = base.join("one.sql");
218221
let file2 = base.join("two.sql");
219222

220-
fs::write(&file1, "CREATE TABLE t1 (id INTEGER PRIMARY KEY);")?;
223+
std::fs::write(&file1, "CREATE TABLE t1 (id INTEGER PRIMARY KEY);")?;
221224

222225
let pg_sql = r"
223226
CREATE OR REPLACE FUNCTION f()
@@ -233,7 +236,7 @@ mod tests {
233236
234237
CREATE TABLE t2 (id INTEGER PRIMARY KEY);
235238
";
236-
fs::write(&file2, pg_sql)?;
239+
std::fs::write(&file2, pg_sql)?;
237240

238241
let set = SqlSource::sql_sources(&base, &[])?;
239242
let parsed_set = ParsedSqlSourceSet::parse_all::<GenericDialect>(set)?;
@@ -248,7 +251,7 @@ mod tests {
248251
);
249252
}
250253

251-
let _ = fs::remove_dir_all(&base);
254+
let _ = std::fs::remove_dir_all(&base);
252255
Ok(())
253256
}
254257

0 commit comments

Comments
 (0)