Skip to content

Commit

Permalink
Change the limit value for the default query
Browse files Browse the repository at this point in the history
  • Loading branch information
photino committed Jul 7, 2023
1 parent eccb7aa commit a2d7330
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 46 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ This project is licensed under the [MIT license][license].
[`actix-app`]: https://github.com/photino/zino/tree/main/examples/actix-app
[`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app
[license]: https://github.com/photino/zino/blob/main/LICENSE

## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=photino/zino&type=Date)](https://star-history.com/#photino/zino&Date)
5 changes: 3 additions & 2 deletions zino-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ orm-mysql = ["orm", "sqlx/mysql"]
orm-postgres = ["orm", "sqlx/postgres"]
runtime-async-std = ["sqlx/runtime-async-std"]
runtime-tokio = ["sqlx/runtime-tokio"]
tls-native = ["sqlx/tls-native-tls"]
tls-rustls = ["sqlx/tls-rustls"]
view = ["dep:minijinja"]
view-tera = ["view", "dep:tera"]
view-minijinja = ["view", "dep:minijinja"]
Expand Down Expand Up @@ -94,7 +96,7 @@ metrics-exporter-prometheus = "0.12.1"
multer = "2.1.0"
parking_lot = "0.12.1"
rand = "0.8.5"
regex = "1.8.4"
regex = "1.9.0"
reqwest-middleware = "0.2.2"
reqwest-retry = "0.2.2"
reqwest-tracing = "0.4.5"
Expand Down Expand Up @@ -165,7 +167,6 @@ features = [
"bigdecimal",
"chrono",
"rust_decimal",
"tls-rustls",
"uuid",
]

Expand Down
2 changes: 1 addition & 1 deletion zino-core/src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl ConnectionPool {
if let Some(host) = config.get_str("host") {
connect_options = connect_options.host(host);
}
if let Some(port) = config.get_u16("hport") {
if let Some(port) = config.get_u16("port") {
connect_options = connect_options.port(port);
}
if let Some(statement_cache_capacity) = config.get_usize("statement-cache-capacity") {
Expand Down
25 changes: 10 additions & 15 deletions zino-core/src/database/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,16 @@ impl QueryExt<DatabaseDriver> for Query {
self.sort_order()
}

#[inline]
fn query_offset(&self) -> usize {
self.offset()
}

#[inline]
fn query_limit(&self) -> usize {
self.limit()
}

#[inline]
fn placeholder(_n: usize) -> SharedString {
"?".into()
Expand All @@ -501,21 +511,6 @@ impl QueryExt<DatabaseDriver> for Query {
crate::format::query::prepare_sql_query(query, params, '?')
}

fn format_pagination(&self) -> String {
let limit = self.limit();
if limit == usize::MAX {
return String::new();
}

let (sort_by, _) = self.sort_order();
if self.filters().contains_key(sort_by) {
format!("LIMIT {limit}")
} else {
let offset = self.offset();
format!("LIMIT {offset}, {limit}")
}
}

fn format_field(field: &str) -> Cow<'_, str> {
if field.contains('.') {
field
Expand Down
27 changes: 11 additions & 16 deletions zino-core/src/database/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<'c> EncodeColumn<DatabaseDriver> for Column<'c> {
let condition = format!(r#"array_length({field}, 1) = {value}"#);
conditions.push(condition);
} else if operator == "IN" || operator == "NOT IN" {
if let Some(values) = value.as_array() && !values.is_empty() {
if let Some(values) = value.as_array() {
let field = Query::format_field(field);
let value = values
.iter()
Expand Down Expand Up @@ -494,6 +494,16 @@ impl QueryExt<DatabaseDriver> for Query {
self.sort_order()
}

#[inline]
fn query_offset(&self) -> usize {
self.offset()
}

#[inline]
fn query_limit(&self) -> usize {
self.limit()
}

#[inline]
fn placeholder(n: usize) -> SharedString {
if n == 1 {
Expand All @@ -511,21 +521,6 @@ impl QueryExt<DatabaseDriver> for Query {
crate::format::query::prepare_sql_query(query, params, '$')
}

fn format_pagination(&self) -> String {
let limit = self.limit();
if limit == usize::MAX {
return String::new();
}

let (sort_by, _) = self.sort_order();
if self.filters().contains_key(sort_by) {
format!("LIMIT {limit}")
} else {
let offset = self.offset();
format!("OFFSET {offset} LIMIT {limit} ")
}
}

fn format_field(field: &str) -> Cow<'_, str> {
if field.contains('.') {
field
Expand Down
28 changes: 24 additions & 4 deletions zino-core/src/database/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ pub(super) trait QueryExt<DB> {
/// Returns the sort order.
fn query_order(&self) -> (&str, bool);

/// Returns the query offset.
fn query_offset(&self) -> usize;

/// Returns the query limit.
fn query_limit(&self) -> usize;

/// Returns a placeholder for the n-th parameter.
fn placeholder(n: usize) -> SharedString;

Expand All @@ -26,9 +32,6 @@ pub(super) trait QueryExt<DB> {
params: Option<&'a Map>,
) -> (Cow<'a, str>, Vec<&'a JsonValue>);

/// Formats the query pagination to generate SQL `LIMIT` expression.
fn format_pagination(&self) -> String;

/// Formats a field for the query.
fn format_field(field: &str) -> Cow<'_, str>;

Expand Down Expand Up @@ -71,6 +74,7 @@ pub(super) trait QueryExt<DB> {
}

let (sort_by, ascending) = self.query_order();
let offset = self.query_offset();
let mut expression = String::new();
let mut conditions = Vec::with_capacity(filters.len());
for (key, value) in filters {
Expand Down Expand Up @@ -114,7 +118,7 @@ pub(super) trait QueryExt<DB> {
}
_ => {
if let Some(col) = M::get_column(key) {
let condition = if key == sort_by {
let condition = if key == sort_by && offset > 0 {
// Use the filter condition to optimize pagination offset.
let key = Self::format_field(key);
let operator = if ascending { ">" } else { "<" };
Expand Down Expand Up @@ -160,6 +164,22 @@ pub(super) trait QueryExt<DB> {
}
}

/// Formats the query pagination to generate SQL `LIMIT` expression.
fn format_pagination(&self) -> String {
let limit = self.query_limit();
if limit == usize::MAX {
return String::new();
}

let (sort_by, _) = self.query_order();
if self.query_filters().contains_key(sort_by) {
format!("LIMIT {limit}")
} else {
let offset = self.query_offset();
format!("LIMIT {limit} OFFSET {offset}")
}
}

// Formats the selection with a logic operator.
fn format_selection<M: Schema>(selection: &Map, operator: &str) -> String {
let mut conditions = Vec::with_capacity(selection.len());
Expand Down
1 change: 1 addition & 0 deletions zino-core/src/database/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
let mut query = Query::default();
query.allow_fields(Self::fields());
query.deny_fields(Self::writeonly_fields());
query.set_limit(super::MAX_ROWS.load(Relaxed));
query
}

Expand Down
2 changes: 1 addition & 1 deletion zino-core/src/model/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Query {
filters,
sort_order: (None, false),
offset: 0,
limit: usize::MAX,
limit: 10,
}
}

Expand Down
16 changes: 14 additions & 2 deletions zino-core/src/openapi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub(crate) fn default_paths() -> Paths {
/// Returns the default OpenAPI components.
pub(crate) fn default_components() -> Components {
let mut components = OPENAPI_COMPONENTS.get_or_init(Components::new).clone();

// Default response
let status_schema = ObjectBuilder::new()
.schema_type(SchemaType::Integer)
.example(Some(200.into()))
Expand All @@ -47,8 +49,6 @@ pub(crate) fn default_components() -> Components {
.schema_type(SchemaType::String)
.format(Some(SchemaFormat::KnownFormat(KnownFormat::Uuid)))
.build();

// Default response
let message_schema = ObjectBuilder::new()
.schema_type(SchemaType::String)
.example(Some("OK".into()))
Expand Down Expand Up @@ -90,6 +90,18 @@ pub(crate) fn default_components() -> Components {
let model_id_example = Uuid::new_v4();
let detail_example = format!("404 Not Found: cannot find the model `{model_id_example}`");
let instance_example = format!("/model/{model_id_example}/view");
let status_schema = ObjectBuilder::new()
.schema_type(SchemaType::Integer)
.example(Some(404.into()))
.build();
let success_schema = ObjectBuilder::new()
.schema_type(SchemaType::Boolean)
.example(Some(false.into()))
.build();
let request_id_schema = ObjectBuilder::new()
.schema_type(SchemaType::String)
.format(Some(SchemaFormat::KnownFormat(KnownFormat::Uuid)))
.build();
let title_schema = ObjectBuilder::new()
.schema_type(SchemaType::String)
.example(Some("NotFound".into()))
Expand Down
6 changes: 3 additions & 3 deletions zino-core/src/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub type StatusCode = http::StatusCode;
pub type FullResponse = http::Response<Full<Bytes>>;

/// A function pointer of transforming the response data.
pub type ResponseDataTransformer = fn(data: JsonValue) -> Result<Vec<u8>, Error>;
pub type DataTransformer = fn(data: JsonValue) -> Result<Vec<u8>, Error>;

/// An HTTP response.
#[derive(Debug, Serialize)]
Expand Down Expand Up @@ -72,7 +72,7 @@ pub struct Response<S = StatusCode> {
data: Option<Box<RawValue>>,
/// Transformer of the response data.
#[serde(skip)]
data_transformer: Option<ResponseDataTransformer>,
data_transformer: Option<DataTransformer>,
/// Content type.
#[serde(skip)]
content_type: Option<SharedString>,
Expand Down Expand Up @@ -268,7 +268,7 @@ impl<S: ResponseCode> Response<S> {

/// Sets a transformer for the response data.
#[inline]
pub fn set_data_transformer(&mut self, transformer: ResponseDataTransformer) {
pub fn set_data_transformer(&mut self, transformer: DataTransformer) {
self.data_transformer = Some(transformer);
}

Expand Down
2 changes: 1 addition & 1 deletion zino-model/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ maintainer-id = []
edition = []

[dependencies]
regex = "1.8.4"
regex = "1.9.0"

[dependencies.serde]
version = "1.0.164"
Expand Down
2 changes: 1 addition & 1 deletion zino-model/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct User {
#[cfg(feature = "visibility")]
#[schema(default_value = "Internal")]
visibility: String,
#[schema(default_value = "Active", index_type = "hash")]
#[schema(default_value = "Inactive", index_type = "hash")]
status: String,
#[schema(index_type = "text")]
description: String,
Expand Down

0 comments on commit a2d7330

Please sign in to comment.