Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the PostgreSQL hstore extension #797

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/backend/mysql/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/backend/postgres/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions src/backend/sqlite/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
45 changes: 45 additions & 0 deletions src/extension/postgres/hstore.rs
Original file line number Diff line number Diff line change
@@ -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 ('[email protected]', '@super_secret_1', 'department=>IT');
/// -- additional_data contains department => IT.
/// update users set additional_data['equipment_issued'] = null where username = '[email protected]';
/// -- 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<PgHstore> for String {
fn from(l: PgHstore) -> Self {
l.to_string()
}
}
2 changes: 2 additions & 0 deletions src/extension/postgres/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub use expr::*;
pub use extension::*;
pub use func::*;
pub use hstore::*;
pub use ltree::*;
pub use types::*;

Expand All @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions src/table/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -98,6 +99,7 @@ pub enum ColumnType {
Inet,
MacAddr,
LTree,
Hstore,
}

/// Length for var-char/binary; default to 255
Expand Down Expand Up @@ -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
///
/// ```
Expand Down