diff --git a/doc/sql.extensions/README.schemas.md b/doc/sql.extensions/README.schemas.md index 8f8a25a31b7..e7593a00a06 100644 --- a/doc/sql.extensions/README.schemas.md +++ b/doc/sql.extensions/README.schemas.md @@ -76,6 +76,8 @@ you can reset the current search path to its initial configuration with the `ALT Nonexistent schemas can be included in the search path but are ignored during name resolution. +If `SYSTEM` is not included in the schema list, it is automatically added as the last schema in the search path. + The first existing schema in the search path is referred to as the **current schema** and is exclusively used in some operations. @@ -103,7 +105,7 @@ create or alter function F1 returns integer as begin end; grant create table to user USER1; ``` -For `ALTER`, `DROP`, and others statements, the system searches for the specified object across all schemas in the +For `ALTER`, `DROP`, and others statements, Firebird searches for the specified object across all schemas in the search path. The reference is bound to the first matching object found. If no matching object exists in any schema, an error is raised. @@ -133,8 +135,7 @@ In this case, the search path is used to locate `TABLE1`, `DOMAIN1`, and `TABLE2 For DDL statements, the search path operates similarly, but with a subtle difference. Once the object being created or modified is bound to a schema during statement preparation, the search path is implicitly and temporarily modified. -This adjustment sets the search path to the schema of the object. Additionally, if the `SYSTEM` schema was already -present in the search path, it is appended as the last schema. +This adjustment sets the search path to the schema of the object with `SYSTEM` added as the final schema in the path. ```sql create schema SCHEMA1; @@ -198,8 +199,8 @@ grant select on table SCHEMA1.TABLE1 to user USER2; ## The SYSTEM schema All system schema-bound objects (e.g., `RDB$*` and `MON$*`) are now created in a dedicated schema called `SYSTEM`. -The `SYSTEM` schema has a default `USAGE` permission granted to `PUBLIC` and is included in the default search path. -This ensures backward compatibility with previous Firebird versions. +The `SYSTEM` schema has a default `USAGE` permission granted to `PUBLIC` and is automatically included in the +search path. This ensures backward compatibility with previous Firebird versions. While the `SYSTEM` schema allows operations like index creation and manipulation of those indexes, it is otherwise locked for DDL changes. Modifying objects within the `SYSTEM` schema through DDL operations is strongly discouraged. @@ -265,6 +266,8 @@ schema exists, it returns `NULL`. SET SEARCH_PATH TO [, ]... ``` +If `SYSTEM` is not included in the schema list, it is automatically added as the last schema in the search path. + ### RDB$GET_CONTEXT #### CURRENT_SCHEMA (SYSTEM) @@ -626,8 +629,7 @@ slave side. This allows mapping database objects to a specific schema using a se ## System packages and functions Firebird includes system packages such as `RDB$TIME_ZONE_UTIL`, `RDB$PROFILER`, and others. These system packages -are now located in the `SYSTEM` schema. If the `SYSTEM` schema is not included in the search path, their usage -requires explicit qualification with `SYSTEM`, as with any other object bound to the `SYSTEM` schema. +are now located in the `SYSTEM` schema. In contrast, Firebird also provides non-packaged built-in functions like `RDB$GET_CONTEXT`, `ABS`, and `DATEDIFF`. These functions are not listed in the database metadata (`RDB$FUNCTIONS`) and neither require nor accept the diff --git a/src/common/classes/objects_array.h b/src/common/classes/objects_array.h index c7fb9f58a60..edab7f18f20 100644 --- a/src/common/classes/objects_array.h +++ b/src/common/classes/objects_array.h @@ -453,6 +453,12 @@ namespace Firebird return false; } + bool exist(const T& item) const + { + size_type pos; // ignored + return find(item, pos); + } + private: void add(const ObjectsArray& o) { diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index f1b8f15d739..5e58ce246b1 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -10412,8 +10412,18 @@ void SetSearchPathNode::execute(thread_db* tdbb, DsqlRequest* /*request*/, jrd_t auto newSearchPath = makeRef( FB_NEW_POOL(*attachment->att_pool) AnyRef>(*attachment->att_pool)); + bool hasSystem = false; + for (const auto& schema : *schemas) + { + if (schema == SYSTEM_SCHEMA) + hasSystem = true; + newSearchPath->add(schema); + } + + if (!hasSystem) + newSearchPath->add(SYSTEM_SCHEMA); attachment->att_schema_search_path = std::move(newSearchPath); } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 84deafb4179..b2bb9cf6329 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -7435,6 +7435,8 @@ void DatabaseOptions::get(const UCHAR* dpb, FB_SIZE_T dpb_length, bool& invalid_ case isc_dpb_search_path: getString(rdr, tempStr); MetaString::parseList(tempStr, dpb_schema_search_path); + if (!dpb_schema_search_path.exist(SYSTEM_SCHEMA)) + dpb_schema_search_path.add(SYSTEM_SCHEMA); break; case isc_dpb_blr_request_search_path: