<commit_before>#[cfg(feature = "bigdecimal")]
mod bigdecimal {
    // NOTE: No `std::ops::MulAssign` impl for `BigInt`
    #![cfg_attr(feature = "cargo-clippy", allow(assign_op_pattern))]

    extern crate bigdecimal;
    extern crate num_bigint;
    extern crate num_integer;
    extern crate num_traits;

    use self::bigdecimal::BigDecimal;
    use self::num_bigint::{BigInt, BigUint, Sign};
    use self::num_integer::Integer;
    use self::num_traits::{Signed, ToPrimitive, Zero};
    use std::io::prelude::*;

    use deserialize::{self, FromSql};
    use pg::data_types::PgNumeric;
    use pg::Pg;
    use serialize::{self, Output, ToSql};
    use sql_types::Numeric;

    #[cfg(feature = "unstable")]
    use std::convert::{TryFrom, TryInto};
    #[cfg(feature = "unstable")]
    use std::error::Error;

    /// Iterator over the digits of a big uint in base 10k.
    /// The digits will be returned in little endian order.
    struct ToBase10000(Option<BigUint>);

    impl Iterator for ToBase10000 {
        type Item = i16;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.take().map(|v| {
                let (div, rem) = v.div_rem(&BigUint::from(10_000u16));
                if !div.is_zero() {
                    self.0 = Some(div);
                }
                rem.to_i16().expect("10000 always fits in an i16")
            })
        }
    }

    fn pg_decimal_to_bigdecimal(numeric: &PgNumeric) -> deserialize::Result<BigDecimal> {
        let (sign, weight, scale, digits) = match *numeric {
            PgNumeric::Positive {
                weight,
                scale,
                ref digits,
            } => (Sign::Plus, weight, scale, digits),
            PgNumeric::Negative {
                weight,
                scale,
                ref digits,
            } => (Sign::Minus, weight, scale, digits),
            PgNumeric::NaN => return Err(Box::from("NaN is not (yet) supported in BigDecimal")),
        };

        let mut result = BigUint::default();
        let count = digits.len() as i64;
        for digit in digits {
            result *= BigUint::from(10_000u64);
            result += BigUint::from(*digit as u64);
        }
        // First digit got factor 10_000^(digits.len() - 1), but should get 10_000^weight
        let correction_exp = 4 * (i64::from(weight) - count + 1);
        let result = BigDecimal::new(BigInt::from_biguint(sign, result), -correction_exp)
            .with_scale(i64::from(scale));
        Ok(result)
    }

    #[cfg(feature = "unstable")]
    impl<'a> TryFrom<&'a PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self> {
            pg_decimal_to_bigdecimal(numeric)
        }
    }

    #[cfg(feature = "unstable")]
    impl TryFrom<PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
            (&numeric).try_into()
        }
    }

    impl<'a> From<&'a BigDecimal> for PgNumeric {
        fn from(decimal: &'a BigDecimal) -> Self {
            let (mut integer, scale) = decimal.as_bigint_and_exponent();
            let scale = scale as u16;
            integer = integer.abs();

            // Ensure that the decimal will always lie on a digit boundary
            for _ in 0..(4 - scale % 4) {
                integer = integer * 10;
            }
            let integer = integer.to_biguint().expect("integer is always positive");

            let mut digits = ToBase10000(Some(integer)).collect::<Vec<_>>();
            digits.reverse();
            let digits_after_decimal = scale as u16 / 4 + 1;
            let weight = digits.len() as i16 - digits_after_decimal as i16 - 1;

            let unnecessary_zeroes = if weight >= 0 {
                let index_of_decimal = (weight + 1) as usize;
                digits
                    .get(index_of_decimal..)
                    .expect("enough digits exist")
                    .iter()
                    .rev()
                    .take_while(|i| i.is_zero())
                    .count()
            } else {
                0
            };

            let relevant_digits = digits.len() - unnecessary_zeroes;
            digits.truncate(relevant_digits);

            match decimal.sign() {
                Sign::Plus => PgNumeric::Positive {
                    digits,
                    scale,
                    weight,
                },
                Sign::Minus => PgNumeric::Negative {
                    digits,
                    scale,
                    weight,
                },
                Sign::NoSign => PgNumeric::Positive {
                    digits: vec![0],
                    scale: 0,
                    weight: 0,
                },
            }
        }
    }

    impl From<BigDecimal> for PgNumeric {
        fn from(bigdecimal: BigDecimal) -> Self {
            (&bigdecimal).into()
        }
    }

    impl ToSql<Numeric, Pg> for BigDecimal {
        fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
            let numeric = PgNumeric::from(self);
            ToSql::<Numeric, Pg>::to_sql(&numeric, out)
        }
    }

    impl FromSql<Numeric, Pg> for BigDecimal {
        fn from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self> {
            // FIXME: Use the TryFrom impl when try_from is stable
            let numeric = PgNumeric::from_sql(numeric)?;
            pg_decimal_to_bigdecimal(&numeric)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;
        use std::str::FromStr;

        #[test]
        fn bigdecimal_to_pgnumeric_converts_digits_to_base_10000() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![10],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 0],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 0,
                digits: vec![1, 0, 0],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_properly_adjusts_scale() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.0").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 2,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000.0001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 4,
                digits: vec![1, 0, 0, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("0.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: -1,
                scale: 1,
                digits: vec![1000],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_retains_sign() {
            let decimal = BigDecimal::from_str("123.456").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("-123.456").unwrap();
            let expected = PgNumeric::Negative {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        #[cfg(feature = "unstable")]
        fn pg_numeric_to_bigdecimal_works() {
            let expected = BigDecimal::from_str("123.456").unwrap();
            let pg_numeric = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);

            let expected = BigDecimal::from_str("-56.78").unwrap();
            let pg_numeric = PgNumeric::Negative {
                weight: 0,
                scale: 2,
                digits: vec![56, 7800],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);
        }
    }
}
<commit_msg>Move clippy cfg_attr for bigdecimal to function scope<commit_after>#[cfg(feature = "bigdecimal")]
mod bigdecimal {
    extern crate bigdecimal;
    extern crate num_bigint;
    extern crate num_integer;
    extern crate num_traits;

    use self::bigdecimal::BigDecimal;
    use self::num_bigint::{BigInt, BigUint, Sign};
    use self::num_integer::Integer;
    use self::num_traits::{Signed, ToPrimitive, Zero};
    use std::io::prelude::*;

    use deserialize::{self, FromSql};
    use pg::data_types::PgNumeric;
    use pg::Pg;
    use serialize::{self, Output, ToSql};
    use sql_types::Numeric;

    #[cfg(feature = "unstable")]
    use std::convert::{TryFrom, TryInto};
    #[cfg(feature = "unstable")]
    use std::error::Error;

    /// Iterator over the digits of a big uint in base 10k.
    /// The digits will be returned in little endian order.
    struct ToBase10000(Option<BigUint>);

    impl Iterator for ToBase10000 {
        type Item = i16;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.take().map(|v| {
                let (div, rem) = v.div_rem(&BigUint::from(10_000u16));
                if !div.is_zero() {
                    self.0 = Some(div);
                }
                rem.to_i16().expect("10000 always fits in an i16")
            })
        }
    }

    fn pg_decimal_to_bigdecimal(numeric: &PgNumeric) -> deserialize::Result<BigDecimal> {
        let (sign, weight, scale, digits) = match *numeric {
            PgNumeric::Positive {
                weight,
                scale,
                ref digits,
            } => (Sign::Plus, weight, scale, digits),
            PgNumeric::Negative {
                weight,
                scale,
                ref digits,
            } => (Sign::Minus, weight, scale, digits),
            PgNumeric::NaN => return Err(Box::from("NaN is not (yet) supported in BigDecimal")),
        };

        let mut result = BigUint::default();
        let count = digits.len() as i64;
        for digit in digits {
            result *= BigUint::from(10_000u64);
            result += BigUint::from(*digit as u64);
        }
        // First digit got factor 10_000^(digits.len() - 1), but should get 10_000^weight
        let correction_exp = 4 * (i64::from(weight) - count + 1);
        let result = BigDecimal::new(BigInt::from_biguint(sign, result), -correction_exp)
            .with_scale(i64::from(scale));
        Ok(result)
    }

    #[cfg(feature = "unstable")]
    impl<'a> TryFrom<&'a PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self> {
            pg_decimal_to_bigdecimal(numeric)
        }
    }

    #[cfg(feature = "unstable")]
    impl TryFrom<PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
            (&numeric).try_into()
        }
    }

    impl<'a> From<&'a BigDecimal> for PgNumeric {
        // NOTE(clippy): No `std::ops::MulAssign` impl for `BigInt`
        #[cfg_attr(feature = "cargo-clippy", allow(assign_op_pattern))]
        fn from(decimal: &'a BigDecimal) -> Self {
            let (mut integer, scale) = decimal.as_bigint_and_exponent();
            let scale = scale as u16;
            integer = integer.abs();

            // Ensure that the decimal will always lie on a digit boundary
            for _ in 0..(4 - scale % 4) {
                integer = integer * 10;
            }
            let integer = integer.to_biguint().expect("integer is always positive");

            let mut digits = ToBase10000(Some(integer)).collect::<Vec<_>>();
            digits.reverse();
            let digits_after_decimal = scale as u16 / 4 + 1;
            let weight = digits.len() as i16 - digits_after_decimal as i16 - 1;

            let unnecessary_zeroes = if weight >= 0 {
                let index_of_decimal = (weight + 1) as usize;
                digits
                    .get(index_of_decimal..)
                    .expect("enough digits exist")
                    .iter()
                    .rev()
                    .take_while(|i| i.is_zero())
                    .count()
            } else {
                0
            };

            let relevant_digits = digits.len() - unnecessary_zeroes;
            digits.truncate(relevant_digits);

            match decimal.sign() {
                Sign::Plus => PgNumeric::Positive {
                    digits,
                    scale,
                    weight,
                },
                Sign::Minus => PgNumeric::Negative {
                    digits,
                    scale,
                    weight,
                },
                Sign::NoSign => PgNumeric::Positive {
                    digits: vec![0],
                    scale: 0,
                    weight: 0,
                },
            }
        }
    }

    impl From<BigDecimal> for PgNumeric {
        fn from(bigdecimal: BigDecimal) -> Self {
            (&bigdecimal).into()
        }
    }

    impl ToSql<Numeric, Pg> for BigDecimal {
        fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
            let numeric = PgNumeric::from(self);
            ToSql::<Numeric, Pg>::to_sql(&numeric, out)
        }
    }

    impl FromSql<Numeric, Pg> for BigDecimal {
        fn from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self> {
            // FIXME: Use the TryFrom impl when try_from is stable
            let numeric = PgNumeric::from_sql(numeric)?;
            pg_decimal_to_bigdecimal(&numeric)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;
        use std::str::FromStr;

        #[test]
        fn bigdecimal_to_pgnumeric_converts_digits_to_base_10000() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![10],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 0],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 0,
                digits: vec![1, 0, 0],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_properly_adjusts_scale() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.0").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 2,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000.0001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 4,
                digits: vec![1, 0, 0, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("0.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: -1,
                scale: 1,
                digits: vec![1000],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_retains_sign() {
            let decimal = BigDecimal::from_str("123.456").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("-123.456").unwrap();
            let expected = PgNumeric::Negative {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        #[cfg(feature = "unstable")]
        fn pg_numeric_to_bigdecimal_works() {
            let expected = BigDecimal::from_str("123.456").unwrap();
            let pg_numeric = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);

            let expected = BigDecimal::from_str("-56.78").unwrap();
            let pg_numeric = PgNumeric::Negative {
                weight: 0,
                scale: 2,
                digits: vec![56, 7800],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);
        }
    }
}
<|endoftext|>


<commit_before>//! Types related to describing schema, and interactions between tables.
//!
//! Most traits in this module are derived or generated by [`table!`].
//!
//! [`table!`]: crate::table!
mod alias;
#[doc(hidden)]
pub mod joins;
mod peano_numbers;

use crate::expression::{Expression, SelectableExpression, ValidGrouping};
use crate::query_builder::*;

#[doc(hidden)]
pub use self::alias::{
    Alias, AliasAliasAppearsInFromClause, AliasAppearsInFromClause, AliasSource, AliasedField,
    FieldAliasMapper, FieldAliasMapperAssociatedTypesDisjointnessTrick,
};
pub use self::joins::JoinTo;
pub use self::peano_numbers::*;

/// Represents a type which can appear in the `FROM` clause. Apps should not
/// need to concern themselves with this trait.
///
/// Types which implement this trait include:
/// - Tables generated by the `table!` macro
/// - Internal structs which represent joins
/// - A select statement which has had no query builder methods called on it,
///   other than those which can affect the from clause.
pub trait QuerySource {
    /// The type returned by `from_clause`
    type FromClause;
    /// The type returned by `default_selection`
    type DefaultSelection: SelectableExpression<Self>;

    /// The actual `FROM` clause of this type. This is typically only called in
    /// `QueryFragment` implementations.
    fn from_clause(&self) -> Self::FromClause;
    /// The default select clause of this type, which should be used if no
    /// select clause was explicitly specified. This should always be a tuple of
    /// all the desired columns, not `star`
    fn default_selection(&self) -> Self::DefaultSelection;
}

/// A column on a database table. Types which implement this trait should have
/// been generated by the [`table!` macro](crate::table!).
pub trait Column: Expression {
    /// The table which this column belongs to
    type Table: Table;

    /// The name of this column
    const NAME: &'static str;
}

/// A SQL database table. Types which implement this trait should have been
/// generated by the [`table!` macro](crate::table!).
pub trait Table: QuerySource + AsQuery + Sized {
    /// The type returned by `primary_key`
    type PrimaryKey: SelectableExpression<Self> + ValidGrouping<()>;
    /// The type returned by `all_columns`
    type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;

    /// Returns the primary key of this table.
    ///
    /// If the table has a composite primary key, this will be a tuple.
    fn primary_key(&self) -> Self::PrimaryKey;
    /// Returns a tuple of all columns belonging to this table.
    fn all_columns() -> Self::AllColumns;
}

/// Determines how many times `Self` appears in `QS`
///
/// This trait is primarily used to determine whether or not a column is
/// selectable from a given from clause. A column can be selected if its table
/// appears in the from clause *exactly once*.
///
/// We do not allow the same table to appear in a query multiple times in any
/// context where referencing that table would be ambiguous (depending on the
/// context and backend being used, this may or may not be something that would
/// otherwise result in a runtime error).
pub trait AppearsInFromClause<QS> {
    /// How many times does `Self` appear in `QS`?
    type Count;
}

/// Allows Diesel to determine whether two tables are equal.
///
/// This trait is implemented by the `allow_tables_to_appear_in_same_query!` macro,
/// and allows diesel to implement a bunch of `AppearsInFromClause` for the tables and their
/// aliases.
pub trait TableNotEqual<T: Table>: Table {}

impl<T1, T2> AppearsInFromClause<T2> for T1
where
    T1: TableNotEqual<T2> + Table,
    T2: Table,
{
    type Count = Never;
}

#[doc(hidden)]
/// Used to determine which of two from clauses contains a given table.
///
/// This trait can be used to emulate "or" conditions in where clauses when
/// we want a trait to be implemented with one of two type parameters.
///
/// For example, if we wanted to write:
///
/// ```rust,ignore
/// where
///     T: SelectableExpression<Left> | SelectableExpression<Right>,
/// ```
///
/// we can emulate this by writing:
///
/// ```rust,ignore
/// where
///     Left: AppearsInFromClause<T::Table>,
///     Right: AppearsInFromClause<T::Table>,
///     (Left::Count, Right::Count): Pick<Left, Right>,
///     T: SelectableExpression<
///         <(Left::Count, Right::Count) as Pick<Left, Right>>::Selection,
///     >,
/// ```
///
/// In order to aquire the counts in the first place, we must already know
/// the table we're searching for.
pub trait Pick<Left, Right> {
    /// The selected type.
    ///
    /// For `(Once, Never)` this type will be `Left`. For `(Never, Once)`, this type will be
    /// `Right`
    type Selection;
}

impl<Left, Right> Pick<Left, Right> for (Once, Never) {
    type Selection = Left;
}

impl<Left, Right> Pick<Left, Right> for (Never, Once) {
    type Selection = Right;
}

#[doc(hidden)]
#[allow(
    non_camel_case_types,
    missing_debug_implementations,
    missing_copy_implementations
)]
/// Everything in this module is here to give something more helpful than:
///
/// > (Never, Never): Pick<table1, table2> is not satisifed
///
/// Any of these impls can be deleted if they are getting in the way of
/// other functionality. Any code which is using these impls is already
/// failing to compile.
mod impls_which_are_only_here_to_improve_error_messages {
    use super::*;

