use query::Operand;
use query::operand::ToOperand;
use dao::ToValue;
use database::Database;
use dao::DaoResult;
use dao::IsDao;
use dao::Dao;
use writer::SqlFrag;
use database::DbError;
use database::BuildMode;
use query::ColumnName;
use query::column_name::ToColumnName;
use query::{TableName, ToTableName};
use query::{Filter, Equality};
use query::Function;
use query::Join;
use query::Order;
use query::Field;
use query::SourceField;
use query::{QuerySource, ToSourceField};
use table::Column;
use query::IsTable;
use std::convert::From;
pub enum Query{
Select(Select),
Insert(Insert),
Update(Update),
Delete(Delete),
}
pub trait IsQuery{
fn build(&mut self, db: &Database) -> SqlFrag;
fn debug_build(&mut self, db: &Database) -> SqlFrag;
}
pub enum Error {
NoTableSpecified(String),
NoColumnSpecified(String),
SqlError(String),
}
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Default)]
#[derive(Clone)]
pub struct Range {
pub limit: Option<usize>,
pub offset: Option<usize>,
}
impl Range {
pub fn new() -> Self {
Range {
limit: None,
offset: None,
}
}
pub fn set_limit(&mut self, limit: usize) {
self.limit = Some(limit);
}
pub fn set_offset(&mut self, offset: usize) {
self.offset = Some(offset);
}
}
#[derive(Debug)]
#[derive(Clone)]
pub struct DeclaredQuery{
pub name: String,
pub fields: Vec<String>,
pub query: Select,
pub is_recursive: bool
}
#[derive(Debug)]
#[derive(Clone)]
pub struct Select {
pub distinct: bool,
pub enumerate_all: bool,
pub declared_query: Vec<DeclaredQuery>,
pub enumerated_fields: Vec<Field>,
pub distinct_on_columns: Vec<String>,
pub from: Vec<SourceField>,
pub joins: Vec<Join>,
pub filters: Vec<Filter>,
pub order_by: Vec<Order>,
pub group_by: Vec<Operand>,
pub having: Vec<Filter>,
pub excluded_columns: Vec<ColumnName>,
pub range: Range,
pub values: Vec<Operand>,
pub enumerated_returns: Vec<Field>,
pub enable_query_stat: bool,
}
impl Select {
pub fn new() -> Self {
Select{
distinct: false,
enumerate_all: false,
declared_query: vec![],
enumerated_fields: vec![],
distinct_on_columns: vec![],
filters: vec![],
joins: vec![],
order_by: vec![],
group_by: vec![],
having: vec![],
excluded_columns: vec![],
range: Range::new(),
from: vec![],
values: vec![],
enumerated_returns: vec![],
enable_query_stat: true,
}
}
pub fn enumerate_all(&mut self) {
self.enumerate_all = true;
}
pub fn all() -> Self {
let mut q = Self::new();
q.column_star();
q
}
fn column_star(&mut self){
self.column("*");
}
fn enumerate<C>(&mut self, column_name: C) where C: Into<ColumnName>{
let operand = Operand::ColumnName(column_name.into());
let field = Field {
operand: operand,
name: None,
};
self.enumerated_fields.push(field);
}
pub fn column(&mut self, column: &str) {
let column_name = ColumnName::from(column);
self.enumerate(column_name);
}
pub fn columns(&mut self, columns: Vec<&str>) {
for c in columns {
self.column(c);
}
}
pub fn exclude_column(&mut self, column: &str) {
let c = ColumnName::from(column);
self.excluded_columns.push(c);
}
pub fn exclude_columns(&mut self, columns: Vec<&str>) {
for c in columns {
self.exclude_column(c);
}
}
pub fn distinct_on_columns(&mut self, columns: &Vec<String>) {
let columns = columns.clone();
for c in columns {
self.distinct_on_columns.push(c);
}
}
pub fn value(&mut self, value: &ToValue) {
let value = value.to_db_type();
self.values.push(Operand::Value(value));
}
pub fn set_limit(&mut self, limit: usize) {
self.range.set_limit(limit);
}
pub fn set_offset(&mut self, offset: usize) {
self.range.set_offset(offset);
}
pub fn get_range(&self) -> Range {
self.range.to_owned()
}
pub fn only_from(&mut self, table: &ToTableName) {
self.enumerate_all = false;
self.enumerate_from_table(&table.to_table_name());
}
pub fn from_query(&mut self, query: Select, alias: &str) {
let sf = SourceField {
source: QuerySource::Query(query),
rename: Some(alias.to_owned()),
};
self.from.push(sf);
}
pub fn from(&mut self, to_source_field: &ToSourceField) {
self.from.append(&mut to_source_field.to_source_field());
}
pub fn table(&mut self, to_source_field: &ToSourceField) {
self.from(to_source_field);
}
pub fn get_from_table(&self) -> Option<TableName> {
for fr in &self.from {
match &fr.source {
&QuerySource::TableName(ref table_name) => {
return Some(table_name.to_owned());
}
_ => {}
}
}
None
}
fn match_fields_indexes(&self, column: &str) -> Vec<usize> {
let mut indexes = vec![];
let mut cnt = 0;
for field in &self.enumerated_fields {
if let Operand::ColumnName(ref column_name) = field.operand {
if column_name.column == column {
indexes.push(cnt);
}
}
cnt += 1;
}
indexes
}
fn rename_fields(&mut self, column: &str) {
let matched_indexes = self.match_fields_indexes(column);
for index in matched_indexes {
let field = self.enumerated_fields.remove(index); let field = field.rename(); self.enumerated_fields.insert(index, field); }
}
pub fn get_involved_tables(&self) -> Vec<TableName> {
let mut tables = vec![];
let from_table = self.get_from_table();
if let Some(from) = from_table {
tables.push(from.clone());
}
for j in &self.joins {
if !tables.contains(&&j.table_name) {
tables.push(j.table_name.clone());
}
}
tables
}
pub fn finalize(&mut self) -> &Self {
let involved_models = self.get_involved_tables();
if involved_models.len() > 1 {
if self.enumerate_all {
self.enumerate_involved_tables_columns(&involved_models);
}
self.rename_conflicting_columns(); }
let excluded_columns = &self.excluded_columns.clone();
for i in excluded_columns {
self.remove_from_enumerated(&i);
}
if self.excluded_columns.is_empty() && self.enumerated_fields.is_empty() {
self.column_star();
}
self
}
fn enumerate_involved_tables_columns(&mut self, involved_models: &Vec<TableName>) {
for m in involved_models {
for c in &m.columns {
self.enumerate(c.clone());
}
}
}
pub fn enumerate_from_table(&mut self, table: &TableName) {
for c in &table.columns {
self.enumerate(c.clone());
}
}
fn get_renamed_fields(&self) -> Vec<&Field> {
let mut renamed = vec![];
for field in &self.enumerated_fields {
if field.name.is_some() {
renamed.push(field);
}
}
renamed
}
pub fn get_renamed_columns(&self) -> Vec<(ColumnName, String)> {
let mut renamed_columns = vec![];
let renamed_fields = self.get_renamed_fields();
for field in &renamed_fields {
if let Operand::ColumnName(ref column_name) = field.operand {
if let Some(ref rename) = field.name {
renamed_columns.push((column_name.clone(), rename.to_owned()));
}
}
}
renamed_columns
}
fn get_conflicting_columns(&self) -> Vec<String> {
let mut conflicts = vec![];
let enumerated_columns = self.get_enumerated_columns();
for c in &enumerated_columns {
for d in &enumerated_columns {
if c != d && c.is_conflicted(d) {
conflicts.push(c.column.to_owned());
}
}
}
conflicts
}
fn rename_conflicting_columns(&mut self) {
let conflicts = self.get_conflicting_columns();
for c in conflicts {
self.rename_fields(&c);
}
}
fn index_of_field(&self, column: &ColumnName) -> Option<usize> {
let mut cnt = 0;
for field in &self.enumerated_fields {
if let Operand::ColumnName(ref column_name) = field.operand {
if column_name == column {
return Some(cnt);
}
}
cnt += 1;
}
None
}
fn remove_from_enumerated(&mut self, column_name: &ColumnName) {
let index = self.index_of_field(column_name);
if let Some(idx) = index {
self.enumerated_fields.remove(idx);
}
}
pub fn get_enumerated_columns(&self) -> Vec<&ColumnName> {
let mut columns = vec![];
for field in &self.enumerated_fields {
if let Operand::ColumnName(ref column_name) = field.operand {
columns.push(column_name);
}
}
columns
}
pub fn add_filter(&mut self, filter: &Filter) {
self.filters.push(filter.clone());
}
pub fn add_filters(&mut self, filters: &Vec<Filter>) {
self.filters.extend_from_slice(filters)
}
pub fn filter_eq(&mut self, column: &str, value: &ToValue) {
self.add_filter(&Filter::new(column, Equality::EQ, value));
}
pub fn filter_lt(&mut self, column: &str, value: &ToValue) {
self.add_filter(&Filter::new(column, Equality::LT, value));
}
pub fn filter_lte(&mut self, column: &str, value: &ToValue) {
self.add_filter(&Filter::new(column, Equality::LTE, value));
}
pub fn filter_gt(&mut self, column: &str, value: &ToValue) {
self.add_filter(&Filter::new(column, Equality::GT, value));
}
pub fn filter_gte(&mut self, column: &str, value: &ToValue) {
self.add_filter(&Filter::new(column, Equality::GTE, value));
}
pub fn return_all(&mut self) {
self.enumerate_column_as_return("*");
}
pub fn returns(&mut self, columns: Vec<&str>) {
for c in columns {
self.enumerate_column_as_return(c);
}
}
pub fn enumerate_column_as_return(&mut self, column: &str) {
let column_name = ColumnName::from(column);
let operand = Operand::ColumnName(column_name);
let field = Field {
operand: operand,
name: None,
};
self.enumerated_returns.push(field);
}
pub fn retrieve(&mut self, db: &Database) -> Result<DaoResult, DbError> {
self.finalize();
db.execute_with_return(self)
}
pub fn retrieve_one(&mut self, db: &Database) -> Result<Option<Dao>, DbError> {
self.finalize();
db.execute_with_one_return(self)
}
pub fn collect<T: IsDao + IsTable>(&mut self, db: &Database) -> Result<Vec<T>, DbError> {
let result = try!(self.retrieve(db));
Ok(result.cast())
}
pub fn collect_one<T: IsDao + IsTable>(&mut self, db: &Database) -> Result<T, DbError> {
let result = try!(self.retrieve(db));
match result.cast_one() {
Some(res) => Ok(res),
None => Err(DbError::new("No entry to collect found.")),
}
}
}
impl IsQuery for Select{
fn build(&mut self, db: &Database) -> SqlFrag{
self.finalize();
db.build_select(self, &BuildMode::Standard)
}
fn debug_build(&mut self, db: &Database) -> SqlFrag{
self.finalize();
db.build_select(self, &BuildMode::Debug)
}
}
pub enum Data{
Values(Vec<Operand>),
Query(Select),
}
pub struct Insert{
pub into: TableName,
pub columns: Vec<ColumnName>,
pub data: Data,
pub return_columns: Vec<ColumnName>
}
impl Insert{
pub fn into(table: &ToTableName) -> Self{
Insert{
into: table.to_table_name(),
columns: vec![],
data: Data::Values(vec![]),
return_columns: vec![]
}
}
pub fn columns(&mut self, columns: Vec<&str>){
for c in columns{
self.column(c);
}
}
pub fn column(&mut self, column: &str){
self.columns.push(column.to_column_name())
}
pub fn values(&mut self, operands: Vec<&ToOperand>){
for op in operands{
self.value(op);
}
}
pub fn value(&mut self, operand: &ToOperand){
match self.data{
Data::Values(ref mut values) => {
(*values).push(operand.to_operand());
},
Data::Query(_) => panic!("can not add value to query")
}
}
pub fn return_columns(&mut self, columns: Vec<&str>){
self.return_columns.clear();
for c in columns{
self.return_column(c);
}
}
fn return_column(&mut self, column: &str){
self.return_columns.push(column.to_column_name());
}
pub fn return_all(&mut self){
self.return_columns(vec!["*"]);
}
pub fn debug_build(&mut self, db: &Database) -> SqlFrag {
db.build_insert(&self, &BuildMode::Debug)
}
pub fn insert<D: IsDao>(&mut self, db: &Database) -> Result<D, DbError>{
let result = db.insert(self);
match result{
Ok(res) => Ok(D::from_dao(&res)),
Err(e) => Err(e),
}
}
pub fn set(&mut self, column: &str, value: &ToValue) {
self.column(&column);
self.value(&Operand::Value(value.to_db_type()));
}
}
pub struct Update{
pub table: TableName,
pub columns: Vec<ColumnName>,
pub values: Vec<Operand>,
pub filters: Vec<Filter>,
pub return_columns: Vec<ColumnName>
}
impl Update{
pub fn table(table: &ToTableName) -> Self{
Update{
table: table.to_table_name(),
columns: vec![],
values: vec![],
filters: vec![],
return_columns: vec![],
}
}
pub fn add_filter(&mut self, filter: &Filter){
self.filters.push(filter.clone());
}
pub fn add_filters(&mut self, filters: &Vec<Filter>){
self.filters.extend_from_slice(filters);
}
pub fn columns(&mut self, columns: &Vec<ColumnName>){
self.columns = columns.to_owned();
}
pub fn value(&mut self, operand: &ToOperand){
self.values.push(operand.to_operand());
}
pub fn return_all(&mut self){
self.return_columns = vec![ColumnName::from("*")];
}
pub fn column(&mut self, column: &ToColumnName){
self.columns.push(column.to_column_name());
}
pub fn set(&mut self, column: &str, value: &ToValue) {
self.column(&column);
self.value(&Operand::Value(value.to_db_type()));
}
pub fn update<D: IsDao>(&mut self, db: &Database) -> Result<D, DbError>{
let result = db.update(self);
match result{
Ok(res) => Ok(D::from_dao(&res)),
Err(e) => Err(e),
}
}
}
pub struct Delete{
pub from_table: TableName,
pub filters: Vec<Filter>
}
impl Delete{
pub fn from(table: &ToTableName) -> Self{
Delete{
from_table: table.to_table_name(),
filters: vec![]
}
}
pub fn add_filter(&mut self, filter: &Filter){
self.filters.push(filter.clone())
}
pub fn add_filters(&mut self, filter: Vec<Filter>){
self.filters.extend(filter)
}
pub fn execute(&self, db: &Database) -> Result<usize, DbError> {
db.delete(self)
}
}
impl IsQuery for Delete{
fn build(&mut self, db: &Database) -> SqlFrag{
db.build_delete(self, &BuildMode::Standard)
}
fn debug_build(&mut self, db: &Database) -> SqlFrag {
db.build_delete(self, &BuildMode::Debug)
}
}
pub struct CreateTable{
pub table: TableName,
pub column: Vec<Column>
}
pub struct DropTable{
pub table: TableName,
pub force: bool,
}
pub struct CreateSchema{
pub schema: String,
}
pub struct DropSchema{
pub schema: String,
pub force: bool
}
pub struct CreateFunction{
pub function: Function
}
pub struct AlterTable{
pub table: String,
}
pub enum TableOrColumn{
Table(TableName),
Column(ColumnName)
}
pub struct Comment{
pub target: TableOrColumn,
pub comment: String
}
pub struct CopyTable{
pub table: String,
pub dao: Vec<Operand>
}
pub struct CreateExtension{
pub extension: String,
}