diff --git a/src/backend/mysql/table.rs b/src/backend/mysql/table.rs index 562ec36b..8c407464 100644 --- a/src/backend/mysql/table.rs +++ b/src/backend/mysql/table.rs @@ -94,6 +94,7 @@ impl TableBuilder for MysqlQueryBuilder { ColumnType::Inet => unimplemented!("Inet is not available in MySQL."), ColumnType::MacAddr => unimplemented!("MacAddr is not available in MySQL."), ColumnType::LTree => unimplemented!("LTree is not available in MySQL."), + ColumnType::Hstore => unimplemented!("Hstore is not available in MySQL."), } ) .unwrap(); diff --git a/src/backend/postgres/table.rs b/src/backend/postgres/table.rs index a022d1d7..62fe3b6b 100644 --- a/src/backend/postgres/table.rs +++ b/src/backend/postgres/table.rs @@ -78,6 +78,7 @@ impl TableBuilder for PostgresQueryBuilder { ColumnType::MacAddr => "macaddr".into(), ColumnType::Year => unimplemented!("Year is not available in Postgres."), ColumnType::LTree => "ltree".into(), + ColumnType::Hstore => "hstore".into(), } ) .unwrap() diff --git a/src/backend/sqlite/table.rs b/src/backend/sqlite/table.rs index 834b0727..29767a57 100644 --- a/src/backend/sqlite/table.rs +++ b/src/backend/sqlite/table.rs @@ -191,6 +191,7 @@ impl SqliteQueryBuilder { ColumnType::Bit(_) => unimplemented!("Bit is not available in Sqlite."), ColumnType::VarBit(_) => unimplemented!("VarBit is not available in Sqlite."), ColumnType::LTree => unimplemented!("LTree is not available in Sqlite."), + ColumnType::Hstore => unimplemented!("Hstore is not available in Sqlite."), } ) .unwrap() diff --git a/src/extension/postgres/hstore.rs b/src/extension/postgres/hstore.rs new file mode 100644 index 00000000..4105f890 --- /dev/null +++ b/src/extension/postgres/hstore.rs @@ -0,0 +1,45 @@ +use crate::Iden; + +/// PostgreSQL `hstore` extension type. +/// +/// `hstore` provides semi-structured data support by storing key/value pairs in a single column. +/// +/// See [the Postgres manual, Appendix F, Section 18][PG.F.18] +/// +/// [PG.F.18]: https://www.postgresql.org/docs/current/hstore.html +/// +/// ### Note: Requires Postgres 8.3+ +/// The `hstore` extension was first added in PostgreSQL 8.3. +/// +/// # PostgreSQL Reference +/// The following set of SQL statements can be used to create a table with a `hstore` column. +/// +/// ```ignore +/// create table users (username varchar primary key, password varchar, additional_data hstore); +/// create index idx_gist on users using gist (additional_data); -- Sets GIST index support. +/// create index idx_gin on users using gin (additional_data); -- Sets GIN index support. +/// +/// insert into users values ('name.surname@email.com', '@super_secret_1', 'department=>IT'); +/// -- additional_data contains department => IT. +/// update users set additional_data['equipment_issued'] = null where username = 'name.surname@email.com'; +/// -- additional_data now contains equipment_issued => null, department => IT. +/// +/// select * from users; +/// select * from users where additional_data['department'] = 'IT'; +/// select * from users where additional_data->'department' = 'IT'; -- Alternate form. +/// ``` +/// +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct PgHstore; + +impl Iden for PgHstore { + fn unquoted(&self, s: &mut dyn std::fmt::Write) { + write!(s, "hstore").unwrap(); + } +} + +impl From for String { + fn from(l: PgHstore) -> Self { + l.to_string() + } +} diff --git a/src/extension/postgres/mod.rs b/src/extension/postgres/mod.rs index 6dd48041..681e2e84 100644 --- a/src/extension/postgres/mod.rs +++ b/src/extension/postgres/mod.rs @@ -1,6 +1,7 @@ pub use expr::*; pub use extension::*; pub use func::*; +pub use hstore::*; pub use ltree::*; pub use types::*; @@ -9,6 +10,7 @@ use crate::types::BinOper; pub(crate) mod expr; pub(crate) mod extension; pub(crate) mod func; +pub(crate) mod hstore; pub(crate) mod interval; pub(crate) mod ltree; pub(crate) mod types; diff --git a/src/table/column.rs b/src/table/column.rs index eac4ee72..992d593f 100644 --- a/src/table/column.rs +++ b/src/table/column.rs @@ -54,6 +54,7 @@ pub trait IntoColumnDef { /// | Inet | N/A | inet | N/A | /// | MacAddr | N/A | macaddr | N/A | /// | LTree | N/A | ltree | N/A | +/// | Hstore | N/A | hstore | N/A | #[non_exhaustive] #[derive(Debug, Clone)] pub enum ColumnType { @@ -98,6 +99,7 @@ pub enum ColumnType { Inet, MacAddr, LTree, + Hstore, } /// Length for var-char/binary; default to 255 @@ -638,6 +640,37 @@ impl ColumnDef { self } + /// Set column type as `hstore` + /// This is only supported on Postgres. + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// assert_eq!( + /// Table::create() + /// .table(Glyph::Table) + /// .col( + /// ColumnDef::new(Glyph::Id) + /// .integer() + /// .not_null() + /// .auto_increment() + /// .primary_key() + /// ) + /// .col(ColumnDef::new(Glyph::Tokens).hstore()) + /// .to_string(PostgresQueryBuilder), + /// [ + /// r#"CREATE TABLE "glyph" ("#, + /// r#""id" serial NOT NULL PRIMARY KEY,"#, + /// r#""tokens" hstore"#, + /// r#")"#, + /// ] + /// .join(" ") + /// ); + /// ``` + pub fn hstore(&mut self) -> &mut Self { + self.types = Some(ColumnType::Hstore); + self + } + /// Set constraints as SimpleExpr /// /// ```