Skip to content

Commit 92f7cfc

Browse files
committed
Support UNIQUE NULLS DISTINCT index in CREATE TABLE
1 parent f897a1a commit 92f7cfc

File tree

13 files changed

+633
-288
lines changed

13 files changed

+633
-288
lines changed

src/protos/generated/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![allow(clippy::all)]
22

3-
#[rustfmt::skip]
4-
mod seamdb;
5-
pub use self::seamdb::*;
6-
73
#[rustfmt::skip]
84
mod sql;
95
pub use self::sql::*;
6+
7+
#[rustfmt::skip]
8+
mod seamdb;
9+
pub use self::seamdb::*;

src/protos/generated/sql.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ pub struct StoringFloat64 {
110110
#[prost(double, tag = "1")]
111111
pub value: f64,
112112
}
113+
#[allow(clippy::derive_partial_eq_without_eq)]
114+
#[derive(Clone, PartialEq, ::prost::Message)]
115+
pub struct Column {
116+
#[prost(uint32, tag = "1")]
117+
pub id: u32,
118+
#[prost(message, optional, tag = "2")]
119+
pub value: ::core::option::Option<ColumnValue>,
120+
}
113121
#[derive(Eq, Hash, PartialOrd)]
114122
#[allow(clippy::derive_partial_eq_without_eq)]
115123
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -158,10 +166,12 @@ pub struct IndexDescriptor {
158166
pub id: u32,
159167
#[prost(string, tag = "2")]
160168
pub name: ::prost::alloc::string::String,
161-
#[prost(bool, tag = "3")]
162-
pub unique: bool,
169+
#[prost(enumeration = "!IndexKind", tag = "3")]
170+
pub kind: IndexKind,
171+
/// Declared index columns.
163172
#[prost(uint32, repeated, tag = "4")]
164173
pub column_ids: ::prost::alloc::vec::Vec<u32>,
174+
/// Declared storing columns,
165175
#[prost(uint32, repeated, tag = "5")]
166176
pub storing_column_ids: ::prost::alloc::vec::Vec<u32>,
167177
}
@@ -209,3 +219,35 @@ impl ColumnTypeKind {
209219
}
210220
}
211221
}
222+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
223+
#[repr(i32)]
224+
pub enum IndexKind {
225+
NotUnique = 0,
226+
UniqueNullsDistinct = 1,
227+
UniqueNullsNotDistinct = 2,
228+
PrimaryKey = 3,
229+
}
230+
impl IndexKind {
231+
/// String value of the enum field names used in the ProtoBuf definition.
232+
///
233+
/// The values are not transformed in any way and thus are considered stable
234+
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
235+
pub fn as_str_name(&self) -> &'static str {
236+
match self {
237+
IndexKind::NotUnique => "NotUnique",
238+
IndexKind::UniqueNullsDistinct => "UNIQUE_NULLS_DISTINCT",
239+
IndexKind::UniqueNullsNotDistinct => "UNIQUE_NULLS_NOT_DISTINCT",
240+
IndexKind::PrimaryKey => "PRIMARY_KEY",
241+
}
242+
}
243+
/// Creates an enum from field names used in the ProtoBuf definition.
244+
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
245+
match value {
246+
"NotUnique" => Some(Self::NotUnique),
247+
"UNIQUE_NULLS_DISTINCT" => Some(Self::UniqueNullsDistinct),
248+
"UNIQUE_NULLS_NOT_DISTINCT" => Some(Self::UniqueNullsNotDistinct),
249+
"PRIMARY_KEY" => Some(Self::PrimaryKey),
250+
_ => None,
251+
}
252+
}
253+
}

src/protos/protos/sql.proto

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ message StoringFloat64 {
100100
double value = 1;
101101
}
102102