    pub struct this_table_doesnt_appear_in_the_from_clause_of_your_query;

    impl<Left, Right> Pick<Left, Right> for (Never, Never) {
        type Selection = this_table_doesnt_appear_in_the_from_clause_of_your_query;
    }

    pub struct this_table_appears_in_your_query_more_than_once_and_must_be_aliased;

    impl<Left, Right, OtherCount> Pick<Left, Right> for (MoreThanOnce, OtherCount) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Never, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Once, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }
}
<commit_msg>improve doc<commit_after>//! Types related to describing schema, and interactions between tables.
//!
//! Most traits in this module are derived or generated by [`table!`].
//!
//! [`table!`]: crate::table!
mod alias;
#[doc(hidden)]
pub mod joins;
mod peano_numbers;

use crate::expression::{Expression, SelectableExpression, ValidGrouping};
use crate::query_builder::*;

pub use self::alias::{
    Alias, AliasAliasAppearsInFromClause, AliasAppearsInFromClause, AliasSource, AliasedField,
    FieldAliasMapper, FieldAliasMapperAssociatedTypesDisjointnessTrick,
};
pub use self::joins::JoinTo;
pub use self::peano_numbers::*;

/// Represents a type which can appear in the `FROM` clause. Apps should not
/// need to concern themselves with this trait.
///
/// Types which implement this trait include:
/// - Tables generated by the `table!` macro
/// - Internal structs which represent joins
/// - A select statement which has had no query builder methods called on it,
///   other than those which can affect the from clause.
pub trait QuerySource {
    /// The type returned by `from_clause`
    type FromClause;
    /// The type returned by `default_selection`
    type DefaultSelection: SelectableExpression<Self>;

