Skip to content

Commit

Permalink
Set all datamodel-related flags in structopt
Browse files Browse the repository at this point in the history
  • Loading branch information
Julius de Bruijn committed Mar 20, 2020
1 parent 2f92b67 commit a0c4a9e
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 332 deletions.
6 changes: 5 additions & 1 deletion libs/prisma-models/src/model.rs
Expand Up @@ -51,7 +51,11 @@ impl ModelTemplate {
self.id_field_names,
);

let indexes = self.indexes.into_iter().map(|i| i.build(&fields.all)).collect();
let indexes = self
.indexes
.into_iter()
.map(|i| i.build(&fields.all))
.collect();

// The model is created here and fields WILL BE UNSET before now!
model.fields.set(fields).unwrap();
Expand Down
86 changes: 54 additions & 32 deletions query-engine/prisma/src/cli.rs
@@ -1,46 +1,64 @@
use crate::{
configuration,
context::PrismaContext,
dmmf,
error::PrismaError,
request_handlers::{graphql::*, PrismaRequest, RequestHandler},
PrismaResult, {CliOpt, PrismaOpt, Subcommand},
};
use prisma_models::DatamodelConverter;
use query_core::{
schema::{QuerySchemaRef, SupportedCapabilities},
BuildMode, QuerySchemaBuilder,
};
use std::collections::HashMap;
use std::{convert::TryFrom, fs::File, io::Read, sync::Arc};

use crate::context::PrismaContext;
use crate::error::PrismaError;
use crate::request_handlers::{graphql::*, PrismaRequest, RequestHandler};
use crate::{
data_model_loader::{load_configuration, load_data_model_components},
dmmf, PrismaResult,
};
use crate::{CliOpt, PrismaOpt, Subcommand};
use std::{collections::HashMap, convert::TryFrom, sync::Arc};

#[derive(Debug)]
pub struct ExecuteRequest {
legacy: bool,
query: String,
datamodel: String,
force_transactions: bool,
enable_raw_queries: bool,
legacy: bool,
overwrite_datasources: Option<String>,
}

#[derive(Debug)]
pub struct DmmfRequest {
datamodel: String,
build_mode: BuildMode,
enable_raw_queries: bool,
overwrite_datasources: Option<String>,
}

#[derive(Debug)]
pub struct GetConfigRequest {
datamodel: String,
overwrite_datasources: Option<String>,
}

pub enum CliCommand {
Dmmf(DmmfRequest),
GetConfig(String),
GetConfig(GetConfigRequest),
ExecuteRequest(ExecuteRequest),
}

