Compare commits

...
12 changed files with 127 additions and 72 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ If this is false, and another index already exists on the same columns
and the same name, then an error will be returned. This is true even if and the same name, then an error will be returned. This is true even if
that index is out of date. that index is out of date.
The default is true The default is false
*** ***
+1 -5
View File
@@ -1526,11 +1526,7 @@ describe("When creating an index", () => {
it("should allow me to replace (or not) an existing index", async () => { it("should allow me to replace (or not) an existing index", async () => {
await tbl.createIndex("id"); await tbl.createIndex("id");
// Default is replace=true await expect(tbl.createIndex("id")).rejects.toThrow("already exists");
await tbl.createIndex("id");
await expect(tbl.createIndex("id", { replace: false })).rejects.toThrow(
"already exists",
);
await tbl.createIndex("id", { replace: true }); await tbl.createIndex("id", { replace: true });
}); });
+1 -1
View File
@@ -841,7 +841,7 @@ export interface IndexOptions {
* and the same name, then an error will be returned. This is true even if * and the same name, then an error will be returned. This is true even if
* that index is out of date. * that index is out of date.
* *
* The default is true * The default is false
*/ */
replace?: boolean; replace?: boolean;
+4 -12
View File
@@ -402,6 +402,7 @@ class RemoteTable(Table):
/, /,
*, *,
config: IndexConfigType, config: IndexConfigType,
replace: bool = ...,
wait_timeout: Optional[timedelta] = ..., wait_timeout: Optional[timedelta] = ...,
name: Optional[str] = ..., name: Optional[str] = ...,
train: bool = ..., train: bool = ...,
@@ -416,7 +417,7 @@ class RemoteTable(Table):
index_cache_size: Optional[int] = ..., index_cache_size: Optional[int] = ...,
num_partitions: Optional[int] = ..., num_partitions: Optional[int] = ...,
num_sub_vectors: Optional[int] = ..., num_sub_vectors: Optional[int] = ...,
replace: Optional[bool] = ..., replace: bool = ...,
accelerator: Optional[str] = ..., accelerator: Optional[str] = ...,
index_type: Literal[ index_type: Literal[
"VECTOR", "IVF_FLAT", "IVF_SQ", "IVF_PQ", "IVF_HNSW_SQ", "IVF_HNSW_PQ" "VECTOR", "IVF_FLAT", "IVF_SQ", "IVF_PQ", "IVF_HNSW_SQ", "IVF_HNSW_PQ"
@@ -435,7 +436,7 @@ class RemoteTable(Table):
index_cache_size: Optional[int] = None, index_cache_size: Optional[int] = None,
num_partitions: Optional[int] = None, num_partitions: Optional[int] = None,
num_sub_vectors: Optional[int] = None, num_sub_vectors: Optional[int] = None,
replace: Optional[bool] = None, replace: bool = False,
accelerator: Optional[str] = None, accelerator: Optional[str] = None,
index_type="vector", index_type="vector",
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
@@ -479,7 +480,6 @@ class RemoteTable(Table):
vector_column_name, vector_column_name,
accelerator, accelerator,
index_cache_size, index_cache_size,
replace,
) )
if is_legacy: if is_legacy:
@@ -503,12 +503,6 @@ class RemoteTable(Table):
"If you have 100M+ vectors to index," "If you have 100M+ vectors to index,"
"please contact us at contact@lancedb.com" "please contact us at contact@lancedb.com"
) )
if replace is not None:
logging.warning(
"replace is not supported on LanceDB cloud."
"Existing indexes will always be replaced."
)
idx_type = index_type.upper() idx_type = index_type.upper()
if idx_type == "VECTOR" or idx_type == "IVF_PQ": if idx_type == "VECTOR" or idx_type == "IVF_PQ":
config = IvfPq( config = IvfPq(
@@ -561,7 +555,7 @@ class RemoteTable(Table):
column: str, column: str,
*, *,
config: IndexConfigType, config: IndexConfigType,
replace: Optional[bool] = None, replace: bool = False,
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
name: Optional[str] = None, name: Optional[str] = None,
train: bool = True, train: bool = True,
@@ -593,7 +587,6 @@ class RemoteTable(Table):
vector_column_name: str, vector_column_name: str,
accelerator: Optional[str], accelerator: Optional[str],
index_cache_size: Optional[int], index_cache_size: Optional[int],
replace: Optional[bool],
) -> bool: ) -> bool:
"""Detect if this is a legacy create_index call.""" """Detect if this is a legacy create_index call."""
if config is not None: if config is not None:
@@ -605,7 +598,6 @@ class RemoteTable(Table):
num_sub_vectors, num_sub_vectors,
accelerator, accelerator,
index_cache_size, index_cache_size,
replace,
) )
): ):
return True return True
+13 -13
View File
@@ -1132,7 +1132,7 @@ class Table(ABC):
num_partitions: Optional[int] = None, num_partitions: Optional[int] = None,
num_sub_vectors: Optional[int] = None, num_sub_vectors: Optional[int] = None,
vector_column_name: str = VECTOR_COLUMN_NAME, vector_column_name: str = VECTOR_COLUMN_NAME,
replace: bool = True, replace: bool = False,
accelerator: Optional[str] = None, accelerator: Optional[str] = None,
index_cache_size: Optional[int] = None, index_cache_size: Optional[int] = None,
*, *,
@@ -1166,7 +1166,7 @@ class Table(ABC):
The index configuration object. If provided, uses the new unified API. The index configuration object. If provided, uses the new unified API.
Can be one of: IvfFlat, IvfPq, IvfSq, IvfRq, HnswPq, HnswSq, Can be one of: IvfFlat, IvfPq, IvfSq, IvfRq, HnswPq, HnswSq,
BTree, Bitmap, LabelList, Fm, FTS. BTree, Bitmap, LabelList, Fm, FTS.
replace : bool, default True replace : bool, default False
Whether to replace an existing index on this column. Whether to replace an existing index on this column.
wait_timeout : timedelta, optional wait_timeout : timedelta, optional
Timeout to wait for async indexing to complete. Timeout to wait for async indexing to complete.
@@ -1198,7 +1198,7 @@ class Table(ABC):
column: str, column: str,
*, *,
config: IndexConfigType, config: IndexConfigType,
replace: Optional[bool] = None, replace: bool = False,
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
name: Optional[str] = None, name: Optional[str] = None,
train: bool = True, train: bool = True,
@@ -1260,7 +1260,7 @@ class Table(ABC):
self, self,
column: str, column: str,
*, *,
replace: bool = True, replace: bool = False,
index_type: ScalarIndexType = "BTREE", index_type: ScalarIndexType = "BTREE",
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
name: Optional[str] = None, name: Optional[str] = None,
@@ -1272,7 +1272,7 @@ class Table(ABC):
column : str column : str
The column to be indexed. Must be a boolean, integer, float, The column to be indexed. Must be a boolean, integer, float,
or string column. or string column.
replace : bool, default True replace : bool, default False
Replace the existing index if it exists. Replace the existing index if it exists.
index_type: Literal["BTREE", "BITMAP", "LABEL_LIST"], default "BTREE" index_type: Literal["BTREE", "BITMAP", "LABEL_LIST"], default "BTREE"
The type of index to create. The type of index to create.
@@ -2988,7 +2988,7 @@ class LanceTable(Table):
num_partitions: Optional[int] = None, num_partitions: Optional[int] = None,
num_sub_vectors: Optional[int] = None, num_sub_vectors: Optional[int] = None,
vector_column_name: str = VECTOR_COLUMN_NAME, vector_column_name: str = VECTOR_COLUMN_NAME,
replace: bool = True, replace: bool = False,
accelerator: Optional[str] = None, accelerator: Optional[str] = None,
index_cache_size: Optional[int] = None, index_cache_size: Optional[int] = None,
num_bits: int = 8, num_bits: int = 8,
@@ -3030,7 +3030,7 @@ class LanceTable(Table):
The index configuration object. If provided, uses the new unified API. The index configuration object. If provided, uses the new unified API.
Can be one of: IvfFlat, IvfPq, IvfSq, IvfRq, HnswPq, HnswSq, Can be one of: IvfFlat, IvfPq, IvfSq, IvfRq, HnswPq, HnswSq,
BTree, Bitmap, LabelList, Fm, FTS. BTree, Bitmap, LabelList, Fm, FTS.
replace : bool, default True replace : bool, default False
Whether to replace an existing index on this column. Whether to replace an existing index on this column.
wait_timeout : timedelta, optional wait_timeout : timedelta, optional
Timeout to wait for async indexing to complete. Timeout to wait for async indexing to complete.
@@ -3169,7 +3169,7 @@ class LanceTable(Table):
column: str, column: str,
*, *,
config: IndexConfigType, config: IndexConfigType,
replace: Optional[bool] = None, replace: bool = False,
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
name: Optional[str] = None, name: Optional[str] = None,
train: bool = True, train: bool = True,
@@ -3424,7 +3424,7 @@ class LanceTable(Table):
self, self,
column: str, column: str,
*, *,
replace: bool = True, replace: bool = False,
index_type: ScalarIndexType = "BTREE", index_type: ScalarIndexType = "BTREE",
name: Optional[str] = None, name: Optional[str] = None,
): ):
@@ -5313,7 +5313,7 @@ class AsyncTable:
self, self,
column: str, column: str,
*, *,
replace: Optional[bool] = None, replace: bool = False,
config: Optional[ config: Optional[
Union[ Union[
IvfFlat, IvfFlat,
@@ -5344,14 +5344,14 @@ class AsyncTable:
---------- ----------
column: str column: str
The column to index. The column to index.
replace: bool, default True replace: bool, default False
Whether to replace the existing index Whether to replace the existing index
If this is false, and another index already exists on the same columns If this is false, and another index already exists on the same columns
and the same name, then an error will be returned. This is true even if and the same name, then an error will be returned. This is true even if
that index is out of date. that index is out of date.
The default is True The default is False
config: default None config: default None
For advanced configuration you can specify the type of index you would For advanced configuration you can specify the type of index you would
like to create. You can also specify index-specific parameters when like to create. You can also specify index-specific parameters when
@@ -5409,7 +5409,7 @@ class AsyncTable:
self, self,
column: str, column: str,
*, *,
replace: Optional[bool] = None, replace: bool = False,
config: Optional[ config: Optional[
Union[ Union[
IvfFlat, IvfFlat,
+10 -2
View File
@@ -97,6 +97,9 @@ async def test_create_index_async_returns_done_job(some_table: AsyncTable):
async def test_create_scalar_index(some_table: AsyncTable): async def test_create_scalar_index(some_table: AsyncTable):
# Can create # Can create
await some_table.create_index("id") await some_table.create_index("id")
# Can't recreate by default
with pytest.raises(RuntimeError, match="already exists"):
await some_table.create_index("id")
# Can recreate if replace=True # Can recreate if replace=True
await some_table.create_index("id", replace=True) await some_table.create_index("id", replace=True)
indices = await some_table.list_indices() indices = await some_table.list_indices()
@@ -110,7 +113,7 @@ async def test_create_scalar_index(some_table: AsyncTable):
with pytest.raises(RuntimeError, match="already exists"): with pytest.raises(RuntimeError, match="already exists"):
await some_table.create_index("id", replace=False) await some_table.create_index("id", replace=False)
# can also specify index type # can also specify index type
await some_table.create_index("id", config=BTree()) await some_table.create_index("id", config=BTree(), replace=True)
await some_table.drop_index("id_idx") await some_table.drop_index("id_idx")
indices = await some_table.list_indices() indices = await some_table.list_indices()
@@ -351,13 +354,18 @@ async def test_full_text_search_index(some_table: AsyncTable):
async def test_create_vector_index(some_table: AsyncTable): async def test_create_vector_index(some_table: AsyncTable):
# Can create # Can create
await some_table.create_index("vector") await some_table.create_index("vector")
# Can't recreate by default
with pytest.raises(RuntimeError, match="already exists"):
await some_table.create_index("vector")
# Can recreate if replace=True # Can recreate if replace=True
await some_table.create_index("vector", replace=True) await some_table.create_index("vector", replace=True)
# Can't recreate if replace=False # Can't recreate if replace=False
with pytest.raises(RuntimeError, match="already exists"): with pytest.raises(RuntimeError, match="already exists"):
await some_table.create_index("vector", replace=False) await some_table.create_index("vector", replace=False)
# Can also specify index type # Can also specify index type
await some_table.create_index("vector", config=IvfPq(num_partitions=100)) await some_table.create_index(
"vector", config=IvfPq(num_partitions=100), replace=True
)
indices = await some_table.list_indices() indices = await some_table.list_indices()
assert len(indices) == 1 assert len(indices) == 1
assert indices[0].index_type == "IvfPq" assert indices[0].index_type == "IvfPq"
+1 -1
View File
@@ -834,7 +834,7 @@ def test_table_create_indices():
vector_req = received_requests[2] vector_req = received_requests[2]
assert "name" in vector_req assert "name" in vector_req
assert vector_req["name"] == "custom_vector_idx" assert vector_req["name"] == "custom_vector_idx"
assert "replace" not in vector_req assert vector_req["replace"] is False
table.wait_for_index(["custom_scalar_idx"], timedelta(seconds=2)) table.wait_for_index(["custom_scalar_idx"], timedelta(seconds=2))
table.wait_for_index( table.wait_for_index(
+8 -8
View File
@@ -1600,7 +1600,7 @@ def test_create_index_method(mock_create_index, mem_db: DBConnection):
) )
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"my_vector", "my_vector",
replace=True, replace=False,
config=expected_config, config=expected_config,
wait_timeout=None, wait_timeout=None,
name=None, name=None,
@@ -1620,7 +1620,7 @@ def test_create_index_method(mock_create_index, mem_db: DBConnection):
) )
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"my_vector", "my_vector",
replace=True, replace=False,
config=expected_config, config=expected_config,
wait_timeout=None, wait_timeout=None,
name=None, name=None,
@@ -1646,7 +1646,7 @@ def test_create_index_name_and_train_parameters(
expected_config = IvfPq() # Default config expected_config = IvfPq() # Default config
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"vector", "vector",
replace=True, replace=False,
config=expected_config, config=expected_config,
wait_timeout=None, wait_timeout=None,
name="my_custom_index", name="my_custom_index",
@@ -1657,7 +1657,7 @@ def test_create_index_name_and_train_parameters(
table.create_index(vector_column_name="vector", train=False) table.create_index(vector_column_name="vector", train=False)
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"vector", "vector",
replace=True, replace=False,
config=expected_config, config=expected_config,
wait_timeout=None, wait_timeout=None,
name=None, name=None,
@@ -1668,7 +1668,7 @@ def test_create_index_name_and_train_parameters(
table.create_index(vector_column_name="vector", name="my_index_name", train=True) table.create_index(vector_column_name="vector", name="my_index_name", train=True)
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"vector", "vector",
replace=True, replace=False,
config=expected_config, config=expected_config,
wait_timeout=None, wait_timeout=None,
name="my_index_name", name="my_index_name",
@@ -1705,7 +1705,7 @@ def test_create_index_new_api(mock_create_index, mem_db: DBConnection):
table.create_index("vector", config=IvfPq(distance_type="l2")) table.create_index("vector", config=IvfPq(distance_type="l2"))
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"vector", "vector",
replace=True, replace=False,
config=IvfPq(distance_type="l2"), config=IvfPq(distance_type="l2"),
wait_timeout=None, wait_timeout=None,
name=None, name=None,
@@ -1716,7 +1716,7 @@ def test_create_index_new_api(mock_create_index, mem_db: DBConnection):
table.create_index("category", config=BTree()) table.create_index("category", config=BTree())
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"category", "category",
replace=True, replace=False,
config=BTree(), config=BTree(),
wait_timeout=None, wait_timeout=None,
name=None, name=None,
@@ -1727,7 +1727,7 @@ def test_create_index_new_api(mock_create_index, mem_db: DBConnection):
table.create_index("text", config=FTS(with_position=True)) table.create_index("text", config=FTS(with_position=True))
mock_create_index.assert_called_with( mock_create_index.assert_called_with(
"text", "text",
replace=True, replace=False,
config=FTS(with_position=True), config=FTS(with_position=True),
wait_timeout=None, wait_timeout=None,
name=None, name=None,
+2 -2
View File
@@ -200,14 +200,14 @@ impl IndexBuilder {
parent, parent,
index, index,
columns, columns,
replace: true, replace: false,
train: true, train: true,
wait_timeout: None, wait_timeout: None,
name: None, name: None,
} }
} }
/// Whether to replace the existing index, the default is `true`. /// Whether to replace the existing index, the default is `false`.
/// ///
/// If this is false, and another index already exists on the same columns /// If this is false, and another index already exists on the same columns
/// and the same name, then an error will be returned. This is true even if /// and the same name, then an error will be returned. This is true even if
+35 -17
View File
@@ -40,6 +40,7 @@ impl TerminalResult {
} }
} }
#[cfg(feature = "remote")]
pub(crate) fn remote(value: Option<Value>, request_id: String) -> Self { pub(crate) fn remote(value: Option<Value>, request_id: String) -> Self {
Self { Self {
value, value,
@@ -47,30 +48,46 @@ impl TerminalResult {
} }
} }
#[cfg(feature = "remote")]
pub(crate) fn value(&self) -> Option<&Value> { pub(crate) fn value(&self) -> Option<&Value> {
self.value.as_ref() self.value.as_ref()
} }
fn decode<T: DeserializeOwned>(self) -> Result<T> { fn decode<T: DeserializeOwned>(self) -> Result<T> {
let value = self.value.ok_or_else(|| match &self.request_id { let value = self.value.ok_or_else(|| {
Some(request_id) => Error::Http { #[cfg(feature = "remote")]
source: "successful typed job response did not contain a result".into(), if let Some(request_id) = &self.request_id {
request_id: request_id.clone(), return Error::Http {
status_code: None, source: "successful typed job response did not contain a result".into(),
}, request_id: request_id.clone(),
None => Error::Runtime { status_code: None,
};
}
Error::Runtime {
message: "successful typed job did not contain a result".to_string(), message: "successful typed job did not contain a result".to_string(),
}, }
})?; })?;
serde_json::from_value(value).map_err(|error| match self.request_id { serde_json::from_value(value).map_err(|error| {
Some(request_id) => Error::Http { #[cfg(feature = "remote")]
source: format!("failed to parse typed job result: {error}").into(), {
request_id, match self.request_id {
status_code: None, Some(request_id) => Error::Http {
}, source: format!("failed to parse typed job result: {error}").into(),
None => Error::Runtime { request_id,
message: format!("failed to parse typed job result: {error}"), status_code: None,
}, },
None => Error::Runtime {
message: format!("failed to parse typed job result: {error}"),
},
}
}
#[cfg(not(feature = "remote"))]
{
let _ = self.request_id;
Error::Runtime {
message: format!("failed to parse typed job result: {error}"),
}
}
}) })
} }
} }
@@ -117,6 +134,7 @@ impl Job<()> {
} }
} }
#[cfg(feature = "remote")]
pub(crate) fn new(handle: Box<dyn JobHandle>) -> Self { pub(crate) fn new(handle: Box<dyn JobHandle>) -> Self {
Self { Self {
inner: JobInner::Handle { inner: JobInner::Handle {
+49 -7
View File
@@ -524,13 +524,10 @@ impl<S: HttpSend> RemoteTable<S> {
_ => resolve_arrow_field_path(&schema, &column)?, _ => resolve_arrow_field_path(&schema, &column)?,
}; };
let mut body = serde_json::json!({ let mut body = serde_json::json!({
"column": canonical_column "column": canonical_column,
"replace": index.replace,
}); });
if !index.replace {
body["replace"] = false.into();
}
// Add name parameter if provided (for backwards compatibility, only include if Some) // Add name parameter if provided (for backwards compatibility, only include if Some)
if let Some(ref name) = index.name { if let Some(ref name) = index.name {
body["name"] = serde_json::Value::String(name.clone()); body["name"] = serde_json::Value::String(name.clone());
@@ -6309,6 +6306,7 @@ mod tests {
let mut expected_body = expected_body.clone(); let mut expected_body = expected_body.clone();
expected_body["column"] = "a".into(); expected_body["column"] = "a".into();
expected_body[INDEX_TYPE_KEY] = index_type.into(); expected_body[INDEX_TYPE_KEY] = index_type.into();
expected_body["replace"] = false.into();
assert_eq!(body, expected_body); assert_eq!(body, expected_body);
@@ -6327,7 +6325,7 @@ mod tests {
} }
#[tokio::test] #[tokio::test]
async fn test_create_index_forwards_replace_false_on_existing_route() { async fn test_create_index_forwards_default_replace_false_on_existing_route() {
let table = Table::new_with_handler("my_table", move |request| { let table = Table::new_with_handler("my_table", move |request| {
assert_eq!(request.method(), "POST"); assert_eq!(request.method(), "POST");
match request.url().path() { match request.url().path() {
@@ -6354,7 +6352,40 @@ mod tests {
table table
.create_index(&["a"], Index::BTree(Default::default())) .create_index(&["a"], Index::BTree(Default::default()))
.replace(false) .execute()
.await
.unwrap();
}
#[tokio::test]
async fn test_create_index_forwards_explicit_replace_true_on_existing_route() {
let table = Table::new_with_handler("my_table", move |request| {
assert_eq!(request.method(), "POST");
match request.url().path() {
"/v1/table/my_table/describe/" => {
let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
http::Response::builder()
.status(200)
.body(describe_response(&schema))
.unwrap()
}
"/v1/table/my_table/create_index/" => {
let body = request.body().unwrap().as_bytes().unwrap();
let body: serde_json::Value = serde_json::from_slice(body).unwrap();
assert_eq!(body["replace"], json!(true));
http::Response::builder()
.status(200)
.body("{}".to_string())
.unwrap()
}
path => panic!("Unexpected path: {}", path),
}
});
table
.create_index(&["a"], Index::BTree(Default::default()))
.replace(true)
.execute() .execute()
.await .await
.unwrap(); .unwrap();
@@ -6585,38 +6616,46 @@ mod tests {
json!({ json!({
"column": "rowId", "column": "rowId",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "`row-id`", "column": "`row-id`",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "userId", "column": "userId",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "MetaData.userId", "column": "MetaData.userId",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "metadata.user_id", "column": "metadata.user_id",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "image.embedding", "column": "image.embedding",
"index_type": "IVF_PQ", "index_type": "IVF_PQ",
"metric_type": "l2", "metric_type": "l2",
"replace": false,
}), }),
{ {
let mut body = serde_json::to_value(InvertedIndexParams::default()).unwrap(); let mut body = serde_json::to_value(InvertedIndexParams::default()).unwrap();
body["column"] = "payload.text".into(); body["column"] = "payload.text".into();
body["index_type"] = "FTS".into(); body["index_type"] = "FTS".into();
body["replace"] = false.into();
body body
}, },
{ {
let mut body = serde_json::to_value(InvertedIndexParams::default()).unwrap(); let mut body = serde_json::to_value(InvertedIndexParams::default()).unwrap();
body["column"] = "docs.content".into(); body["column"] = "docs.content".into();
body["index_type"] = "FTS".into(); body["index_type"] = "FTS".into();
body["replace"] = false.into();
body body
}, },
{ {
@@ -6624,15 +6663,18 @@ mod tests {
body["column"] = "docs.content".into(); body["column"] = "docs.content".into();
body["index_type"] = "FTS".into(); body["index_type"] = "FTS".into();
body["document_granularity"] = "list_element".into(); body["document_granularity"] = "list_element".into();
body["replace"] = false.into();
body body
}, },
json!({ json!({
"column": "`meta-data`.`user-id`", "column": "`meta-data`.`user-id`",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
json!({ json!({
"column": "literal.`a.b`", "column": "literal.`a.b`",
"index_type": "BTREE", "index_type": "BTREE",
"replace": false,
}), }),
]); ]);
let request_idx = Arc::new(AtomicUsize::new(0)); let request_idx = Arc::new(AtomicUsize::new(0));
+2 -3
View File
@@ -725,12 +725,11 @@ mod tests {
.await .await
.unwrap(); .unwrap();
// Rebuilding the same index without replace fails once the build // Rebuilding the same index without explicit replace fails once the build
// starts, so the failure reaches the job rather than execute_async. // starts, so the failure reaches the job rather than execute_async.
let job = Arc::new( let job = Arc::new(
table table
.create_index(&["id"], Index::BTree(BTreeIndexBuilder::default())) .create_index(&["id"], Index::BTree(BTreeIndexBuilder::default()))
.replace(false)
.execute_async() .execute_async()
.await .await
.unwrap(), .unwrap(),
@@ -769,7 +768,6 @@ mod tests {
let job = table let job = table
.create_index(&["id"], Index::BTree(BTreeIndexBuilder::default())) .create_index(&["id"], Index::BTree(BTreeIndexBuilder::default()))
.replace(false)
.execute_async() .execute_async()
.await .await
.unwrap(); .unwrap();
@@ -1106,6 +1104,7 @@ mod tests {
// Can also specify btree // Can also specify btree
table table
.create_index(&["i"], Index::BTree(BTreeIndexBuilder::default())) .create_index(&["i"], Index::BTree(BTreeIndexBuilder::default()))
.replace(true)
.execute() .execute()
.await .await
.unwrap(); .unwrap();