    /// The actual `FROM` clause of this type. This is typically only called in
    /// `QueryFragment` implementations.
    fn from_clause(&self) -> Self::FromClause;
    /// The default select clause of this type, which should be used if no
    /// select clause was explicitly specified. This should always be a tuple of
    /// all the desired columns, not `star`
    fn default_selection(&self) -> Self::DefaultSelection;
}

/// A column on a database table. Types which implement this trait should have
/// been generated by the [`table!` macro](crate::table!).
pub trait Column: Expression {
    /// The table which this column belongs to
    type Table: Table;

    /// The name of this column
    const NAME: &'static str;
}

/// A SQL database table. Types which implement this trait should have been
/// generated by the [`table!` macro](crate::table!).
pub trait Table: QuerySource + AsQuery + Sized {
    /// The type returned by `primary_key`
    type PrimaryKey: SelectableExpression<Self> + ValidGrouping<()>;
    /// The type returned by `all_columns`
    type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;

    /// Returns the primary key of this table.
    ///
    /// If the table has a composite primary key, this will be a tuple.
    fn primary_key(&self) -> Self::PrimaryKey;
    /// Returns a tuple of all columns belonging to this table.
    fn all_columns() -> Self::AllColumns;
}

/// Determines how many times `Self` appears in `QS`
///
/// This trait is primarily used to determine whether or not a column is
/// selectable from a given from clause. A column can be selected if its table
/// appears in the from clause *exactly once*.
///
/// We do not allow the same table to appear in a query multiple times in any
/// context where referencing that table would be ambiguous (depending on the
/// context and backend being used, this may or may not be something that would
/// otherwise result in a runtime error).
pub trait AppearsInFromClause<QS> {
    /// How many times does `Self` appear in `QS`?
    type Count;
}

/// Allows Diesel to implement some internal traits for two tables that are distinct.
///
/// (Notably, a bunch of [`AppearsInFromClause`] for the tables and their aliases.)
///
/// This trait is implemented by the [`allow_tables_to_appear_in_same_query!`] macro.
///
/// Troubleshooting
/// ---------------
/// If you encounter an error mentionning this trait, it could mean that either:
/// - You are attempting to use tables that don't belong to the same database together
///   (no call to [`allow_tables_to_appear_in_same_query!`] was made)
/// - You are attempting to use two aliases to the same table in the same query, but they
///   were declared through different calls to [`alias!`](crate::alias)
pub trait TableNotEqual<T: Table>: Table {}

impl<T1, T2> AppearsInFromClause<T2> for T1
where
    T1: TableNotEqual<T2> + Table,
    T2: Table,
{
    type Count = Never;
}

#[doc(hidden)]
/// Used to determine which of two from clauses contains a given table.
///
/// This trait can be used to emulate "or" conditions in where clauses when
/// we want a trait to be implemented with one of two type parameters.
///
/// For example, if we wanted to write:
///
/// ```rust,ignore
/// where
///     T: SelectableExpression<Left> | SelectableExpression<Right>,
/// ```
///
/// we can emulate this by writing:
///
/// ```rust,ignore
/// where
///     Left: AppearsInFromClause<T::Table>,
///     Right: AppearsInFromClause<T::Table>,
///     (Left::Count, Right::Count): Pick<Left, Right>,
///     T: SelectableExpression<
///         <(Left::Count, Right::Count) as Pick<Left, Right>>::Selection,
///     >,
/// ```
///
/// In order to aquire the counts in the first place, we must already know
/// the table we're searching for.
pub trait Pick<Left, Right> {
    /// The selected type.
    ///
    /// For `(Once, Never)` this type will be `Left`. For `(Never, Once)`, this type will be
    /// `Right`
    type Selection;
}

