Skip to content

Commit

Permalink
Generate SQL type definitions for unknown types
Browse files Browse the repository at this point in the history
This commit adds support for generating SQL type definitions for unknown
types to `diesel print-schema`. The basic idea is to generate the
corresponding marker type to always end up with an existing schema.
Especially this does not generate any code that is required for
serializing/deserializing rust values.
  • Loading branch information
weiznich committed May 19, 2021
1 parent c0b6130 commit f1d1393
Show file tree
Hide file tree
Showing 23 changed files with 333 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/

* Add support for HAVING clauses.

* Diesel CLI will now generate SQL type definitions for SQL types that are not supported by diesel out of the box. It's possible to disable this behavior via the `generate_missing_sql_type_definitions` config option.

### Removed

* All previously deprecated items have been removed.
Expand Down
4 changes: 2 additions & 2 deletions diesel/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,10 @@ macro_rules! __diesel_table_impl {
},)+],
) => {
$($meta)*
#[allow(unused_imports)]
pub mod $table_name {
#![allow(dead_code)]
$($imports)*
pub use self::columns::*;
$($imports)*

/// Re-exports all of the columns of this table, as well as the
/// table struct renamed to the module name. This is meant to be
Expand Down
1 change: 0 additions & 1 deletion diesel/src/pg/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ pub mod sql_types {
pub type BigSerial = crate::sql_types::BigInt;

/// The `UUID` SQL type. This type can only be used with `feature = "uuid"`
/// (uuid <=0.6) or `feature = "uuidv07"` (uuid = 0.7)
///
/// ### [`ToSql`] impls
///
Expand Down
7 changes: 7 additions & 0 deletions diesel_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ pub fn build_cli() -> App<'static, 'static> {
.multiple(true)
.number_of_values(1)
.help("A list of types to import for every table, separated by commas"),
)
.arg(
Arg::with_name("generate-custom-type-definitions")
.long("generate-custom-type-definitions")
.takes_value(true)
.possible_values(&["true", "false"])
.help("Generate SQL type definitions for types not provided by diesel"),
);

let config_arg = Arg::with_name("CONFIG_FILE")
Expand Down
6 changes: 6 additions & 0 deletions diesel_cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ pub struct PrintSchema {
pub patch_file: Option<PathBuf>,
#[serde(default)]
pub import_types: Option<Vec<String>>,
#[serde(default)]
pub generate_missing_sql_type_definitions: Option<bool>,
}

impl PrintSchema {
pub fn generate_missing_sql_type_definitions(&self) -> bool {
self.generate_missing_sql_type_definitions.unwrap_or(true)
}

pub fn schema_name(&self) -> Option<&str> {
self.schema.as_deref()
}
Expand Down
4 changes: 2 additions & 2 deletions diesel_cli/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

enum Backend {
pub enum Backend {
#[cfg(feature = "postgres")]
Pg,
#[cfg(feature = "sqlite")]
Expand All @@ -26,7 +26,7 @@ enum Backend {
}

impl Backend {
fn for_url(database_url: &str) -> Self {
pub fn for_url(database_url: &str) -> Self {
match database_url {
_ if database_url.starts_with("postgres://")
|| database_url.starts_with("postgresql://") =>
Expand Down
3 changes: 2 additions & 1 deletion diesel_cli/src/infer_schema_internals/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ pub struct ColumnInformation {
pub nullable: bool,
}

#[derive(Debug)]
#[derive(Debug, PartialEq, Clone)]
pub struct ColumnType {
pub rust_name: String,
pub sql_name: String,
pub is_array: bool,
pub is_nullable: bool,
pub is_unsigned: bool,
Expand Down
1 change: 1 addition & 0 deletions diesel_cli/src/infer_schema_internals/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub fn determine_column_type(
let unsigned = determine_unsigned(&attr.type_name);

Ok(ColumnType {
sql_name: tpe.trim().to_lowercase(),
rust_name: tpe.trim().to_camel_case(),
is_array: false,
is_nullable: attr.nullable,
Expand Down
1 change: 1 addition & 0 deletions diesel_cli/src/infer_schema_internals/pg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub fn determine_column_type(
}

Ok(ColumnType {
sql_name: tpe.to_lowercase(),
rust_name: tpe.to_camel_case(),
is_array,
is_nullable: attr.nullable,
Expand Down
3 changes: 2 additions & 1 deletion diesel_cli/src/infer_schema_internals/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ pub fn determine_column_type(
};

Ok(ColumnType {
rust_name: path,
rust_name: path.clone(),
sql_name: path,
is_array: false,
is_nullable: attr.nullable,
is_unsigned: false,
Expand Down
4 changes: 4 additions & 0 deletions diesel_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,10 @@ fn run_infer_schema(matches: &ArgMatches) -> Result<(), Box<dyn Error + Send + S
config.import_types = Some(types);
}

if let Some(generate_types) = matches.value_of("generate-custom-type-definitions") {
config.generate_missing_sql_type_definitions = Some(generate_types.parse()?);
}

run_print_schema(&database_url, &config, &mut stdout())?;
Ok(())
}
Expand Down
Loading

0 comments on commit f1d1393

Please sign in to comment.