1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

use super::{ColumnData, TableTemplate};
use super::column::{Column, IndexKind};
use crate::Result;

use tokio_postgres::types::ToSql;
use tokio_postgres::row::Row;

pub fn data_into_sql_params<'a>(data: &'a [ColumnData]) -> Vec<&'a (dyn ToSql + Sync)> {
	data.iter().map(|d| d as &(dyn ToSql + Sync)).collect()
}

pub fn rows_into_data<T>(rows: Vec<Row>) -> Result<Vec<T>>
where T: TableTemplate {
	let mut new_rows = Vec::with_capacity(rows.len());

	for row in rows {
		let mut data: Vec<ColumnData> = Vec::with_capacity(row.len());
		for i in 0..row.len() {
			data.push(row.try_get(i)?);
		}
		new_rows.push(T::from_data(data)?);
	}

	Ok(new_rows)
}

pub fn info_data_to_sql(name: &str, data: &[Column]) -> String {

	let mut primary_indexes = vec![];
	let mut normal_indexes = vec![];
	let mut unique_indexes = vec![]; // (name, vec![])

	let mut cols_sql = vec![];

	for col in data {
		let kind = col.kind.to_string(col.name);
		let not_null = col.kind.not_null_str();
		let quoted_name = quote(col.name);

		cols_sql.push(format!("{} {} {}", quoted_name, kind, not_null));

		match col.index {
			IndexKind::Primary => primary_indexes.push(quoted_name),
			IndexKind::Unique => unique_indexes.push((col.name, vec![quoted_name])),
			IndexKind::NamedUnique(n) => 'match_arm: loop {
				for ind in unique_indexes.iter_mut() {
					if ind.0 == n {
						ind.1.push(quoted_name);
						break 'match_arm;
					}
				}
				unique_indexes.push((n, vec![quoted_name]));
				break;
			},
			IndexKind::Index => normal_indexes.push(col.name),
			IndexKind::None => {}
		}
	}

	cols_sql.push(format!("PRIMARY KEY ({})", primary_indexes.join(", ")));
	for ind in unique_indexes {
		cols_sql.push(format!("UNIQUE ({})", ind.1.join(", ")));
	}

	let mut sqls = vec![
		format!("CREATE TABLE IF NOT EXISTS \"{}\" ({})", name, cols_sql.join(", "))
	];

	for ind in normal_indexes {
		let index_name = format!("{}_{}_nidx", name, ind);
		sqls.push(format!("CREATE INDEX IF NOT EXISTS {} ON \"{}\" (\"{}\")", index_name, name, ind));
	}

	sqls.join("; ")
}

pub fn quote(s: &str) -> String {
	format!("\"{}\"", s)
}

// maybe this is not important because table name can't be -
/*pub fn sanitize_index_name(name: String) -> String {
	name
		.replace("-", "_")
		.replace(" ", "_")
}*/