impl<Left, Right> Pick<Left, Right> for (Once, Never) {
    type Selection = Left;
}

impl<Left, Right> Pick<Left, Right> for (Never, Once) {
    type Selection = Right;
}

#[doc(hidden)]
#[allow(
    non_camel_case_types,
    missing_debug_implementations,
    missing_copy_implementations
)]
/// Everything in this module is here to give something more helpful than:
///
/// > (Never, Never): Pick<table1, table2> is not satisifed
///
/// Any of these impls can be deleted if they are getting in the way of
/// other functionality. Any code which is using these impls is already
/// failing to compile.
mod impls_which_are_only_here_to_improve_error_messages {
    use super::*;

    pub struct this_table_doesnt_appear_in_the_from_clause_of_your_query;

    impl<Left, Right> Pick<Left, Right> for (Never, Never) {
        type Selection = this_table_doesnt_appear_in_the_from_clause_of_your_query;
    }

    pub struct this_table_appears_in_your_query_more_than_once_and_must_be_aliased;

    impl<Left, Right, OtherCount> Pick<Left, Right> for (MoreThanOnce, OtherCount) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Never, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Once, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate phf_codegen;
extern crate flate2;

use std::{env, fmt, io};
use std::borrow::{Borrow, Cow};
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{BufReader, BufWriter, Write};
use std::path::{Path, PathBuf};

use walkdir::WalkDir;

use flate2::write::GzEncoder;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Compression {
    None,
    Gzip
}

impl fmt::Display for Compression {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Compression::None => fmt.write_str("None"),
            Compression::Gzip => fmt.write_str("Gzip"),
        }
    }
}

pub struct IncludeDir {
    files: HashMap<String, (Compression, PathBuf)>,
    name: String,
    manifest_dir: PathBuf
}

pub fn start(static_name: &str) -> IncludeDir {
    IncludeDir {
        files: HashMap::new(),
        name: static_name.to_owned(),
        manifest_dir: Path::new(&env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not set")).to_owned()
    }
}

#[cfg(windows)]
fn as_key(path: &str) -> Cow<str> {
    Cow::Owned(path.replace("\\", "/"))
}

#[cfg(not(windows))]
fn as_key(path: &str) -> Cow<str> {
    Cow::Borrowed(path)
}

impl IncludeDir {
    /// Add a single file to the binary.
    /// With Gzip compression, the file will be encoded to OUT_DIR first.
    /// For chaining, it's not sensible to return a Result. If any to-be-included
    /// files can't be found, or encoded, this function will panic!.
    pub fn file<P: AsRef<Path>>(mut self, path: P, comp: Compression) -> IncludeDir {
        self.add_file(path, comp).unwrap();
        self
    }

    /// ## Panics
    ///
    /// This function panics when CARGO_MANIFEST_DIR or OUT_DIR are not defined.
    pub fn add_file<P: AsRef<Path>>(&mut self, path: P, comp: Compression) -> io::Result<()> {
        let key = path.as_ref().to_string_lossy();
        println!("cargo:rerun-if-changed={}", path.as_ref().display());

        match comp {
            Compression::None => {
                self.files.insert(as_key(key.borrow()).into_owned(),
                                  (comp, path.as_ref().clone().to_owned()));
            }
            Compression::Gzip => {
                // gzip encode file to OUT_DIR
                let in_path = self.manifest_dir.join(&path);
                let mut in_file = BufReader::new(File::open(&in_path)?);

                let out_path = Path::new(&env::var("OUT_DIR").unwrap()).join(&path);
                fs::create_dir_all(&out_path.parent().unwrap())?;
                let out_file = BufWriter::new(File::create(&out_path)?);
                let mut encoder = GzEncoder::new(out_file, flate2::Compression::best());

                io::copy(&mut in_file, &mut encoder)?;

                self.files.insert(as_key(key.borrow()).into_owned(),
                                  (comp, out_path.to_owned()));
            }
        }
        Ok(())
    }

    /// Add a whole directory recursively to the binary.
    /// This function calls `file`, and therefore will panic! on missing files.
    pub fn dir<P: AsRef<Path>>(mut self, path: P, comp: Compression) -> IncludeDir {
        self.add_dir(path, comp).unwrap();
        self
    }

    /// ## Panics
    ///
    /// This function panics when CARGO_MANIFEST_DIR or OUT_DIR are not defined.
    pub fn add_dir<P: AsRef<Path>>(&mut self, path: P, comp: Compression) -> io::Result<()> {
        for entry in WalkDir::new(path).follow_links(true).into_iter() {
            match entry {
                Ok(ref e) if !e.file_type().is_dir() => {
                    self.add_file(e.path(), comp)?;
                }
                _ => (),
            }
        }
        Ok(())
    }

    pub fn build(self, out_name: &str) -> io::Result<()> {
        let out_path = Path::new(&env::var("OUT_DIR").unwrap()).join(out_name);
        let mut out_file = BufWriter::new(File::create(&out_path)?);

        write!(&mut out_file,
               "use includedir::*;\n\
                pub static {}: Files = Files {{\n\
                    files:  ",
                self.name)?;

        let mut map: phf_codegen::Map<String> = phf_codegen::Map::new();

        for (name, (compression, path)) in self.files {
            let include_path = format!("{}", self.manifest_dir.join(path).display());

            map.entry(as_key(&name).into_owned(),
                      &format!("(Compression::{}, \
                                include_bytes!(\"{}\") as &'static [u8])",
                               compression, as_key(&include_path)));
        }

        map.build(&mut out_file)?;

        write!(&mut out_file, ", passthrough: ::std::sync::atomic::AtomicBool::new(false)")?;
        write!(&mut out_file, "\n}};\n")?;
        Ok(())
    }
}
<commit_msg>Remove unnecessary clone (of reference)<commit_after>extern crate walkdir;
extern crate phf_codegen;
extern crate flate2;

use std::{env, fmt, io};
use std::borrow::{Borrow, Cow};
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{BufReader, BufWriter, Write};
use std::path::{Path, PathBuf};

use walkdir::WalkDir;

use flate2::write::GzEncoder;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Compression {
    None,
    Gzip
}

impl fmt::Display for Compression {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Compression::None => fmt.write_str("None"),
            Compression::Gzip => fmt.write_str("Gzip"),
        }
    }
}

pub struct IncludeDir {
    files: HashMap<String, (Compression, PathBuf)>,
    name: String,
    manifest_dir: PathBuf
}

