Commit Graph

164 Commits

Author SHA1 Message Date
Jojii
7a8703f166 [TQDT] API (#9172)
* [ai] TQDT in the API

* [ai] unify new sparse error for TQDT

* Rename to `turbo4`

* Add `Turbo4` to comments and doc strings.

* Also validate named sparse vector creation
2026-05-29 15:26:39 +02:00
Tim Visée
ff4e41ed88 Fix empty vector panic (#9070)
* Add test

* Validate empty vector name

* Update test assertions
2026-05-19 15:21:40 +02:00
qdrant-cloud-bot
89fa850edd fix: validate vector dimensions before WAL write for async upserts (#9058)
* fix: validate vector dimensions before WAL write for async upserts

When upserting points with wait=false (the default), dimension
mismatches were silently discarded during background processing.
The API returned 200 "acknowledged" but the points were never stored,
causing silent data loss with no error feedback to the user.

This adds an early dimension validation check in do_upsert_points()
that runs before the operation is written to WAL. This ensures that
dimension errors are returned to the client regardless of the wait
parameter, matching the behavior of wait=true.

The validation handles all vector types:
- Dense single vectors
- Multi-dense vectors
- Named vectors (dense, multi-dense, sparse)
- Sparse vectors are skipped (no fixed dimension)

Closes #9039

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: move vector dimension validation into dedicated module

Extract validate_vector_dimensions and helper functions from update.rs
into src/common/validate_vectors.rs for better code organization.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: update shard update test for early dimension validation

The test expected a shard-level error message, but now dimension
mismatches are caught before reaching the shards. Update the assertion
to accept either the early validation error or the shard-level error.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: assert actual dimension error message in shard update test

Check for the descriptive error ("Vector dimension error: expected dim: 4, got 3")
rather than the generic shard failure wrapper.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 20:18:56 +02:00
qdrant-cloud-bot
50e9c7bba7 Fix match: {except: []} returning zero results with payload index (#9055)
* Add integration test for `match: {except: []}` with integer index

Regression test for https://github.com/qdrant/qdrant/issues/9050

An empty `except` list (NOT IN []) should always match all points that
have the field, both with and without a payload index. Currently the
integer (and keyword) indexed path incorrectly returns zero results
because:

1. serde deserializes `except: []` as `AnyVariants::Strings([])` (first
   variant of the untagged enum)
2. The map index filter_impl returns `iter::empty()` for empty
   cross-type variant, instead of matching everything

The test covers:
- except: [] without any index (baseline, currently works)
- except: [] with an integer index (currently broken)
- except: [] with a keyword index (currently broken)

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix `match: {except: []}` returning zero results with payload index

Fixes https://github.com/qdrant/qdrant/issues/9050

Root cause: `except: []` deserializes as `AnyVariants::Strings([])`
due to the untagged serde enum trying `Strings` first. On an integer
index, the filter_impl matched `Except + Strings(empty)` and returned
`iter::empty()` (zero results). The same issue existed symmetrically
on keyword indexes with `Integers(empty)` and on UUID indexes with
`Integers(empty)`.

The fix: when the cross-type variant reaches the Except branch (e.g.
Strings on an integer index, Integers on a keyword/UUID index), return
`None` unconditionally — regardless of whether the set is empty. This
delegates to the fallback condition checker, which already handles
`except: []` correctly by matching all values.

The `estimate_cardinality_impl` functions had the same bug (returning
`CardinalityEstimation::exact(0)` for the empty cross-type case) and
are fixed the same way.

Affected index types: integer, keyword (str), UUID.
Bool index is NOT affected — it already returns `None` for all
Any/Except conditions.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Expand match-except test to cover all index types and cross-type filters

Extends the regression test for #9050 to comprehensively cover:

- Integer, keyword, and UUID field indexes
- Empty except list (the original bug) for each index type
- Non-empty except list with matching types (normal filtering)
- Cross-type except values (e.g. strings on integer index, integers on
  keyword/UUID index) — type mismatch should exclude nothing → all match
- Exclude-all: listing every value should return zero results
- All scenarios tested both with and without a payload index

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-15 12:51:28 +02:00
Anton Antonov
ce074b1a70 fix(openapi-tests): inject QDRANT_HOST_HEADERS (#9022)
Raw requests already use QDRANT_HOST, but bypass request_with_validation
and missed QDRANT_HOST_HEADERS. Without these headers, tests cannot run
behind host-based reverse proxies or mocks.
2026-05-12 21:14:16 +03:00
qdrant-cloud-bot
be82eceb40 Fix flaky strict mode collection size tests (#8922)
These tests rely on the collection size stats cache being refreshed to
detect that a size limit has been exceeded. Without wait=true, upsert
operations are written to WAL and acknowledged immediately without being
applied to segments. When the cache refreshes, it reads segment data
which may not yet reflect the pending WAL operations, causing the size
check to see stale values and not reject the request.

Adding wait=true ensures operations are applied to segments before the
response returns, so the cache refresh sees the correct sizes.

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-06 13:14:06 +02:00
Jojii
e108a11ae3 [ai] OpenApi tests for TurboQuant (#8845) 2026-04-30 11:01:05 +02:00
Andrey Vasnetsov
d02ef48f24 Dynamic cpu pool (#8790)
* [AI] inptoduce CPU process measurement

* use parking_lot + 4 seconds refresh rate

* [AI] AdaptiveSearchHandle

* fmt

* openapi schema

* keep Runtime field

* fix test

* [AI] instead of async semaphore, use 2 runtimes

* Adjust usage window to 2 seconds

* Address CodeRabbit review comments for dynamic CPU pool

- OpenAPI / telemetry: user-facing cpu_cores_used description (2s window, when null).
- process_cpu_usage: backoff after procfs errors; serialize Linux unit tests on CACHE.
- Docs: decouple runtime thread comments from hardcoded 4× multiplier; name search_runtime in test.
- consensus test: replace stale runtime comment.

Made-with: Cursor

* chore(openapi): regenerate master spec via generate_openapi_models.sh

Replace hand-edited cpu_cores_used description with output from
schema_generator + merge pipeline so openapi_consistency_check passes.

Made-with: Cursor

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-04-27 12:56:29 +02:00
Arnaud Gourlay
4d435e5734 Fix Openapi spec for new vector crud ops (#8779)
* Fix Openapi spec for new vector crud ops

* validate spec conformance in tests
2026-04-23 18:34:50 +02:00
Arnaud Gourlay
4cb494d3b6 Fix missing validation on adding named vector (#8776) 2026-04-23 12:23:38 +02:00
Arnaud Gourlay
2481fd32ed Fix panic in validate_iter when two siblings fail validation (#8762) 2026-04-22 13:58:32 +02:00
Tim Visée
3ac7e8409f Fix IsEmpty condition on null rebuilt index (#8734)
* [ai] Fix IsEmpty condition on null rebuilt index

* [#8734] Alternative fix (#8736)

* don't grow mmap

* fix iter_falses

* Fix is_empty and has_values mix up

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-04-21 15:23:46 +02:00
Jojii
f51c334554 Fix grpc stop words (#8728)
* Fix stopwords always being lowered in grpc path only

* [ai] add integration test, stopwords grpc vs rest
2026-04-20 11:27:32 +02:00
qdrant-cloud-bot
e160fb9ed4 Fix datetime parsing for YYYY-MM-DDTHH:MM format (T separator, no seconds) (#8719)
The documented format `2023-02-08T10:49` was not accepted because the
parser only had `%Y-%m-%d %H:%M` (space separator) but was missing
`%Y-%m-%dT%H:%M` (T separator). Add the missing format variant and
tests.

Closes #8718

Made-with: Cursor

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-04-20 10:00:56 +02:00
Andrey Vasnetsov
acfb6503b1 crud named vectors (#8605)
* Add empty placeholder vector storage types for named vector CRUD

Introduce EmptyDenseVectorStorage and EmptySparseVectorStorage as
placeholder storages for newly created named vectors on immutable
segments. These report all vectors as deleted, consume no disk space,
and are reconstructed from segment config on load via the new
VectorStorageType::Empty and SparseVectorStorageType::Empty variants.

Key design decisions:
- is_on_disk is derived from original user config, not hardcoded
- MultiVectorConfig is preserved for multi-vector support
- Config mismatch optimizer skips Empty storage to avoid false rebuilds
- Quantization delegates normally (handles 0 vectors gracefully)
- get_vector includes debug_assert to catch unexpected access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [AI] segment-level operations for creating and deleting anmed vectors

* [AI] implement named vector creation and deleting in proxy segment

* [AI] Step 3: Proxy Segment Handling for Named Vector Operations

* [AI] implement for Edge

* [AI] implement consensus operations for named vector operations

* [AI] refactor VectorNameConfig, remove VectorNameConfigInternal

* [AI] handle vector schema inconsistency in raft snapshot recovery

* [AI] rest + grpc API

* [AI] clippy

* [AI] generate openAPI schema

* fmt

* ci fixes

* [AI] fix jwt access test

* [AI] nop operation for awaiting of consensus-commited update ops

* [AI] move vector name operations into points service

* [AI] implement internal api for vector name operations

* [AI] change collection-level config along with segment level operation

* [AI] vector schema reconceliation instead of error

* fmt

* missing compile-time option

* [AI] integration test

* [AI] fix missing JWT tests

* [AI] remove NOP

* [AI] openapi test

* [AI] fix initialization of mutable segment

* [AI] more simple integration tests

* fmt

* [AI] make cluster test a bit harder

* [AI] make test less flacky

* [AI] rabbit comments

* [AI] check params compatibility before writing vector config

* [AI] make sure to register vector storages in structure payload index

* [AI] vector name validation

* lower vector length validation to 200 chars to account for prefix in filename

* [AI] proxy segment: prevent stale data leak through optimization

* fmt

* [AI] filter out removed vectors from proxy response

* [AI] handle vector name in proxy

* fmt

* adjust proxy info based on dropped vectors

* [AI] proxy segment: update filters to correct has_vector condition

* fmt

* clippy

* Fix consensus snapshot applicaiton for vector schema

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:45:18 +02:00
Leo Henon
b8a78c18eb Fix empty sparse vector name validation (#8194)
* Fix empty sparse vector name validation

* Reorder validation to check empty sparse name before duplicate name

---------

Co-authored-by: leohenon <77656081+lhenon999@users.noreply.github.com>
2026-04-10 11:18:15 +02:00
Daniel Boros
b47fa7d1ee fix: timeout tests (#8591) 2026-04-02 12:57:32 +02:00
Bhagirath Kapdi
fb704e5d13 Feature/strict mode search max batchsize (#8469)
* feat: add search_max_batchsize to strict mode config

* added test case for search_max_batchsize

* Changes for fixing CI issue dure openapi

* Modify check_strict_mode_batch

---------

Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-03-26 16:26:09 +01:00
Excellencedev
3230f1d952 Implement Per collection metrics for Promethus (#8214)
* Implement Per-Collection Prometheus Metrics

* Update config/config.yaml

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update tests/per_collection_metrics_test.sh

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update tests/per_collection_metrics_test.sh

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix ci

* comment

* Update tests/per_collection_metrics_test.sh

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* adress revew

* fix: linter

* refactor: cardinality limit, anonymize fix, cleanup

- Add max_per_collection_metrics config (default 256) to bound
  per-collection label cardinality
- Fix anonymize: strip per_collection_responses entirely instead of
  leaking hashed collection names
- Move CollectionName into requests_telemetry, remove
  telemetry_context.rs
- Add unit tests for cardinality limits
- Add integration test assertions for default mode
- Regenerate OpenAPI spec
- Document why internal gRPC doesn't attach CollectionName

* avoid cloning

* fix: address pr reviews

* fix: linter

* fix: linter

* feat: enforce {name} in actix api

* chore: remove empty line

* feat: add actix pre-commit hook

* feat: potential enforce tonic collection name

* feat: use proc_macro instead

* feat: use collection_name instead of name

* feat: add tonic telemetry tests

* fix: linter

* fix: linter

* chore: remove unneccessary clone

* fix: use collection_name everywhere

* fix: python tests and openapi

* chore: simplify collection_name tests

* actix collection_name enforcign: use relative path in test + avoid grep

* fix: remove macro

* chore: add some comment to telemetry_wrapper

* fix: clippy

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Daniel Boros <dancixx@gmail.com>
Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-23 15:19:02 +01:00
Jojii
356040312b Correct calculation of deferred point counts (#8366)
* Don't account for deferred points in some places

# Conflicts:
#	lib/collection/src/shards/local_shard/scroll.rs

* Add in QueryContext

* Cover more places

* Coderabbit review remarks

* Properly count amount of deleted deferred points (#8386)

* Properly count amount of deleted deferred points

* Prevent double-counting of the same point

* Remove hints to estimations

* Properly handle counts in ProxySegment

* Add tests and fix deleted point count issue

* Adjusts tests + fix issues

* Separte fields for deferred points in telemetry (SegmentInfo)

* Remove deferred_points_count()

* openapi

* Fix test by manually calculating visible points

* Adjust ProxySegment test to revertion of SegmentInfo

* Throw error if collection was not found in telemetry (e2e Test)

* Update lib/segment/src/segment/segment_ops.rs

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>

* Make new fields in API optional

* Don't take range if no deferred point exist

* Review remarks

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2026-03-19 11:33:09 +01:00
Arnaud Gourlay
09c0ad6fb4 Fix timeout in test_shard_snapshot_transfer_deferred (#8398)
* Fix timeout in test_shard_snapshot_transfer_deferred

* more specific exception net

* set client timeout explicitly
2026-03-13 23:42:26 +01:00
Arnaud Gourlay
9074b9640b Integration test for deferred points (#8365)
* Integration test for deferred points

* test facets

* rework
2026-03-13 12:45:19 +01:00
xzfc
8ab0057566 DiscoveryQuery -> DiscoverQuery (#8378) 2026-03-12 19:54:34 +01:00
Andrey Vasnetsov
b14e0be4ed Restrict snaphsot recovery to snapshots directory, hide file contents (#8341)
* restrict recovery from snapshot folder

* fmt

* clippy

* Extend test, path must be inside snapshots directory

* In release builds, hide detailed tar error message to not leak contents

* Change from bad request to forbidden

* fix(auth_tests): place snapshot in peer snapshots dir for recover_collection_snapshot

The recover from snapshot API now requires file:// paths to be inside the
configured snapshots directory. Write the test snapshot into the peer's
snapshots directory instead of a temp file so the request is allowed.

Made-with: Cursor

---------

Co-authored-by: timvisee <tim@visee.me>
Co-authored-by: Tim Visée <tim+github@visee.me>
Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-10 17:13:32 +01:00
Andrey Vasnetsov
6e79f8bf02 Untagged Enum for FeedbackStrategy (#8171)
* [manual] make untagged enum for consistent API for FeedbackStrategy

* add #[validate(nested)]

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-02-18 16:55:47 +01:00
Arnaud Gourlay
5ffc6a45a8 Remove update queue opnum from CollectionInfo (#8127) 2026-02-13 17:36:54 +01:00
Tim Visée
c63f9eef29 Fix stream records transfer data race, losing pending updates (#8103)
* Add integration test to assert all queued updates are also transferred

* Plunge update queue in stream records transfers

* Migrate existing plunger usages to new plunge helper

* Skip test if not compiled with staging flag

* Only send delay operation when staging feature is enabled

* Reformat

* Fix review remarks
2026-02-11 17:18:44 +01:00
Luis Cossío
a43780941b [relevance feedback] add rest and grpc interfaces (#7399)
* add rest and grpc interfaces

Also handle inference for this query

* follow refactor from base branch

* renaming from Ms Cooper

* get started on validation testing

* more validations

* test equivalence with query when less than 2 feedback elements

* rename feedback query to relevance_feedback query

* fix extraction of context pairs

* rename feedback vector to example

* make coderabbit happier

* upd test

---------

Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-02-11 16:05:11 +01:00
Luis Cossío
a87c22f56b fix: handle score_threshold in Formula queries (#8097)
* handle `score_threshold` in Formula queries

* AI: add openapi test

prompt: Upload 4 points with a numeric payload, use the payload as the
score, and set a score threshold. We can assert which ids should be in
the result and which shouldn't
2026-02-10 17:28:27 -03:00
Andrey Vasnetsov
4437edb775 Weighted rrf (#8063)
* weighted rrf implementation

* test

* fmt

* fix edge

* validate number of sources and number of weights

* do not partial match

* upd schema

* review fixes

* update formula

* remove calcualtions from tests

* update comment, because AI have OCD

* fmt
2026-02-06 19:36:27 +01:00
Ivan Pleshkov
510b0c090a Update queue status in metrics and telemetry (#8060)
* update queue status in metrics and telemetry

* fix python tests

* update openapi
2026-02-05 11:37:19 +01:00
Arnaud Gourlay
9f09dbfd3b Update queue info into CollectionInfo (#8010)
* Update queue info into CollectionInfo

* basic test

* fix

* cleaner

* Update lib/collection/src/shards/local_shard/mod.rs

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>

* fix the fix

* rename to op_num

* skip_serializing_if just in case

* first step

* test queue length with staging feature

* gate integration test based on binary feature

---------

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>
2026-01-30 17:23:53 +01:00
Andrey Vasnetsov
81e7ab72fe introduce update_mode parameter for upsert operation to control if we want to insert, update, or upsert (#7963)
* introduce update_mode parameter for upsert operation to control if we want to insert, update, or upsert

* add test

* upd dockstring

* require resharding once all peers have updated version

* use service error

* fix clippy again

* wait for same version before resharding in tests
2026-01-27 00:39:25 +01:00
xzfc
d7a0f2f882 Update GET collections/{}/optimizations (#7946)
* refactor(SegmentOptimizer::name): make it `&'static`

* refactor(TrackerStatus): add is_running()

* refactor: add TrackerSegmentInfo

* feat: rework optimizations endpoint

* feat(collections/{}/optimizations): trim spaces
2026-01-26 18:03:52 +01:00
Daniel Boros
1c20cb5090 feat/test-timeout (#7920)
* feat: add timeout tests

* fix: timeout test

* fix: api urls

* fix: test

* feat: add staging api def

* feat: add parallel executor for tests

* fix: imports

* fix: ci/cd

* rollback openapi schema change

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-01-20 13:50:02 +01:00
Andrey Vasnetsov
28215e6125 Validate vector name in matrix request (#7923)
* validate `using` param

* fix slop
2026-01-16 12:20:40 +01:00
Sapphire
a494452524 Add enable_hnsw option for payload field schema (#7887)
* feat: Add enable_hnsw option for payload field indexes

Add optional enable_hnsw parameter to all payload index types to control
whether additional HNSW graph links are built for each indexed field.

- Add enable_hnsw field to all 8 payload index param types
- Update gRPC proto definitions and conversions
- Update OpenAPI schema
- Modify HNSW graph builder to respect enable_hnsw flag
- Add enable_hnsw() helper methods to PayloadSchemaParams and PayloadFieldSchema
- Update all tests to include new field (default: None)

When enable_hnsw is true and payload_M > 0, additional HNSW links will
be built for the payload field. Default value is true for backward compatibility.

* Fix Some format problems

* fix: address comment problem

---------

Co-authored-by: EC2 Default User <ec2-user@ip-10-78-171-148.ec2.internal>
2026-01-09 11:39:44 +01:00
xzfc
77c71712db Indexing progress (#7625)
* Add progress_tracker.rs

* Pass progress tracker around

* Populate progress tracker with actual data

* Expose progress on `/collections/{name}/optimizations` endpoint
2025-12-09 00:15:36 +00:00
Jojii
8da4c22cae Make indexed-only-excluded-points metric default to 0 (#7649)
* Make indexed_only_excluded in metrics default to 0

* Fix tests
2025-12-02 09:36:41 +01:00
AMIR
4f13b994e3 Add list shard keys API (#7615) 2025-11-28 21:50:09 -03:00
Arnaud Gourlay
adc3bb8540 Fix Openapi schema for DELETE issues (#7634) 2025-11-28 14:50:34 +01:00
Arnaud Gourlay
b7da071199 Clarify multivector inline storage warning (#7523)
* Clarify multivector inline storage warning

* do what I actually wanted to do in first place

* fix test
2025-11-12 15:52:04 +01:00
Jojii
f6b715bd62 Metrics for snapshots (#7497)
* Add atomic counter for running snapshots

* Refactor collection telemetry + export prometheus metric

* Handle collection in ToC + current recovery measurements

* Fix openapi tests

* Fix tests

* Add snapshot metrics for streaming and partial snapshots.

* Fix typo in metrics name

* Adjust metrics names

---------

Co-authored-by: timvisee <tim@visee.me>
2025-11-11 15:00:11 +01:00
Andrey Vasnetsov
925d5127c8 remove init_from (#7454)
* wip: remove init_from

* remove init_from tests

* upd schema

* rm test
2025-10-29 17:37:02 +01:00
Andrey Vasnetsov
c1af720d0d remove lock api (#7449)
* remove lock api

* fix api count + remove tests

* remove another test

* remove more tests
2025-10-29 17:36:54 +01:00
Jojii
48d61f1719 Metrics vectors by name per collection (#7441)
* Add vector count per vector-name to metrics API

* Add to metrics API

* Improve TinyMap::get_or_insert_default and add tests

* Minor improvements

* Update openapi

* Review remarks

* Remove `collection_vectors` since it can be calculated manually
2025-10-29 17:00:53 +01:00
xzfc
95b4bbf978 Rename HnswConfig::{copy_vectors -> inline_storage} (#7389) 2025-10-13 10:08:06 +00:00
xzfc
780d406ff8 Add CollectionInfo::warnings field (#7293)
* refactor: swap DiffConfig parmeters

was: diff.update(&config)
now: config.update(diff)

* refactor: introduce DiffConfig::update_opt

* feat: add CollectionInfo::configuration_status field

* rename ConfigurationStatus to CollectionWarning
2025-09-29 18:17:03 +00:00
Andrey Vasnetsov
bff9cb1a50 fix strict mode validation for nested filters (#7264)
* fix strict mode validation for nested filters

* fix test
2025-09-16 12:03:54 +02:00
Arnaud Gourlay
e79100a2f2 Fix phrase match to not match with unknown tokens (#7252)
* Fix phrase match to not match with unknown tokens

* add tests

* spelling
2025-09-16 11:16:17 +02:00