impl TryFrom<&PrismaOpt> for CliCommand {
type Error = PrismaError;

fn try_from(opts: &PrismaOpt) -> crate::PrismaResult<CliCommand> {
match opts.subcommand {
None => Err(PrismaError::InvocationError(String::from(
"cli subcommand not present",
))),
Some(Subcommand::Cli(ref cliopts)) => match cliopts {
let subcommand = opts.subcommand.clone().ok_or_else(|| {
PrismaError::InvocationError(String::from("cli subcommand not present"))
})?;

let datamodel = opts
.datamodel
.clone()
.xor(opts.datamodel_path.clone())
.expect("Datamodel should be provided either as path or base64-encoded string.");

match subcommand {
Subcommand::Cli(ref cliopts) => match cliopts {
CliOpt::Dmmf => {
let build_mode = if opts.legacy {
BuildMode::Legacy
Expand All @@ -49,23 +67,23 @@ impl TryFrom<&PrismaOpt> for CliCommand {
};

Ok(CliCommand::Dmmf(DmmfRequest {
datamodel,
build_mode,
enable_raw_queries: opts.enable_raw_queries,
overwrite_datasources: opts.overwrite_datasources.clone(),
}))
}
CliOpt::GetConfig(input) => {
let mut file = File::open(&input.path).expect("File should open read only");
let mut datamodel = String::new();

file.read_to_string(&mut datamodel)
.expect("Couldn't read file");
Ok(CliCommand::GetConfig(datamodel))
}
CliOpt::GetConfig => Ok(CliCommand::GetConfig(GetConfigRequest {
datamodel,
overwrite_datasources: opts.overwrite_datasources.clone(),
})),
CliOpt::ExecuteRequest(input) => Ok(CliCommand::ExecuteRequest(ExecuteRequest {
query: input.query.clone(),
force_transactions: opts.always_force_transactions,
overwrite_datasources: opts.overwrite_datasources.clone(),
enable_raw_queries: opts.enable_raw_queries,
legacy: input.legacy,
datamodel,
})),
},
}
Expand All @@ -76,13 +94,16 @@ impl CliCommand {
pub async fn execute(self) -> PrismaResult<()> {
match self {
CliCommand::Dmmf(request) => Self::dmmf(request),
CliCommand::GetConfig(input) => Self::get_config(input),
CliCommand::GetConfig(input) => {
Self::get_config(input.datamodel, input.overwrite_datasources)
}
CliCommand::ExecuteRequest(request) => Self::execute_request(request).await,
}
}

fn dmmf(request: DmmfRequest) -> PrismaResult<()> {
let (v2components, template) = load_data_model_components(true)?;
let dm = datamodel::parse_datamodel(&request.datamodel)?;
let template = DatamodelConverter::convert(&dm);

// temporary code duplication
let internal_data_model = template.build("".into());
Expand All @@ -97,16 +118,16 @@ impl CliCommand {

let query_schema: QuerySchemaRef = Arc::new(schema_builder.build());

let dmmf = dmmf::render_dmmf(&v2components.datamodel, query_schema);
let dmmf = dmmf::render_dmmf(&dm, query_schema);
let serialized = serde_json::to_string_pretty(&dmmf)?;

println!("{}", serialized);

Ok(())
}

fn get_config(input: String) -> PrismaResult<()> {
let config = load_configuration(&input, false)?;
fn get_config(datamodel: String, overwrite_datasources: Option<String>) -> PrismaResult<()> {
let config = configuration::load(&datamodel, overwrite_datasources, false)?;
let json = datamodel::json::mcf::config_to_mcf_json_value(&config);
let serialized = serde_json::to_string(&json)?;

Expand All @@ -119,10 +140,11 @@ impl CliCommand {
let decoded = base64::decode(&request.query)?;
let decoded_request = String::from_utf8(decoded)?;

let ctx = PrismaContext::builder()
let ctx = PrismaContext::builder(request.datamodel)
.legacy(request.legacy)
.force_transactions(request.force_transactions)
.enable_raw_queries(request.enable_raw_queries)
.overwrite_datasources(request.overwrite_datasources)
.build()
.await?;

Expand Down
50 changes: 50 additions & 0 deletions query-engine/prisma/src/configuration.rs
@@ -0,0 +1,50 @@
use crate::{PrismaError, PrismaResult};
use serde::Deserialize;
use serde_json;

/// Loads data model components for the v2 data model.
/// The v2 data model is provided either as file (PRISMA_DML_PATH) or as string in the env (PRISMA_DML).
/// Attempts to construct a Prisma v2 datamodel.
/// Returns: DatamodelV2Components
/// Err If a source for v2 was found, but conversion failed.
/// Ok(Some) If a source for v2 was found, and the conversion suceeded.
/// Ok(None) If no source for a v2 data model was found.
pub fn load(
dml_string: &str,
datasource_overwrites: Option<String>,
ignore_env_var_errors: bool,
) -> PrismaResult<datamodel::Configuration> {
let config_result = if ignore_env_var_errors {
datamodel::parse_configuration_and_ignore_env_errors(&dml_string)
} else {
datamodel::parse_configuration(&dml_string)
};

match config_result {
Err(errors) => Err(PrismaError::ConversionError(errors, dml_string.to_string())),
Ok(mut configuration) => {
if let Some(overwrites) = datasource_overwrites {
let datasource_overwrites: Vec<SourceOverride> = serde_json::from_str(&overwrites)?;

for datasource_override in datasource_overwrites {
for datasource in &mut configuration.datasources {
if &datasource_override.name == datasource.name() {
debug!(
"overwriting datasource {} with url {}",
&datasource_override.name, &datasource_override.url
);
datasource.set_url(&datasource_override.url);
}
}
}
}
Ok(configuration)
}
}
}

#[derive(Deserialize)]
struct SourceOverride {
name: String,
url: String,
}
60 changes: 22 additions & 38 deletions query-engine/prisma/src/context.rs
@@ -1,9 +1,10 @@
use crate::{data_model_loader::*, exec_loader, PrismaError, PrismaResult};
use crate::{configuration, exec_loader, PrismaError, PrismaResult};
use query_core::{
schema::{QuerySchemaRef, SupportedCapabilities},
BuildMode, QueryExecutor, QuerySchemaBuilder,
};
// use prisma_models::InternalDataModelRef;
use datamodel::Datamodel;
use prisma_models::DatamodelConverter;
use std::sync::Arc;

Expand All @@ -16,7 +17,7 @@ pub struct PrismaContext {
query_schema: QuerySchemaRef,

/// DML-based v2 datamodel.
dm: datamodel::Datamodel,
dm: Datamodel,

/// Central query executor.
pub executor: Box<dyn QueryExecutor + Send + Sync + 'static>,
Expand All @@ -26,7 +27,8 @@ pub struct ContextBuilder {
legacy: bool,
force_transactions: bool,
enable_raw_queries: bool,
datamodel: Option<String>,
datamodel: String,
overwrite_datasources: Option<String>,
}

impl ContextBuilder {
Expand All @@ -45,9 +47,8 @@ impl ContextBuilder {
self
}

#[cfg(test)]
pub fn datamodel(mut self, val: String) -> Self {
self.datamodel = Some(val);
pub fn overwrite_datasources(mut self, val: Option<String>) -> Self {
self.overwrite_datasources = val;
self
}

Expand All @@ -57,6 +58,7 @@ impl ContextBuilder {
self.force_transactions,
self.enable_raw_queries,
self.datamodel,
self.overwrite_datasources,
)
.await
}
Expand All @@ -72,37 +74,18 @@ impl PrismaContext {
legacy: bool,
force_transactions: bool,
enable_raw_queries: bool,
datamodel: Option<String>,
datamodel: String,
overwrite_datasources: Option<String>,
) -> PrismaResult<Self> {
// Load data model in order of precedence.
let (v2components, template) = match datamodel {
Some(datamodel_string) => {
let dm = datamodel::parse_datamodel(&datamodel_string)?;

let components = load_configuration(&datamodel_string, false).map(|config| {
DatamodelV2Components {
datamodel: dm,
data_sources: config.datasources,
}
})?;

let template = DatamodelConverter::convert(&components.datamodel);

(components, template)
}
None => load_data_model_components(false)?,
};

let (dm, data_sources) = (v2components.datamodel, v2components.data_sources);
let dm = datamodel::parse_datamodel(&datamodel)?;
let config = configuration::load(&datamodel, overwrite_datasources, false)?;
let template = DatamodelConverter::convert(&dm);

// We only support one data source at the moment, so take the first one (default not exposed yet).
let data_source = if data_sources.is_empty() {
return Err(PrismaError::ConfigurationError(
"No valid data source found".into(),
));
} else {
data_sources.first().unwrap()
};
let data_source = config
.datasources
.first()
.ok_or_else(|| PrismaError::ConfigurationError("No valid data source found".into()))?;

// Load executor
let (db_name, executor) = exec_loader::load(&**data_source, force_transactions).await?;
Expand All @@ -116,6 +99,7 @@ impl PrismaContext {
} else {
BuildMode::Modern
};

let capabilities = SupportedCapabilities::empty(); // todo connector capabilities.

let schema_builder = QuerySchemaBuilder::new(
Expand All @@ -128,27 +112,27 @@ impl PrismaContext {
let query_schema: QuerySchemaRef = Arc::new(schema_builder.build());

Ok(Self {
// internal_data_model,
query_schema,
dm,
executor,
})
}

pub fn builder() -> ContextBuilder {
pub fn builder(datamodel: String) -> ContextBuilder {
ContextBuilder {
legacy: false,
force_transactions: false,
enable_raw_queries: false,
datamodel: None,
overwrite_datasources: None,
datamodel,
}
}

pub fn query_schema(&self) -> &QuerySchemaRef {
&self.query_schema
}

pub fn datamodel(&self) -> &datamodel::Datamodel {
pub fn datamodel(&self) -> &Datamodel {
&self.dm
}

Expand Down

0 comments on commit a0c4a9e

Please sign in to comment.