pub fn start(static_name: &str) -> IncludeDir {
    IncludeDir {
        files: HashMap::new(),
        name: static_name.to_owned(),
        manifest_dir: Path::new(&env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not set")).to_owned()
    }
}

#[cfg(windows)]
fn as_key(path: &str) -> Cow<str> {
    Cow::Owned(path.replace("\\", "/"))
}

#[cfg(not(windows))]
fn as_key(path: &str) -> Cow<str> {
    Cow::Borrowed(path)
}

impl IncludeDir {
    /// Add a single file to the binary.
    /// With Gzip compression, the file will be encoded to OUT_DIR first.
    /// For chaining, it's not sensible to return a Result. If any to-be-included
    /// files can't be found, or encoded, this function will panic!.
    pub fn file<P: AsRef<Path>>(mut self, path: P, comp: Compression) -> IncludeDir {
        self.add_file(path, comp).unwrap();
        self
    }

    /// ## Panics
    ///
    /// This function panics when CARGO_MANIFEST_DIR or OUT_DIR are not defined.
    pub fn add_file<P: AsRef<Path>>(&mut self, path: P, comp: Compression) -> io::Result<()> {
        let key = path.as_ref().to_string_lossy();
        println!("cargo:rerun-if-changed={}", path.as_ref().display());

        match comp {
            Compression::None => {
                self.files.insert(as_key(key.borrow()).into_owned(),
                                  (comp, path.as_ref().to_owned()));
            }
            Compression::Gzip => {
                // gzip encode file to OUT_DIR
                let in_path = self.manifest_dir.join(&path);
                let mut in_file = BufReader::new(File::open(&in_path)?);

                let out_path = Path::new(&env::var("OUT_DIR").unwrap()).join(&path);
                fs::create_dir_all(&out_path.parent().unwrap())?;
                let out_file = BufWriter::new(File::create(&out_path)?);
                let mut encoder = GzEncoder::new(out_file, flate2::Compression::best());

                io::copy(&mut in_file, &mut encoder)?;

                self.files.insert(as_key(key.borrow()).into_owned(),
                                  (comp, out_path.to_owned()));
            }
        }
        Ok(())
    }

    /// Add a whole directory recursively to the binary.
    /// This function calls `file`, and therefore will panic! on missing files.
    pub fn dir<P: AsRef<Path>>(mut self, path: P, comp: Compression) -> IncludeDir {
        self.add_dir(path, comp).unwrap();
        self
    }

    /// ## Panics
    ///
    /// This function panics when CARGO_MANIFEST_DIR or OUT_DIR are not defined.
    pub fn add_dir<P: AsRef<Path>>(&mut self, path: P, comp: Compression) -> io::Result<()> {
        for entry in WalkDir::new(path).follow_links(true).into_iter() {
            match entry {
                Ok(ref e) if !e.file_type().is_dir() => {
                    self.add_file(e.path(), comp)?;
                }
                _ => (),
            }
        }
        Ok(())
    }

    pub fn build(self, out_name: &str) -> io::Result<()> {
        let out_path = Path::new(&env::var("OUT_DIR").unwrap()).join(out_name);
        let mut out_file = BufWriter::new(File::create(&out_path)?);

        write!(&mut out_file,
               "use includedir::*;\n\
                pub static {}: Files = Files {{\n\
                    files:  ",
                self.name)?;

        let mut map: phf_codegen::Map<String> = phf_codegen::Map::new();

        for (name, (compression, path)) in self.files {
            let include_path = format!("{}", self.manifest_dir.join(path).display());

            map.entry(as_key(&name).into_owned(),
                      &format!("(Compression::{}, \
                                include_bytes!(\"{}\") as &'static [u8])",
                               compression, as_key(&include_path)));
        }

        map.build(&mut out_file)?;

        write!(&mut out_file, ", passthrough: ::std::sync::atomic::AtomicBool::new(false)")?;
        write!(&mut out_file, "\n}};\n")?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{fs::File,
          io::prelude::*,
          path::Path,
          str::FromStr};

use crate::{common::ui::UI,
            hcore::{package::{PackageArchive,
                              PackageIdent},
                    service::ServiceBind}};
use base64;
use clap::ArgMatches;

use crate::export_docker::{DockerImage,
                           Result};

use crate::{env::EnvironmentVariable,
            manifestjson::ManifestJson,
            storage::PersistentStorage,
            topology::Topology};

/// Represents a Kubernetes manifest.
#[derive(Debug, Clone)]
pub struct Manifest {
    /// The identifier of the Habitat package
    pub pkg_ident: PackageIdent,
    /// Name of the Kubernetes resource.
    pub metadata_name: String,
    /// The docker image.
    pub image: String,
    /// The number of desired instances in the service group.
    pub count: u64,
    /// The relationship of a service with peers in the same service group.
    pub service_topology: Topology,
    /// The logical group of services in the service group.
    pub service_group: Option<String>,
    /// The config file content (in base64 encoded format).
    pub config: Option<String>,
    /// The name of the Kubernetes secret that contains the ring key, which encrypts the
    /// communication between Habitat supervisors.
    pub ring_secret_name: Option<String>,

    /// Any binds, as `ServiceBind` instances.
    pub binds: Vec<ServiceBind>,
    /// Persistent storage specification.
    pub persistent_storage: Option<PersistentStorage>,
    /// Environment.
    pub environment: Vec<EnvironmentVariable>,
}

impl Manifest {
    /// Create a Manifest instance from command-line arguments passed as [`clap::ArgMatches`].
    ///
    /// [`clap::ArgMatches`]: https://kbknapp.github.io/clap-rs/clap/struct.ArgMatches.html
    pub fn new_from_cli_matches(_ui: &mut UI,
                                matches: &ArgMatches<'_>,
                                image: Option<DockerImage>)
                                -> Result<Self> {
        let count = matches.value_of("COUNT").unwrap_or("1").parse()?;
        let topology: Topology = matches.value_of("TOPOLOGY")
                                        .unwrap_or("standalone")
                                        .parse()
                                        .unwrap_or_default();
        let group = matches.value_of("GROUP").map(str::to_string);
        let config_file = matches.value_of("CONFIG");
        let ring_secret_name = matches.value_of("RING_SECRET_NAME").map(str::to_string);
        // clap ensures that we do have the mandatory args so unwrap() is fine here
        let pkg_ident_str = matches.value_of("PKG_IDENT_OR_ARTIFACT")
                                   .expect("No package specified");
        let pkg_ident = if Path::new(pkg_ident_str).is_file() {
            // We're going to use the `$pkg_origin/$pkg_name`, fuzzy form of a package
            // identifier to ensure that update strategies will work if desired
            PackageArchive::new(pkg_ident_str).ident()?
        } else {
            PackageIdent::from_str(pkg_ident_str)?
        };

        let version_suffix = match pkg_ident.version {
            Some(ref v) => {
                pkg_ident.release
                         .as_ref()
                         .map(|r| format!("{}-{}", v, r))
                         .unwrap_or_else(|| v.to_string())
            }
            None => "latest".to_owned(),
        };
        let name = matches.value_of("K8S_NAME")
                          .map(str::to_string)
                          .unwrap_or_else(|| format!("{}-{}", pkg_ident.name, version_suffix));

        let formatted_resource_name = Manifest::formatted_metadata_name(&name);

        let image_name = match matches.value_of("IMAGE_NAME") {
            Some(i) => i.to_string(),
            None => {
                let (image_name, tag) = match image {
                    Some(i) => {
                        (i.name().to_owned(),
                         i.tags()
                          .get(0)
                          .cloned()
                          .unwrap_or_else(|| "latest".to_owned()))
                    }
                    None => (format!("{}/{}", pkg_ident.origin, pkg_ident.name), version_suffix),
                };

                format!("{}:{}", image_name, tag)
            }
        };

        let binds = matches
            .values_of("BIND")
            .unwrap_or_default()
            .map(|b| ServiceBind::from_str(b).unwrap()) // unwrap ok as we've validated input
            .collect();

        let persistent_storage = PersistentStorage::from_args(&matches)?;
        let environment = EnvironmentVariable::from_args(&matches)?;

        let config = match config_file {
            None => None,
            Some(name) => {
                let mut contents = String::new();
                File::open(name)?.read_to_string(&mut contents)?;

                Some(base64::encode(&contents))
            }
        };

        Ok(Manifest { pkg_ident,
                      metadata_name: formatted_resource_name,
                      image: image_name,
                      count,
                      service_topology: topology,
                      service_group: group,
                      config,
                      ring_secret_name,
                      binds,
                      persistent_storage,
                      environment })
    }

    /// Generates manifest as a string and writes it to `write`.
    pub fn generate(&mut self, write: &mut dyn Write) -> Result<()> {
        let out: String = ManifestJson::new(&self).into();

        write.write_all(out.as_bytes())?;
        Ok(())
    }

    // Replaces any periods in the metadata name with hyphens
    // To make it a valid Kubernetes resource name
    fn formatted_metadata_name(metadata_name: &str) -> String {
        metadata_name.replace(".", "-")
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_manifest_generation() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             Some(base64::encode(&"port = 4444")),
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTest.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_binds() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec!["name1:service1.group1".parse().unwrap()],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestBinds.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_persistent_storage() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: Some("10Gi:/foo/bar:standard".parse().unwrap()),
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestPersistentStorage.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_environment() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec!["FOO=bar".parse().unwrap(),
                                                        "QUOTES=quo\"te".parse().unwrap(),], };

        let expected = include_str!("../tests/KubernetesManifestTestEnvironment.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_metadata_name() {
        let expected = String::from("sample-node-app-1-1-0-2019050321383");
        let formatted_metadata_name = Manifest::formatted_metadata_name("sample-node-app-1.1.0-2019050321383");

        assert_eq!(formatted_metadata_name, expected);
    }
}
<commit_msg>makes method name clearer<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{fs::File,
          io::prelude::*,
          path::Path,
          str::FromStr};

use crate::{common::ui::UI,
            hcore::{package::{PackageArchive,
                              PackageIdent},
                    service::ServiceBind}};
use base64;
use clap::ArgMatches;

use crate::export_docker::{DockerImage,
                           Result};

use crate::{env::EnvironmentVariable,
            manifestjson::ManifestJson,
            storage::PersistentStorage,
            topology::Topology};

/// Represents a Kubernetes manifest.
#[derive(Debug, Clone)]
pub struct Manifest {
    /// The identifier of the Habitat package
    pub pkg_ident: PackageIdent,
    /// Name of the Kubernetes resource.
    pub metadata_name: String,
    /// The docker image.
    pub image: String,
    /// The number of desired instances in the service group.
    pub count: u64,
    /// The relationship of a service with peers in the same service group.
    pub service_topology: Topology,
    /// The logical group of services in the service group.
    pub service_group: Option<String>,
    /// The config file content (in base64 encoded format).
    pub config: Option<String>,
    /// The name of the Kubernetes secret that contains the ring key, which encrypts the
    /// communication between Habitat supervisors.
    pub ring_secret_name: Option<String>,

    /// Any binds, as `ServiceBind` instances.
    pub binds: Vec<ServiceBind>,
    /// Persistent storage specification.
    pub persistent_storage: Option<PersistentStorage>,
    /// Environment.
    pub environment: Vec<EnvironmentVariable>,
}

impl Manifest {
    /// Create a Manifest instance from command-line arguments passed as [`clap::ArgMatches`].
    ///
    /// [`clap::ArgMatches`]: https://kbknapp.github.io/clap-rs/clap/struct.ArgMatches.html
    pub fn new_from_cli_matches(_ui: &mut UI,
                                matches: &ArgMatches<'_>,
                                image: Option<DockerImage>)
                                -> Result<Self> {
        let count = matches.value_of("COUNT").unwrap_or("1").parse()?;
        let topology: Topology = matches.value_of("TOPOLOGY")
                                        .unwrap_or("standalone")
                                        .parse()
                                        .unwrap_or_default();
        let group = matches.value_of("GROUP").map(str::to_string);
        let config_file = matches.value_of("CONFIG");
        let ring_secret_name = matches.value_of("RING_SECRET_NAME").map(str::to_string);
        // clap ensures that we do have the mandatory args so unwrap() is fine here
        let pkg_ident_str = matches.value_of("PKG_IDENT_OR_ARTIFACT")
                                   .expect("No package specified");
        let pkg_ident = if Path::new(pkg_ident_str).is_file() {
            // We're going to use the `$pkg_origin/$pkg_name`, fuzzy form of a package
            // identifier to ensure that update strategies will work if desired
            PackageArchive::new(pkg_ident_str).ident()?
        } else {
            PackageIdent::from_str(pkg_ident_str)?
        };

        let version_suffix = match pkg_ident.version {
            Some(ref v) => {
                pkg_ident.release
                         .as_ref()
                         .map(|r| format!("{}-{}", v, r))
                         .unwrap_or_else(|| v.to_string())
            }
            None => "latest".to_owned(),
        };
        let name = matches.value_of("K8S_NAME")
                          .map(str::to_string)
                          .unwrap_or_else(|| format!("{}-{}", pkg_ident.name, version_suffix));

        let formatted_resource_name = Manifest::formatted_resource_name(&name);

        let image_name = match matches.value_of("IMAGE_NAME") {
            Some(i) => i.to_string(),
            None => {
                let (image_name, tag) = match image {
                    Some(i) => {
                        (i.name().to_owned(),
                         i.tags()
                          .get(0)
                          .cloned()
                          .unwrap_or_else(|| "latest".to_owned()))
                    }
                    None => (format!("{}/{}", pkg_ident.origin, pkg_ident.name), version_suffix),
                };

                format!("{}:{}", image_name, tag)
            }
        };

        let binds = matches
            .values_of("BIND")
            .unwrap_or_default()
            .map(|b| ServiceBind::from_str(b).unwrap()) // unwrap ok as we've validated input
            .collect();

        let persistent_storage = PersistentStorage::from_args(&matches)?;
        let environment = EnvironmentVariable::from_args(&matches)?;

        let config = match config_file {
            None => None,
            Some(name) => {
                let mut contents = String::new();
                File::open(name)?.read_to_string(&mut contents)?;

                Some(base64::encode(&contents))
            }
        };

        Ok(Manifest { pkg_ident,
                      metadata_name: formatted_resource_name,
                      image: image_name,
                      count,
                      service_topology: topology,
                      service_group: group,
                      config,
                      ring_secret_name,
                      binds,
                      persistent_storage,
                      environment })
    }

    /// Generates manifest as a string and writes it to `write`.
    pub fn generate(&mut self, write: &mut dyn Write) -> Result<()> {
        let out: String = ManifestJson::new(&self).into();

        write.write_all(out.as_bytes())?;
        Ok(())
    }

    // Replaces any periods in the `name with hyphens
    // To make it a valid Kubernetes resource name
    fn formatted_resource_name(resource_name: &str) -> String {
        resource_name.replace(".", "-")
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_manifest_generation() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             Some(base64::encode(&"port = 4444")),
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTest.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_binds() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec!["name1:service1.group1".parse().unwrap()],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestBinds.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_persistent_storage() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: Some("10Gi:/foo/bar:standard".parse().unwrap()),
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestPersistentStorage.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_environment() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec!["FOO=bar".parse().unwrap(),
                                                        "QUOTES=quo\"te".parse().unwrap(),], };

        let expected = include_str!("../tests/KubernetesManifestTestEnvironment.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_resource_name() {
        let expected = String::from("sample-node-app-1-1-0-2019050321383");
        let formatted_resource_name = Manifest::formatted_resource_name("sample-node-app-1.1.0-2019050321383");

        assert_eq!(formatted_resource_name, expected);
    }
}
<|endoftext|>


<commit_before>//! This module contains all render objects used in OrbTk. Render
//! objects are used to define how to draw parts of a widget.

use std::{any::Any, collections::BTreeMap};

use dces::prelude::*;

use crate::{application::ContextProvider, prelude::*, render::RenderContext2D, utils::*};

pub use self::cursor::*;
pub use self::default::*;
pub use self::font_icon::*;
pub use self::image::*;
pub use self::pipeline::*;
pub use self::rectangle::*;
pub use self::text::*;

mod cursor;
mod default;
mod font_icon;
mod image;
mod pipeline;
mod rectangle;
mod text;

/// The `RenderObject` trait defines rendering of 2D objects.
///
/// The trait is acting as a wrapper to the render subcrate. Calls to
/// render objects (self, or its children) will consume the `renderer`
/// methods. The acutual subcrate path is brought into scape with the
/// identifier `render` which resolves to `orbtk_tinyskia` by now.
pub trait RenderObject: Any {
    fn render(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        let mut global_position = Point::default();

        if let Some(parent) = ecm.entity_store().parent[&entity] {
            if let Some(offset) = offsets.get(&parent) {
                global_position = Point::new(offset.0, offset.1);
            }
        }

        if let Ok(visibility) = ecm
            .component_store()
            .get::<Visibility>("visibility", entity)
        {
            if *visibility != Visibility::Visible {
                return;
            }
        } else {
            return;
        }

        render_context.begin_path();
        render_context.set_alpha(
            *ecm.component_store()
                .get::<f32>("opacity", entity)
                .unwrap_or(&1.0),
        );

        // We can safely use unwrap(), because every widget implements the clip property
        let clip = *ecm.component_store().get::<bool>("clip", entity).unwrap();
        if clip {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.save();
                render_context.rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.clip();
            }
        }

        self.render_self(
            &mut Context::new((entity, ecm), &theme, context_provider, render_context),
            &global_position,
        );

        let mut global_pos = (0.0, 0.0);

        if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
            global_pos = (
                global_position.x() + bounds.x(),
                global_position.y() + bounds.y(),
            );
            offsets.insert(entity, global_pos);
        }

        if let Ok(g_pos) = ecm
            .component_store_mut()
            .get_mut::<Point>("position", entity)
        {
            g_pos.set_x(global_pos.0);
            g_pos.set_y(global_pos.1);
        }

        self.render_children(
            render_context,
            entity,
            ecm,
            context_provider,
            &theme,
            offsets,
            debug,
        );

        render_context.close_path();

        if clip {
            render_context.restore();
        }

        // debug mode: render each widget with a border
        if debug {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.begin_path();
                render_context.set_stroke_style(Brush::from("#0033cc"));
                render_context.stroke_rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.close_path();
            }
        }
    }

    fn render_self(&self, _: &mut Context, _: &Point) {}

    fn render_children(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        for index in 0..ecm.entity_store().children[&entity].len() {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(render_object) = context_provider.render_objects.borrow().get(&child) {
                render_object.render(
                    render_context,
                    child,
                    ecm,
                    context_provider,
                    &theme,
                    offsets,
                    debug,
                );
            }
        }
    }
}
<commit_msg>orbtk_core: update render_object documentation<commit_after>//! This module contains all render objects used in OrbTk.
//!
//! Render objects define how to draw associatied entities of a widget
//! to the render buffer.

