Skip to content

Add SchemaView for namespace-isolated schema access #716

Description

@shirly121

Summary

Introduce SchemaView, a read-only logical view over the underlying Schema, to expose only vertex and edge types that belong to a specific schema namespace.

The underlying Schema should continue to store and manage all vertex and edge labels globally. SchemaView adds namespace-based filtering on top of it, so internal features and future user-facing multi-graph support can isolate schema objects without immediately changing the low-level schema storage model.

Motivation

NeuG needs a way to isolate schema entries that should not be visible in the normal user graph schema.

Primary use cases:

  1. Internal hidden vertex/edge types

    Some internal features, such as full-text search, may need auxiliary vertex or edge types to store index-related data. These types should reuse NeuG's existing schema and storage infrastructure, but they should not be visible or accessible from normal user queries.

  2. Future multi-graph support

    After validating the internal use case, the same abstraction can support user-facing logical schemas or multiple graphs. Users could create labels under different schema namespaces and query a specific namespace while keeping labels from other namespaces isolated.

Design

Add a SchemaView abstraction above Schema.

SchemaView owns no schema data. It maintains:

  • a const Schema* pointing to the underlying schema;
  • the current namespace name for this view.

The underlying Schema continues to store all labels across all namespaces and continues to provide mutation APIs by label name. Namespace isolation is implemented by SchemaView filtering query results.

For now, different namespaces must not use the same label name. This is a temporary limitation because the underlying Schema still uses label name as the unique storage key. Users and internal callers must guarantee label names are globally unique. Supporting duplicate label names across namespaces would require changing the underlying schema key from label to (namespace, label).

Proposed Interface

class SchemaView {
 public:
  SchemaView(const Schema* schema, std::string namespace_name);
  SchemaView(const Schema& schema, std::string namespace_name);

  const Schema& GetSchema() const;
  const std::string& GetNamespace() const;

  std::vector<std::shared_ptr<const VertexSchema>> GetVertexSchemas() const;
  std::vector<std::shared_ptr<const EdgeSchema>> GetEdgeSchemas() const;

  std::shared_ptr<const VertexSchema> GetVertexSchema(label_t label) const;
  std::shared_ptr<const VertexSchema> GetVertexSchema(
      const std::string& label) const;

  std::shared_ptr<const EdgeSchema> GetEdgeSchema(
      label_t src_label, label_t dst_label, label_t edge_label) const;
  std::shared_ptr<const EdgeSchema> GetEdgeSchema(
      const std::string& src_label,
      const std::string& dst_label,
      const std::string& edge_label) const;

  bool ContainsVertexLabel(label_t label) const;
  bool ContainsVertexLabel(const std::string& label) const;

  bool ContainsEdgeLabel(label_t label) const;
  bool ContainsEdgeLabel(const std::string& label) const;

  bool ContainsEdgeTriplet(
      label_t src_label, label_t dst_label, label_t edge_label) const;
  bool ContainsEdgeTriplet(
      const std::string& src_label,
      const std::string& dst_label,
      const std::string& edge_label) const;

  std::vector<label_t> GetVertexLabelIds() const;
  std::vector<label_t> GetEdgeLabelIds() const;

 private:
  void EnsureSchema() const;

  bool IsVertexInNamespace(label_t label) const;
  bool IsVertexInNamespace(const VertexSchema& schema) const;
  bool IsEdgeInNamespace(const EdgeSchema& schema) const;

  const Schema* schema_;
  std::string namespace_;
};

All Get* APIs must validate that returned schemas belong to the view namespace. They must not expose vertex or edge schemas from other namespaces.

Required Schema Changes

Add namespace metadata to schema entries and allow label creation APIs to specify it.

Schema::AddVertexLabel and Schema::AddEdgeLabel should accept a namespace parameter. If omitted, the namespace should default to "default".

class Schema {
 public:
  void AddVertexLabel(
      const std::string& label,
      const std::vector<DataType>& property_types,
      const std::vector<std::string>& property_names,
      const std::vector<std::tuple<DataType, std::string, size_t>>& primary_key,
      size_t max_vnum = static_cast<size_t>(1) << 32,
      const std::string& description = "",
      const std::vector<Value>& default_property_values = {},
      bool temporary = false,
      std::string namespace_name = "default");

  void AddEdgeLabel(
      const std::string& src_label,
      const std::string& dst_label,
      const std::string& edge_label,
      const std::vector<DataType>& properties,
      const std::vector<std::string>& prop_names,
      EdgeStrategy oe = EdgeStrategy::kMultiple,
      EdgeStrategy ie = EdgeStrategy::kMultiple,
      bool oe_mutable = true,
      bool ie_mutable = true,
      std::optional<std::string> sort_key_for_nbr = std::nullopt,
      const std::string& description = "",
      const std::vector<Value>& default_property_values = {},
      bool temporary = false,
      std::string namespace_name = "default");
};

Note: use namespace_name instead of namespace because namespace is a C++ keyword.

Required GraphInterface Changes

Propagate namespace through schema creation parameters:

  • Add namespace_name = "default" to CreateVertexTypeParam.
  • Add namespace_name = "default" to CreateEdgeTypeParam.
  • When full-text search creates internal vertex or edge types, explicitly set namespace_name = "fts" or another reserved internal namespace.

Acceptance Criteria

  • SchemaView can be constructed from a Schema and namespace name.
  • SchemaView returns only vertex schemas in the current namespace.
  • SchemaView returns only edge schemas in the current namespace.
  • Edge visibility should also ensure that the source and destination vertex labels are visible in the same namespace.
  • Contains* APIs return false for labels or edge triplets outside the current namespace.
  • Existing code paths that do not pass a namespace continue to behave as the default namespace.
  • Internal schema entries can be created under a non-default namespace and hidden from the default SchemaView.
  • Tests cover default namespace behavior, cross-namespace filtering, and hidden internal labels.

Metadata

Metadata

Assignees

Labels

compilerCompiler infrastructurestoreStorage layer

Projects

Status
In progress

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions