You've already forked pgvecto.rs
mirror of
https://github.com/tensorchord/pgvecto.rs.git
synced 2025-07-29 08:21:12 +03:00
feat: deny unknown field in options (#184)
* fix: deny unknown options Signed-off-by: usamoi <usamoi@outlook.com> * test: deny unknown options Signed-off-by: usamoi <usamoi@outlook.com> --------- Signed-off-by: usamoi <usamoi@outlook.com>
This commit is contained in:
@ -15,6 +15,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum QuantizationOptions {
|
pub enum QuantizationOptions {
|
||||||
Trivial(TrivialQuantizationOptions),
|
Trivial(TrivialQuantizationOptions),
|
||||||
|
@ -16,6 +16,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ProductQuantizationOptions {
|
pub struct ProductQuantizationOptions {
|
||||||
#[serde(default = "ProductQuantizationOptions::default_sample")]
|
#[serde(default = "ProductQuantizationOptions::default_sample")]
|
||||||
pub sample: u32,
|
pub sample: u32,
|
||||||
@ -40,6 +41,7 @@ impl Default for ProductQuantizationOptions {
|
|||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum ProductQuantizationOptionsRatio {
|
pub enum ProductQuantizationOptionsRatio {
|
||||||
X4 = 1,
|
X4 = 1,
|
||||||
|
@ -11,6 +11,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ScalarQuantizationOptions {}
|
pub struct ScalarQuantizationOptions {}
|
||||||
|
|
||||||
impl Default for ScalarQuantizationOptions {
|
impl Default for ScalarQuantizationOptions {
|
||||||
|
@ -9,6 +9,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct TrivialQuantizationOptions {}
|
pub struct TrivialQuantizationOptions {}
|
||||||
|
|
||||||
impl Default for TrivialQuantizationOptions {
|
impl Default for TrivialQuantizationOptions {
|
||||||
|
@ -3,6 +3,7 @@ use crate::utils::file_wal::FileWal;
|
|||||||
use dashmap::mapref::entry::Entry;
|
use dashmap::mapref::entry::Entry;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ impl Delete {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct Log {
|
struct Log {
|
||||||
key: Pointer,
|
key: Pointer,
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct FlatIndexingOptions {
|
pub struct FlatIndexingOptions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[validate]
|
#[validate]
|
||||||
|
@ -10,6 +10,7 @@ use std::{path::PathBuf, sync::Arc};
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct HnswIndexingOptions {
|
pub struct HnswIndexingOptions {
|
||||||
#[serde(default = "HnswIndexingOptions::default_m")]
|
#[serde(default = "HnswIndexingOptions::default_m")]
|
||||||
#[validate(range(min = 4, max = 128))]
|
#[validate(range(min = 4, max = 128))]
|
||||||
|
@ -11,6 +11,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct IvfIndexingOptions {
|
pub struct IvfIndexingOptions {
|
||||||
#[serde(default = "IvfIndexingOptions::default_least_iterations")]
|
#[serde(default = "IvfIndexingOptions::default_least_iterations")]
|
||||||
#[validate(range(min = 1, max = 1_000_000))]
|
#[validate(range(min = 1, max = 1_000_000))]
|
||||||
|
@ -16,6 +16,7 @@ use std::sync::Arc;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum IndexingOptions {
|
pub enum IndexingOptions {
|
||||||
Flat(FlatIndexingOptions),
|
Flat(FlatIndexingOptions),
|
||||||
|
@ -37,6 +37,7 @@ use validator::Validate;
|
|||||||
pub struct OutdatedError(#[from] pub Option<GrowingSegmentInsertError>);
|
pub struct OutdatedError(#[from] pub Option<GrowingSegmentInsertError>);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct VectorOptions {
|
pub struct VectorOptions {
|
||||||
#[validate(range(min = 1, max = 65535))]
|
#[validate(range(min = 1, max = 65535))]
|
||||||
#[serde(rename = "dimensions")]
|
#[serde(rename = "dimensions")]
|
||||||
@ -48,6 +49,7 @@ pub struct VectorOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct IndexOptions {
|
pub struct IndexOptions {
|
||||||
#[validate]
|
#[validate]
|
||||||
pub vector: VectorOptions,
|
pub vector: VectorOptions,
|
||||||
@ -467,7 +469,7 @@ impl<S: G> IndexView<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct IndexStartup {
|
struct IndexStartup {
|
||||||
sealeds: HashSet<Uuid>,
|
sealeds: HashSet<Uuid>,
|
||||||
growings: HashSet<Uuid>,
|
growings: HashSet<Uuid>,
|
||||||
|
@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct OptimizingOptions {
|
pub struct OptimizingOptions {
|
||||||
#[serde(default = "OptimizingOptions::default_sealing_secs")]
|
#[serde(default = "OptimizingOptions::default_sealing_secs")]
|
||||||
#[validate(range(min = 0, max = 60))]
|
#[validate(range(min = 0, max = 60))]
|
||||||
|
@ -7,6 +7,7 @@ use crate::prelude::*;
|
|||||||
use crate::utils::dir_ops::sync_dir;
|
use crate::utils::dir_ops::sync_dir;
|
||||||
use crate::utils::file_wal::FileWal;
|
use crate::utils::file_wal::FileWal;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -199,7 +200,7 @@ impl<S: G> Drop for GrowingSegment<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct Log<S: G> {
|
struct Log<S: G> {
|
||||||
vector: Vec<S::Scalar>,
|
vector: Vec<S::Scalar>,
|
||||||
payload: Payload,
|
payload: Payload,
|
||||||
|
@ -9,6 +9,7 @@ use validator::Validate;
|
|||||||
use validator::ValidationError;
|
use validator::ValidationError;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
#[validate(schema(function = "Self::validate_0"))]
|
#[validate(schema(function = "Self::validate_0"))]
|
||||||
pub struct SegmentsOptions {
|
pub struct SegmentsOptions {
|
||||||
#[serde(default = "SegmentsOptions::default_max_growing_segment_size")]
|
#[serde(default = "SegmentsOptions::default_max_growing_segment_size")]
|
||||||
|
@ -87,7 +87,7 @@ pub trait FloatCast: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum DynamicVector {
|
pub enum DynamicVector {
|
||||||
F32(Vec<F32>),
|
F32(Vec<F32>),
|
||||||
F16(Vec<F16>),
|
F16(Vec<F16>),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Vec2<S: G> {
|
pub struct Vec2<S: G> {
|
||||||
dims: u16,
|
dims: u16,
|
||||||
v: Vec<S::Scalar>,
|
v: Vec<S::Scalar>,
|
||||||
|
@ -10,6 +10,7 @@ use crate::utils::dir_ops::sync_dir;
|
|||||||
use crate::utils::file_atomic::FileAtomic;
|
use crate::utils::file_atomic::FileAtomic;
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::DisplayFromStr;
|
use serde_with::DisplayFromStr;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -172,7 +173,7 @@ impl WorkerProtect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[serde_with::serde_as]
|
#[serde_with::serde_as]
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct WorkerStartup {
|
struct WorkerStartup {
|
||||||
#[serde_as(as = "HashMap<DisplayFromStr, _>")]
|
#[serde_as(as = "HashMap<DisplayFromStr, _>")]
|
||||||
indexes: HashMap<Id, IndexOptions>,
|
indexes: HashMap<Id, IndexOptions>,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::datatype::typmod::Typmod;
|
use crate::datatype::typmod::Typmod;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::Deserialize;
|
||||||
use service::index::indexing::IndexingOptions;
|
use service::index::indexing::IndexingOptions;
|
||||||
use service::index::optimizing::OptimizingOptions;
|
use service::index::optimizing::OptimizingOptions;
|
||||||
use service::index::segments::SegmentsOptions;
|
use service::index::segments::SegmentsOptions;
|
||||||
@ -118,7 +118,8 @@ unsafe fn get_parsed_from_varlena(helper: *const pgrx::pg_sys::varlena) -> Parse
|
|||||||
toml::from_str::<Parsed>(cstr.to_str().unwrap()).unwrap()
|
toml::from_str::<Parsed>(cstr.to_str().unwrap()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Deserialize, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
struct Parsed {
|
struct Parsed {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
segment: SegmentsOptions,
|
segment: SegmentsOptions,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum CreatePacket {
|
pub enum CreatePacket {
|
||||||
|
12
tests/sqllogictest/index.slt
Normal file
12
tests/sqllogictest/index.slt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
statement ok
|
||||||
|
DROP TABLE IF EXISTS t;
|
||||||
|
|
||||||
|
statement ok
|
||||||
|
CREATE TABLE t (val vector(3));
|
||||||
|
|
||||||
|
statement ok
|
||||||
|
INSERT INTO t (val) SELECT ARRAY[random(), random(), random()]::real[] FROM generate_series(1, 1000);
|
||||||
|
|
||||||
|
statement error unknown
|
||||||
|
CREATE INDEX ON t USING vectors (val vector_l2_ops)
|
||||||
|
WITH (options = "unknown_field = 1");
|
Reference in New Issue
Block a user