103+
message Column {
104+
uint32 id = 1;
105+
ColumnValue value = 2;
106+
}
107+
103108
message ColumnValue {
104109
oneof value {
105110
bool boolean = 1;
@@ -123,10 +128,21 @@ message ColumnDescriptor {
123128
ColumnValue default_value = 7;
124129
}
125130

131+
enum IndexKind {
132+
NotUnique = 0;
133+
UNIQUE_NULLS_DISTINCT = 1;
134+
UNIQUE_NULLS_NOT_DISTINCT = 2;
135+
PRIMARY_KEY = 3;
136+
}
137+
126138
message IndexDescriptor {
127139
uint32 id = 1;
128140
string name = 2;
129-
bool unique = 3;
141+
IndexKind kind = 3;
142+
143+
// Declared index columns.
130144
repeated uint32 column_ids = 4;
145+
146+
// Declared storing columns,
131147
repeated uint32 storing_column_ids = 5;
132148
}

src/protos/sql.rs

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,38 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use std::fmt::{self, Display, Formatter};
1516
use std::hash::{Hash, Hasher};
1617

1718
use bytes::{Buf, BufMut};
1819
use prost::Message;
1920

2021
use crate::protos::{
22+
Column,
2123
ColumnDescriptor,
2224
ColumnTypeKind,
2325
ColumnValue,
2426
DatabaseDescriptor,
2527
DescriptorMeta,
2628
IndexDescriptor,
29+
IndexKind,
2730
SchemaDescriptor,
2831
StoringFloat32,
2932
StoringFloat64,
3033
TableDescriptor,
3134
};
3235

36+
impl Display for IndexKind {
37+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
38+
match self {
39+
Self::NotUnique => f.write_str("index"),
40+
Self::UniqueNullsDistinct => f.write_str("unique nulls distinct"),
41+
Self::UniqueNullsNotDistinct => f.write_str("unique nulls not distinct"),
42+
Self::PrimaryKey => f.write_str("primary index"),
43+
}
44+
}
45+
}
46+
3347
pub trait NamespaceDescriptor {
3448
fn kind() -> &'static str;
3549

@@ -113,7 +127,7 @@ impl TableDescriptor {
113127

114128
pub fn primary_index(&self) -> &IndexDescriptor {
115129
for index in self.indices.iter() {
116-
if index.id == 1 {
130+
if index.is_primary() {
117131
return index;
118132
}
119133
}
@@ -134,6 +148,10 @@ impl TableDescriptor {
134148
key
135149
}
136150

151+
pub fn column_indices(&self, columns: impl Iterator<Item = u32>) -> Vec<usize> {
152+
columns.map(|id| self.columns.iter().position(|column| column.id == id).unwrap()).collect()
153+
}
154+
137155
pub fn find_column(&self, name: &str) -> Option<&ColumnDescriptor> {
138156
self.columns.iter().find(|column| column.name == name)
139157
}
@@ -142,22 +160,30 @@ impl TableDescriptor {
142160
self.columns.iter().find(|column| column.id == id)
143161
}
144162

145-
pub fn decode_storing_columns(&self, index: &IndexDescriptor, mut bytes: &[u8]) -> Vec<Option<ColumnValue>> {
146-
let mut values = Vec::with_capacity(index.storing_column_ids.len());
163+
pub fn decode_key_columns_to(&self, index: &IndexDescriptor, mut bytes: &[u8], row: &mut Vec<Column>) {
164+
let prefix = self.index_prefix(index);
165+
bytes.advance(prefix.len());
147166
loop {
148167
let id = bytes.get_u32();
149168
if id == 0 {
150169
break;
151170
}
152-
let value = ColumnValue::decode(&mut bytes);
153-
let i = values.len();
154-
if i >= index.storing_column_ids.len() {
155-
values.push(value);
156-
panic!("index key has more columns than descriptor {index:?}: {values:?}")
171+
let value = ColumnValue::decode_from_key(&mut bytes);
172+
let column = self.column(id).unwrap();
173+
if value.type_kind() != column.type_kind {
174+
panic!("index {index:?} column {column:?} mismatch column value {value:?}")
157175
}
158-
if id != index.storing_column_ids[i] {
159-
panic!("index descriptor {index:?} does not have column id {id}")
176+
row.push(Column::new(id, Some(value)));
177+
}
178+
}
179+
180+
pub fn decode_value_columns_to(&self, index: &IndexDescriptor, mut bytes: &[u8], row: &mut Vec<Column>) {
181+
loop {
182+
let id = bytes.get_u32();
183+
if id == 0 {
184+
break;
160185
}
186+
let value = ColumnValue::decode(&mut bytes);
161187
let column = self.column(id).unwrap();
162188
match value.as_ref().map(|v| v.type_kind()) {
163189
None => {
@@ -171,48 +197,26 @@ impl TableDescriptor {
171197
}
172198
},
173199
}
174-
values.push(value);
175-
}
176-
if values.len() != index.storing_column_ids.len() {
177-
panic!("index {index:?} get mismatching values {values:?}")
200+
row.push(Column::new(id, value));
178201
}
179-
values
180202
}
181203

182-
pub fn decode_index_key(&self, index: &IndexDescriptor, mut bytes: &[u8]) -> Vec<ColumnValue> {
183-
let prefix = self.index_prefix(index);
184-
bytes.advance(prefix.len());
185-
let mut values = Vec::with_capacity(index.column_ids.len());
186-
loop {
187-
let id = bytes.get_u32();
188-
if id == 0 {
189-
break;
190-
}
191-
let value = ColumnValue::decode_from_key(&mut bytes);
192-
let i = values.len();
193-
if i >= index.column_ids.len() {
194-
values.push(value);
195-
panic!("index key has more columns than descriptor {index:?}: {values:?}")
196-
}
197-
if id != index.column_ids[i] {
198-
panic!("index descriptor {index:?} does not have column id {id}")
199-
}
200-
let column = self.column(id).unwrap();
201-
if value.type_kind() != column.type_kind {
202-
panic!("index {index:?} column {column:?} mismatch column value {value:?}")
203-
}
204-
values.push(value);
205-
}
206-
if values.len() != index.column_ids.len() {
207-
panic!("index {index:?} get mismatching keys {values:?}")
208-
}
204+
pub fn decode_key_columns(&self, index: &IndexDescriptor, bytes: &[u8]) -> Vec<Column> {
205+
let mut keys = Vec::with_capacity(index.column_ids.len());
206+
self.decode_key_columns_to(index, bytes, &mut keys);
207+
keys
208+
}
209+
210+
pub fn decode_value_columns(&self, index: &IndexDescriptor, bytes: &[u8]) -> Vec<Column> {
211+
let mut values = Vec::with_capacity(index.storing_column_ids.len());
212+
self.decode_value_columns_to(index, bytes, &mut values);
209213
values
210214
}
211215
}
212216

213217
impl IndexDescriptor {
214218
pub fn is_primary(&self) -> bool {
215-
self.id == 1
219+
self.kind == IndexKind::PrimaryKey
216220
}
217221

218222
pub fn sole_column(&self) -> Option<u32> {
@@ -223,6 +227,44 @@ impl IndexDescriptor {
223227
}
224228
}
225229

230+
impl Column {
231+
pub fn new(id: u32, value: Option<ColumnValue>) -> Self {
232+
Self { id, value }
233+
}
234+
235+
pub fn with_value(id: u32, value: ColumnValue) -> Self {
236+
Self { id, value: Some(value) }
237+
}
238+
239+
pub fn new_null(id: u32) -> Self {
240+
Self { id, value: None }
241+
}
242+
243+
pub fn is_null(&self) -> bool {
244+
self.value.is_none()
245+
}
246+
247+
pub fn encode_as_key(&self, buf: &mut impl BufMut) {
248+
buf.put_u32(self.id);
249+
match self.value.as_ref() {
250+
None => {
251+
buf.put_i32(-1);
252+
},
253+
Some(value) => value.encode_as_key(buf),
254+
}
255+
}
256+
257+
pub fn encode_as_value(&self, buf: &mut impl BufMut) {
258+
buf.put_u32(self.id);
259+
match self.value.as_ref() {
260+
None => {
261+
buf.put_i32(-1);
262+
},
263+
Some(value) => value.encode(buf),
264+
}
265+
}
266+
}
267+
226268
impl ColumnValue {
227269
pub fn minimum_of(type_kind: ColumnTypeKind) -> Self {
228270
match type_kind {

0 commit comments

Comments
 (0)