in src/data.rs [980:1127]
fn append_sort_key_expression(
sort_key: Option<app::Key>,
partition_key_expression: &str,
sort_key_expression: &str,
mut names: HashMap<String, String>,
mut vals: HashMap<String, AttributeValue>,
) -> Result<GeneratedQueryParams, DyneinQueryParamsError> {
// Check if the target table/index key schema has sort key. If there's no sort key definition, return with Err immediately.
let (sk_name, sk_type) = match sort_key {
Some(sk) => (sk.clone().name, sk.kind.to_string()),
None => return Err(DyneinQueryParamsError::NoSortKeyDefined),
};
// Start building KeyConditionExpression. dynein automatically set placeholders, so currently it would be:
// "#DYNEIN_PKNAME = :DYNEIN_PKVAL AND "
let mut built = format!("{} AND ", partition_key_expression);
debug!(
"Start building KeyConditionExpression. Currently built: '{}'",
&built
);
// iterate over splitted tokens and build expression and mappings.
let mut iter = sort_key_expression.trim().split_whitespace();
// Query API https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditionExpression
match iter.next() {
// sortKeyName = :sortkeyval - true if the sort key value is equal to :sortkeyval.
Some("=") | Some("==") => {
let target_val = iter.next().unwrap();
debug!(
"Equal sign is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("#DYNEIN_SKNAME = :DYNEIN_SKVAL");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// sortKeyName <= :sortkeyval - true if the sort key value is less than or equal to :sortkeyval.
Some("<=") => {
let target_val = iter.next().unwrap();
debug!(
"Less than equal sign is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("#DYNEIN_SKNAME <= :DYNEIN_SKVAL");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// sortKeyName < :sortkeyval - true if the sort key value is less than :sortkeyval.
Some("<") => {
let target_val = iter.next().unwrap();
debug!(
"Less than sign is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("#DYNEIN_SKNAME < :DYNEIN_SKVAL");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// sortKeyName >= :sortkeyval - true if the sort key value is greater than or equal to :sortkeyval.
Some(">=") => {
let target_val = iter.next().unwrap();
debug!(
"Greater than equal sign is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("#DYNEIN_SKNAME >= :DYNEIN_SKVAL");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// sortKeyName > :sortkeyval - true if the sort key value is greater than :sortkeyval.
Some(">") => {
let target_val = iter.next().unwrap();
debug!(
"Greater than sign is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("#DYNEIN_SKNAME > :DYNEIN_SKVAL");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// begins_with ( sortKeyName, :sortkeyval ) - true if the sort key value begins with a particular operand.
// You cannot use this function with a sort key that is of type Number.
Some("begins_with") | Some("BEGINS_WITH") => {
let target_val = iter.next().unwrap();
debug!(
"`begins_with` is detected in sort key expression for the value: '{}'",
&target_val
);
built.push_str("begins_with(#DYNEIN_SKNAME, :DYNEIN_SKVAL)"); // the function name `begins_with` is case-sensitive.
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL"),
build_attrval_scalar(&sk_type, &String::from(target_val)),
);
}
// sortKeyName BETWEEN :sortkeyval1 AND :sortkeyval2 - true if the sort key value is greater than or equal to :sortkeyval1, and less than or equal to :sortkeyval2.
Some("between") | Some("BETWEEN") => {
debug!("`between` is detected in sort key expression.");
let from = iter.next().unwrap();
match iter.next() {
Some("and") | Some("AND") => (),
_ => {
println!("ERROR: between syntax error. e.g. 'BETWEEN 10 AND 99'.");
std::process::exit(1)
}
}
let to = iter.next().unwrap();
debug!("Parsed from/to values: between '{}' and '{}'.", &from, &to);
built.push_str("#DYNEIN_SKNAME BETWEEN :DYNEIN_SKVAL_FROM AND :DYNEIN_SKVAL_TO");
names.insert(String::from("#DYNEIN_SKNAME"), sk_name);
vals.insert(
String::from(":DYNEIN_SKVAL_FROM"),
build_attrval_scalar(&sk_type, &String::from(from)),
);
vals.insert(
String::from(":DYNEIN_SKVAL_TO"),
build_attrval_scalar(&sk_type, &String::from(to)),
);
}
_ => return Err(DyneinQueryParamsError::InvalidSortKeyOption),
};
debug!(
"Finished to build KeyConditionExpression. Currently built: '{}'",
&built
);
Ok(GeneratedQueryParams {
exp: Some(built),
names: if names.is_empty() { None } else { Some(names) },
vals: Some(vals),
})
}