@@ -10,12 +10,47 @@ use serde::{Deserialize, Serialize};
1010use super :: * ;
1111use crate :: catalog:: { ColumnId , SchemaId , TableId } ;
1212
13+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Serialize , Deserialize ) ]
14+ pub enum VectorDistance {
15+ Cosine ,
16+ L2 ,
17+ NegativeDotProduct ,
18+ }
19+
20+ impl FromStr for VectorDistance {
21+ type Err = String ;
22+
23+ fn from_str ( s : & str ) -> std:: result:: Result < Self , Self :: Err > {
24+ match s {
25+ "cosine" => Ok ( VectorDistance :: Cosine ) ,
26+ "<=>" => Ok ( VectorDistance :: Cosine ) ,
27+ "l2" => Ok ( VectorDistance :: L2 ) ,
28+ "<->" => Ok ( VectorDistance :: L2 ) ,
29+ "dotproduct" => Ok ( VectorDistance :: NegativeDotProduct ) ,
30+ "<#>" => Ok ( VectorDistance :: NegativeDotProduct ) ,
31+ _ => Err ( format ! ( "invalid vector distance: {}" , s) ) ,
32+ }
33+ }
34+ }
35+
36+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Serialize , Deserialize ) ]
37+ pub enum IndexType {
38+ Hnsw ,
39+ IvfFlat {
40+ distance : VectorDistance ,
41+ nlists : usize ,
42+ nprobe : usize ,
43+ } ,
44+ Btree ,
45+ }
46+
1347#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Serialize , Deserialize ) ]
1448pub struct CreateIndex {
1549 pub schema_id : SchemaId ,
1650 pub index_name : String ,
1751 pub table_id : TableId ,
1852 pub columns : Vec < ColumnId > ,
53+ pub index_type : IndexType ,
1954}
2055
2156impl fmt:: Display for CreateIndex {
@@ -48,6 +83,79 @@ impl FromStr for Box<CreateIndex> {
4883}
4984
5085impl Binder {
86+ fn parse_index_type ( & self , using : Option < Ident > , with : Vec < Expr > ) -> Result < IndexType > {
87+ let Some ( using) = using else {
88+ return Err ( ErrorKind :: InvalidIndex ( "using clause is required" . to_string ( ) ) . into ( ) ) ;
89+ } ;
90+ match using. to_string ( ) . to_lowercase ( ) . as_str ( ) {
91+ "hnsw" => Ok ( IndexType :: Hnsw ) ,
92+ "ivfflat" => {
93+ let mut distfn = None ;
94+ let mut nlists = None ;
95+ let mut nprobe = None ;
96+ for expr in with {
97+ let Expr :: BinaryOp { left, op, right } = expr else {
98+ return Err (
99+ ErrorKind :: InvalidIndex ( "invalid with clause" . to_string ( ) ) . into ( )
100+ ) ;
101+ } ;
102+ if op != BinaryOperator :: Eq {
103+ return Err (
104+ ErrorKind :: InvalidIndex ( "invalid with clause" . to_string ( ) ) . into ( )
105+ ) ;
106+ }
107+ let Expr :: Identifier ( Ident { value : key, .. } ) = * left else {
108+ return Err (
109+ ErrorKind :: InvalidIndex ( "invalid with clause" . to_string ( ) ) . into ( )
110+ ) ;
111+ } ;
112+ let key = key. to_lowercase ( ) ;
113+ let Expr :: Value ( v) = * right else {
114+ return Err (
115+ ErrorKind :: InvalidIndex ( "invalid with clause" . to_string ( ) ) . into ( )
116+ ) ;
117+ } ;
118+ let v: DataValue = v. into ( ) ;
119+ match key. as_str ( ) {
120+ "distfn" => {
121+ let v = v. as_str ( ) ;
122+ distfn = Some ( v. to_lowercase ( ) ) ;
123+ }
124+ "nlists" => {
125+ let Some ( v) = v. as_usize ( ) . unwrap ( ) else {
126+ return Err ( ErrorKind :: InvalidIndex (
127+ "invalid with clause" . to_string ( ) ,
128+ )
129+ . into ( ) ) ;
130+ } ;
131+ nlists = Some ( v) ;
132+ }
133+ "nprobe" => {
134+ let Some ( v) = v. as_usize ( ) . unwrap ( ) else {
135+ return Err ( ErrorKind :: InvalidIndex (
136+ "invalid with clause" . to_string ( ) ,
137+ )
138+ . into ( ) ) ;
139+ } ;
140+ nprobe = Some ( v) ;
141+ }
142+ _ => {
143+ return Err (
144+ ErrorKind :: InvalidIndex ( "invalid with clause" . to_string ( ) ) . into ( )
145+ ) ;
146+ }
147+ }
148+ }
149+ Ok ( IndexType :: IvfFlat {
150+ distance : VectorDistance :: from_str ( distfn. unwrap ( ) . as_str ( ) ) . unwrap ( ) ,
151+ nlists : nlists. unwrap ( ) ,
152+ nprobe : nprobe. unwrap ( ) ,
153+ } )
154+ }
155+ _ => Err ( ErrorKind :: InvalidIndex ( "invalid index type" . to_string ( ) ) . into ( ) ) ,
156+ }
157+ }
158+
51159 pub ( super ) fn bind_create_index ( & mut self , stat : crate :: parser:: CreateIndex ) -> Result {
52160 let Some ( ref name) = stat. name else {
53161 return Err (
@@ -57,6 +165,8 @@ impl Binder {
57165 let crate :: parser:: CreateIndex {
58166 table_name,
59167 columns,
168+ using,
169+ with,
60170 ..
61171 } = stat;
62172 let index_name = lower_case_name ( name) ;
@@ -94,6 +204,7 @@ impl Binder {
94204 index_name : index_name. into ( ) ,
95205 table_id : table. id ( ) ,
96206 columns : column_ids,
207+ index_type : self . parse_index_type ( using, with) ?,
97208 } ) ) ) ;
98209 Ok ( create)
99210 }
0 commit comments