use std::{any::Any, collections::BTreeMap};

use dces::prelude::*;

use crate::{application::ContextProvider, prelude::*, render::RenderContext2D, utils::*};

pub use self::cursor::*;
pub use self::default::*;
pub use self::font_icon::*;
pub use self::image::*;
pub use self::pipeline::*;
pub use self::rectangle::*;
pub use self::text::*;

mod cursor;
mod default;
mod font_icon;
mod image;
mod pipeline;
mod rectangle;
mod text;

/// The `RenderObject` trait defines rendering of 2D objects.
///
/// The trait is acting as a wrapper to the render subcrate. Calls to
/// render objects (self, or its children) will consume the `renderer`
/// methods. The acutual subcrate path is brought into scape with the
/// identifier `render` which resolves to `orbtk_tinyskia` by now.
pub trait RenderObject: Any {
    fn render(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        let mut global_position = Point::default();

        if let Some(parent) = ecm.entity_store().parent[&entity] {
            if let Some(offset) = offsets.get(&parent) {
                global_position = Point::new(offset.0, offset.1);
            }
        }

        if let Ok(visibility) = ecm
            .component_store()
            .get::<Visibility>("visibility", entity)
        {
            if *visibility != Visibility::Visible {
                return;
            }
        } else {
            return;
        }

        render_context.begin_path();
        render_context.set_alpha(
            *ecm.component_store()
                .get::<f32>("opacity", entity)
                .unwrap_or(&1.0),
        );

        // We can safely use unwrap(), because every widget implements the clip property
        let clip = *ecm.component_store().get::<bool>("clip", entity).unwrap();
        if clip {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.save();
                render_context.rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.clip();
            }
        }

