|
|
|
@ -29,6 +29,7 @@ use crate::corestore::memstore::ObjectID;
|
|
|
|
|
use crate::kvengine::encoding;
|
|
|
|
|
use crate::protocol::responses;
|
|
|
|
|
use crate::queryengine::ActionIter;
|
|
|
|
|
use crate::util::compiler;
|
|
|
|
|
use crate::util::Unwrappable;
|
|
|
|
|
use bytes::Bytes;
|
|
|
|
|
use core::str;
|
|
|
|
@ -41,19 +42,25 @@ const STR: &[u8] = "str".as_bytes();
|
|
|
|
|
pub(super) static VALID_CONTAINER_NAME: Lazy<Regex, fn() -> Regex> =
|
|
|
|
|
Lazy::new(|| Regex::new("^[a-zA-Z_$][a-zA-Z_$0-9]*$").unwrap());
|
|
|
|
|
|
|
|
|
|
#[cold]
|
|
|
|
|
#[inline(never)]
|
|
|
|
|
fn cold_err<T>(v: T) -> T {
|
|
|
|
|
v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'static [u8]> {
|
|
|
|
|
let table_name = unsafe { act.next().unsafe_unwrap() };
|
|
|
|
|
let model_name = unsafe { act.next().unsafe_unwrap() };
|
|
|
|
|
if !encoding::is_utf8(&table_name) || !encoding::is_utf8(&model_name) {
|
|
|
|
|
if compiler::unlikely(!encoding::is_utf8(&table_name) || !encoding::is_utf8(&model_name)) {
|
|
|
|
|
return Err(responses::groups::ENCODING_ERROR);
|
|
|
|
|
}
|
|
|
|
|
let table_name_str = unsafe { str::from_utf8_unchecked(&table_name) };
|
|
|
|
|
let model_name_str = unsafe { str::from_utf8_unchecked(&model_name) };
|
|
|
|
|
if !VALID_CONTAINER_NAME.is_match(table_name_str) {
|
|
|
|
|
if compiler::unlikely(!VALID_CONTAINER_NAME.is_match(table_name_str)) {
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
let splits: Vec<&str> = model_name_str.split('(').collect();
|
|
|
|
|
if splits.len() != 2 {
|
|
|
|
|
if compiler::unlikely(splits.len() != 2) {
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
let model_name_split = unsafe { splits.get_unchecked(0) };
|
|
|
|
@ -61,7 +68,7 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
|
|
|
|
|
|
|
|
|
|
// model name has to have at least one char while model args should have
|
|
|
|
|
// atleast `)` 1 chars (for example if the model takes no arguments: `smh()`)
|
|
|
|
|
if model_name_split.is_empty() || model_args_split.is_empty() {
|
|
|
|
|
if compiler::unlikely(model_name_split.is_empty() || model_args_split.is_empty()) {
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -77,7 +84,7 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
|
|
|
|
|
!= b')'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if non_bracketed_end {
|
|
|
|
|
if compiler::unlikely(non_bracketed_end) {
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -86,21 +93,25 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
|
|
|
|
|
.split(',')
|
|
|
|
|
.map(|v| v.trim())
|
|
|
|
|
.collect();
|
|
|
|
|
if model_args.len() != 2 {
|
|
|
|
|
if compiler::unlikely(model_args.len() != 2) {
|
|
|
|
|
// nope, someone had fun with commas or they added more args
|
|
|
|
|
// let's check if it was comma fun or if it was arg fun
|
|
|
|
|
let all_nonzero = model_args.into_iter().all(|v| !v.is_empty());
|
|
|
|
|
if all_nonzero {
|
|
|
|
|
// arg fun
|
|
|
|
|
return Err(responses::groups::TOO_MANY_ARGUMENTS);
|
|
|
|
|
} else {
|
|
|
|
|
// comma fun
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
return cold_err({
|
|
|
|
|
let all_nonzero = model_args.into_iter().all(|v| !v.is_empty());
|
|
|
|
|
if all_nonzero {
|
|
|
|
|
// arg fun
|
|
|
|
|
Err(responses::groups::TOO_MANY_ARGUMENTS)
|
|
|
|
|
} else {
|
|
|
|
|
// comma fun
|
|
|
|
|
Err(responses::groups::BAD_EXPRESSION)
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
let key_ty = unsafe { model_args.get_unchecked(0) };
|
|
|
|
|
let val_ty = unsafe { model_args.get_unchecked(1) };
|
|
|
|
|
if !VALID_CONTAINER_NAME.is_match(key_ty) || !VALID_CONTAINER_NAME.is_match(val_ty) {
|
|
|
|
|
if compiler::unlikely(
|
|
|
|
|
!VALID_CONTAINER_NAME.is_match(key_ty) || !VALID_CONTAINER_NAME.is_match(val_ty),
|
|
|
|
|
) {
|
|
|
|
|
return Err(responses::groups::BAD_EXPRESSION);
|
|
|
|
|
}
|
|
|
|
|
let key_ty = key_ty.as_bytes();
|
|
|
|
@ -113,11 +124,11 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
|
|
|
|
|
_ => return Err(responses::groups::UNKNOWN_DATA_TYPE),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if table_name_str.len() > 64 {
|
|
|
|
|
return Err(responses::groups::CONTAINER_NAME_TOO_LONG);
|
|
|
|
|
if compiler::unlikely(table_name_str.len() > 64) {
|
|
|
|
|
Err(responses::groups::CONTAINER_NAME_TOO_LONG)
|
|
|
|
|
} else {
|
|
|
|
|
Ok((unsafe { ObjectID::from_slice(table_name_str) }, model_code))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok((unsafe { ObjectID::from_slice(table_name_str) }, model_code))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub type EntityGroup<'a> = (Option<&'a [u8]>, Option<&'a [u8]>);
|
|
|
|
@ -128,7 +139,7 @@ pub(super) fn get_query_entity<'a>(input: &'a Bytes) -> Result<EntityGroup<'a>,
|
|
|
|
|
if y.len() == 1 {
|
|
|
|
|
// just tbl
|
|
|
|
|
let tblret = y.get_unchecked(0);
|
|
|
|
|
if tblret.len() > 64 || tblret.is_empty() {
|
|
|
|
|
if compiler::unlikely(tblret.len() > 64 || tblret.is_empty()) {
|
|
|
|
|
Err(responses::groups::BAD_CONTAINER_NAME)
|
|
|
|
|
} else {
|
|
|
|
|
Ok((None, Some(tblret)))
|
|
|
|
@ -137,16 +148,16 @@ pub(super) fn get_query_entity<'a>(input: &'a Bytes) -> Result<EntityGroup<'a>,
|
|
|
|
|
// tbl + ns
|
|
|
|
|
let ksret = y.get_unchecked(0);
|
|
|
|
|
let tblret = y.get_unchecked(1);
|
|
|
|
|
if ksret.len() > 64 || tblret.len() > 64 {
|
|
|
|
|
if compiler::unlikely(ksret.len() > 64 || tblret.len() > 64) {
|
|
|
|
|
Err(responses::groups::BAD_CONTAINER_NAME)
|
|
|
|
|
} else if tblret.is_empty() || ksret.is_empty() {
|
|
|
|
|
} else if compiler::unlikely(tblret.is_empty() || ksret.is_empty()) {
|
|
|
|
|
Err(responses::groups::BAD_EXPRESSION)
|
|
|
|
|
} else {
|
|
|
|
|
Ok((Some(ksret), Some(tblret)))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// something wrong
|
|
|
|
|
Err(responses::groups::BAD_EXPRESSION)
|
|
|
|
|
cold_err(Err(responses::groups::BAD_EXPRESSION))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|