        self.render_self(
            &mut Context::new((entity, ecm), &theme, context_provider, render_context),
            &global_position,
        );

        let mut global_pos = (0.0, 0.0);

        if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
            global_pos = (
                global_position.x() + bounds.x(),
                global_position.y() + bounds.y(),
            );
            offsets.insert(entity, global_pos);
        }

        if let Ok(g_pos) = ecm
            .component_store_mut()
            .get_mut::<Point>("position", entity)
        {
            g_pos.set_x(global_pos.0);
            g_pos.set_y(global_pos.1);
        }

        self.render_children(
            render_context,
            entity,
            ecm,
            context_provider,
            &theme,
            offsets,
            debug,
        );

        render_context.close_path();

        if clip {
            render_context.restore();
        }

        // debug mode: render each widget with a border
        if debug {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.begin_path();
                render_context.set_stroke_style(Brush::from("#0033cc"));
                render_context.stroke_rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.close_path();
            }
        }
    }

    fn render_self(&self, _: &mut Context, _: &Point) {}

    fn render_children(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        for index in 0..ecm.entity_store().children[&entity].len() {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(render_object) = context_provider.render_objects.borrow().get(&child) {
                render_object.render(
                    render_context,
                    child,
                    ecm,
                    context_provider,
                    &theme,
                    offsets,
                    debug,
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#[macro_use]
extern crate criterion;
use criterion::Criterion;

use std::env;
use std::sync::{Arc, Mutex};

extern crate arrow;
extern crate datafusion;

use arrow::datatypes::{DataType, Field, Schema};

use datafusion::datasource::{CsvFile, CsvReadOptions, MemTable};
use datafusion::execution::context::ExecutionContext;

use tokio::runtime::Runtime;

fn query(ctx: Arc<Mutex<ExecutionContext>>, sql: &str) {
    let rt = Runtime::new().unwrap();

    // execute the query
    let df = ctx.lock().unwrap().sql(&sql).unwrap();
    rt.block_on(df.collect()).unwrap();
}

fn create_context() -> Arc<Mutex<ExecutionContext>> {
    // define schema for data source (csv file)
    let schema = Arc::new(Schema::new(vec![
        Field::new("c1", DataType::Utf8, false),
        Field::new("c2", DataType::UInt32, false),
        Field::new("c3", DataType::Int8, false),
        Field::new("c4", DataType::Int16, false),
        Field::new("c5", DataType::Int32, false),
        Field::new("c6", DataType::Int64, false),
        Field::new("c7", DataType::UInt8, false),
        Field::new("c8", DataType::UInt16, false),
        Field::new("c9", DataType::UInt32, false),
        Field::new("c10", DataType::UInt64, false),
        Field::new("c11", DataType::Float32, false),
        Field::new("c12", DataType::Float64, false),
        Field::new("c13", DataType::Utf8, false),
    ]));

    let testdata = env::var("ARROW_TEST_DATA").expect("ARROW_TEST_DATA not defined");

    // create CSV data source
    let csv = CsvFile::try_new(
        &format!("{}/csv/aggregate_test_100.csv", testdata),
        CsvReadOptions::new().schema(&schema),
    )
    .unwrap();

    let rt = Runtime::new().unwrap();

    let ctx_holder: Arc<Mutex<Vec<Arc<Mutex<ExecutionContext>>>>> =
        Arc::new(Mutex::new(vec![]));
    rt.block_on(async {
        let mem_table = MemTable::load(&csv, 16 * 1024).await.unwrap();

        // create local execution context
        let mut ctx = ExecutionContext::new();
        ctx.state.config.concurrency = 1;
        ctx.register_table("aggregate_test_100", Box::new(mem_table));
        ctx_holder.lock().unwrap().push(Arc::new(Mutex::new(ctx)))
    });

    let ctx = ctx_holder.lock().unwrap().get(0).unwrap().clone();
    ctx
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("sort_and_limit_by_int", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY 3
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_by_float", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c12 \
                 FROM aggregate_test_100 \
                 ORDER BY 2
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_lex_by_int", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY 3 DESC, 4 DESC
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_lex_by_string", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY 1, 2
                 LIMIT 10",
            )
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>ARROW-10701: [Rust] Fix sort_limit_query_sql benchmark<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#[macro_use]
extern crate criterion;
use criterion::Criterion;

use std::env;
use std::sync::{Arc, Mutex};

extern crate arrow;
extern crate datafusion;

use arrow::datatypes::{DataType, Field, Schema};

use datafusion::datasource::{CsvFile, CsvReadOptions, MemTable};
use datafusion::execution::context::ExecutionContext;

use tokio::runtime::Runtime;

fn query(ctx: Arc<Mutex<ExecutionContext>>, sql: &str) {
    let rt = Runtime::new().unwrap();

    // execute the query
    let df = ctx.lock().unwrap().sql(&sql).unwrap();
    rt.block_on(df.collect()).unwrap();
}

fn create_context() -> Arc<Mutex<ExecutionContext>> {
    // define schema for data source (csv file)
    let schema = Arc::new(Schema::new(vec![
        Field::new("c1", DataType::Utf8, false),
        Field::new("c2", DataType::UInt32, false),
        Field::new("c3", DataType::Int8, false),
        Field::new("c4", DataType::Int16, false),
        Field::new("c5", DataType::Int32, false),
        Field::new("c6", DataType::Int64, false),
        Field::new("c7", DataType::UInt8, false),
        Field::new("c8", DataType::UInt16, false),
        Field::new("c9", DataType::UInt32, false),
        Field::new("c10", DataType::UInt64, false),
        Field::new("c11", DataType::Float32, false),
        Field::new("c12", DataType::Float64, false),
        Field::new("c13", DataType::Utf8, false),
    ]));

    let testdata = env::var("ARROW_TEST_DATA").expect("ARROW_TEST_DATA not defined");

    // create CSV data source
    let csv = CsvFile::try_new(
        &format!("{}/csv/aggregate_test_100.csv", testdata),
        CsvReadOptions::new().schema(&schema),
    )
    .unwrap();

    let rt = Runtime::new().unwrap();

    let ctx_holder: Arc<Mutex<Vec<Arc<Mutex<ExecutionContext>>>>> =
        Arc::new(Mutex::new(vec![]));
    rt.block_on(async {
        let mem_table = MemTable::load(&csv, 16 * 1024).await.unwrap();

        // create local execution context
        let mut ctx = ExecutionContext::new();
        ctx.state.config.concurrency = 1;
        ctx.register_table("aggregate_test_100", Box::new(mem_table));
        ctx_holder.lock().unwrap().push(Arc::new(Mutex::new(ctx)))
    });

    let ctx = ctx_holder.lock().unwrap().get(0).unwrap().clone();
    ctx
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("sort_and_limit_by_int", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY c6
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_by_float", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c12 \
                 FROM aggregate_test_100 \
                 ORDER BY c13
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_lex_by_int", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY c6 DESC, c10 DESC
                 LIMIT 10",
            )
        })
    });

    c.bench_function("sort_and_limit_lex_by_string", |b| {
        let ctx = create_context();
        b.iter(|| {
            query(
                ctx.clone(),
                "SELECT c1, c13, c6, c10 \
                 FROM aggregate_test_100 \
                 ORDER BY c1, c13
                 LIMIT 10",
            )
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>#![feature(no_core)]
#![no_core]

pub mod foo {
    // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
    // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
    pub struct Bar;
}

// @set root_import_id = - "$.index[*][?(@.inner.span=='foo::Bar')].id"
// @is - "$.index[*][?(@.inner.span=='foo::Bar')].inner.id" $bar_id
// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
pub use foo::Bar;

pub mod baz {
    // @set baz_import_id = - "$.index[*][?(@.inner.span=='crate::foo::Bar')].id"
    // @is - "$.index[*][?(@.inner.span=='crate::foo::Bar')].inner.id" $bar_id
    // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
    pub use crate::foo::Bar;
}
<commit_msg>Rename `span` to `source`<commit_after>#![feature(no_core)]
#![no_core]

pub mod foo {
    // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
    // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
    pub struct Bar;
}

// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id"
// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
pub use foo::Bar;

pub mod baz {
    // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
    // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
    // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
    pub use crate::foo::Bar;
}
<|endoftext|>


<commit_before>pub fn is_leap_year(x:i16) -> bool {
   check_divisibility(x,4) && (
       !check_divisibility(x,100) || check_divisibility(x,400)
       )
}

fn check_divisibility(number:i16,divisor:i16) ->bool{
  number%divisor == 0
}<commit_msg>use xor instead of negating<commit_after>pub fn is_leap_year(x:i16) -> bool {
   check_divisibility(x,4) ^ (
       check_divisibility(x,100) ^ check_divisibility(x,400)
       )
}

fn check_divisibility(number:i16,divisor:i16) ->bool{
  number%divisor == 0
}<|endoftext|>