Multics Technical Bulletin MTB-545, Rev. 01 DM: Relation Manager Functional Spec To: Distribution From: Lindsey Spratt and Lee Baldwin Date: 05/31/84 Subject: Data Management: Relation Manager Functional Specification 1 ABSTRACT The interface to the relation manager is described, with some discussion of how the interface is to be used and what the major implications of the interface are. The first revision includes the addition of new entry | points, and a general reorganization of the documentation. An | updated description of the specification structures can be found | in Appendix A, and the information structures used are described | in Appendix B. The entry points are now presented in | alphabetical order. | Comments should be sent to the author: via Multics Mail: Spratt.Multics on either MIT Multics or System M. via US Mail: Lindsey Spratt Honeywell Information Systems, inc. 4 Cambridge Center Cambridge, Massachusetts 02142 via telephone: (HVN) 261-9321, or (617) 492-9321 _________________________________________________________________ Multics project internal working documentation. Not to be reproduced or distributed outside the Multics project without the consent of the author or the author's management. CONTENTS Page 1 Abstract . . . . . . . . . . . . . . i 2 Introduction . . . . . . . . . . . . 1 3 Significant Changes Contained in Revision 1 . . . . . . . . . . . . . 1 4 Description of the Operations . . . 2 relation_manager_ . . . . . . . . . 3 Data management data types . . . 3 $close . . . . . . . . . . . . . 4 $create_cursor . . . . . . . . . 5 $create_index . . . . . . . . . 6 $create_relation . . . . . . . . 8 $create_subset_index (unimplemented) . . . . . . . . 10 $delete_tuple_by_id . . . . . . 11 $delete_tuples_by_id . . . . . . 12 $delete_tuples_by_spec . . . . . 13 $destroy_cursor . . . . . . . . 14 $destroy_index . . . . . . . . . 15 $destroy_relation_by_opening . . 16 $destroy_relation_by_path . . . 17 $get_count . . . . . . . . . . . 18 $get_cursor_area_ptr . . . . . . 19 $get_cursor_opening_id . . . . . 20 $get_description . . . . . . . . 21 $get_duplicate_key_count . . . . 22 $get_index_id . . . . . . . . . 23 $get_max_and_min_attributes (unimplemented) . . . . . . . . 24 $get_population . . . . . . . . 25 $get_record_collection_id . . . 26 $get_tuple_by_id . . . . . . . . 27 $get_tuple_id . . . . . . . . . 29 $get_tuples_and_ids . . . . . . 31 $get_tuple_array_and_ids . . . . 33 $get_tuple_array_by_id . . . . . 35 $get_tuple_array_by_spec . . . . 36 $get_tuples_by_id . . . . . . . 37 $get_tuples_by_spec . . . . . . 39 $modify_tuple_by_id . . . . . . 41 $modify_tuples_by_id . . . . . . 42 CONTENTS (cont) Page $modify_tuples_by_spec (unimplemented) . . . . . . . . 44 $open . . . . . . . . . . . . . 46 $put_tuple . . . . . . . . . . . 47 $put_tuples . . . . . . . . . . 48 $set_scope . . . . . . . . . . . 50 Appendix A - Specification Structures 52 The specification_head structure . 52 The subset_specification structure 52 The relation_search_specification structure . . . . . . . . . . . . 53 The relation_numeric_specification structure . . . . . . . . . . . . 56 Appendix B - Information Structures . 58 The element_id_list structure . . . 58 The file_create_info structure . . 58 The id_list structure . . . . . . . 59 The rel_creation_info structure . . 60 The relation_description structure 60 The relation_index_flags structure 62 The typed_vector structure . . . . 63 The typed_vector_array structure . 64 The typed_vector_list structure . . 65 Multics Technical Bulletin MTB-545, Rev. 01 DM: Relation Manager Functional Spec 2 INTRODUCTION The relation manager supports the organization of a relation and multiple indices. The tuples of the relation are stored as records in a record collection, managed by the record manager. Since there is one relation per file, the name of the relation is the name of the file in which it resides. At some point in the future this restriction may be loosened and the number of relations in a file may be increased. An extension would be necessary to the interface which allows distinguishing between different relations in the same file. If this is done, the situation of interest is to have tuples (or records) of different format (from different relations and therefore probably having different attributes) in the same record collection. This would provide the ability of placing related records from different relations in the same control interval. This, in turn, reduces reads from disk (of control intervals, the unit of disk reads) for certain patterns of reference of the database. The separate indices are implemented as physically distinct indices in the file of the relation. Initially, the only kind of indexing available will be the multi-field sorting index with a fixed format key and multiple data types. The keys in any index of the relation are constructed such that: 1) The indexed fields of the key correspond to attributes of the relation; 2) No two fields in a key correspond to the same attribute of the relation; 3) The key contains one field which is the record identifier of the tuple from which the data in the indexed fields of the key was extracted. The relation manager guarantees that the tuples and the indices do not become inconsistent, that is that the above three conditions are always true. There is only one kind of opening which is used with the relation manager, the file opening. The file opening is of the file which contains the relation. This assumes that there is one relation per file. Changing to support multiple relations is not a major perturbation, in terms of openings, as the argument which is now filled with a file opening id can be filled with a relation opening id. 3 SIGNIFICANT CHANGES CONTAINED IN REVISION 1 | The following entry points are new: | MTB-545, Rev. 01 Multics Technical Bulletin DM: Relation Manager Functional Spec | $get_cursor_area_ptr | $get_cursor_opening_id | $get_index__id | $get_record_collection_id | $get_tuple_array_and_ids | $get_tuple_array_by_id | $get_tuple_array_by_spec | The entry points which are currently unimplemented are | indicated as such. | The descriptions of the include files referenced by the | relation_manager_ have been updated to reflect the current | implementations. The following corrections have been made: | 1) The relation_search_specification structure is declared in | dm_relation_spec.incl.pl1. | 2) The flags structure used by the create_index entry point is | the relation_index_flags structure declared in | dm_relation_index_flags.incl.pl1. 4 DESCRIPTION OF THE OPERATIONS _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Name: relation_manager_ Manages tuples in a relation. A relation is comprised of a record collection containing all of the "tuples" of the relation and some number of index collections. An index has keys containing one or more fields, where each field is an attribute of the relation (field of the record collection). The index key fields may be in any order. There are several types of search specifications. A spec can be | numeric positioning or a search on values. It can be absolute, | done by starting at the beginning or end of the relation, or it | can be relative, done by starting at a position specified by a | cursor. The various structures used are described in Appendix A. | A number of the entries of the relation_manager_ accept or return data in the form of a simple_typed_vector, a general_typed_vector, a typed_vector_list, a typed_vector_array, | or an element_id_list structure. The include files for these | structures are described in Appendix B. | Data management data types There are several data types supported in the relation_manager_ module. They are specified using Multics standard descriptor structures. The supported data types are: Real binary - data types 1 through 4 Complex binary - data types 5 through 8 Real decimal - data types 9 and 10 Complex decimal - data types 11 and 12 Strings - data types 19 through 22 Unsigned real binary - data types 33 and 34 Real decimal - data types 43 and 44 Complex decimal - data types 45 and 46 All data must be scalar (i.e., arrays are not supported). Both aligned and unaligned data is valid. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$close Decrements the count of openings for this relation in this process by one. If the count goes to zero, the file in which the relation resides is closed and any storage associated with the opening is freed. Usage dcl relation_manager_$close entry (bit(36) aligned, fixed bin(35)); call relation_manager_$close (rel_opening_id, code); where: rel_opening_id (Input) is the opening identifier for the relation which is to be closed. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$create_cursor Allocates a relation cursor in the work_area. The cursor is to be used in subsequent calls to other relation_manager_ entries to identify the relation on which to operate and to hold a position in a relation. The position held by a relation_cursor is only valid for repeated uses of the same relation specification. The caller is responsible for destroying the cursor by calling the destroy_cursor operation or by releasing the area in which the cursor is allocated. Usage dcl relation_manager_$create_cursor entry (bit(36) aligned, ptr, ptr, fixed bin(35)); call relation_manager_$create_cursor (rel_opening_id, work_area_ptr, relation_cursor_ptr, code); where: rel_opening_id (Input) is the opening identifier of the relation. work_area_ptr (Input) is a pointer to an extensible area in which to allocate the cursor. The area must also be a freeing area, i.e., defined with the no_freeing flag off. relation_cursor_ptr (Output) is a pointer to the relation_cursor allocated by this operation. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$create_index Creates an index for a relation using a specified set of the relation's attributes. The attribute identifiers are given in the order in which they are to appear in the indexed fields of the key of the index being created. If the relation contains any tuples when this operation is invoked, then all of the tuples of the relation are processed and keys for each are put into the index. It is possible to invoke this operation such that it simply returns an error in this case, instead of creating and filling the new index. In any event, it is never the case that there exists a tuple in a relation which is not indexed in all of the indices defined for that relation. Usage dcl relation_manager_$create_index entry (bit(36) aligned, ptr, bit(36) aligned, fixed bin(17), bit(36) aligned, fixed bin(35)); call relation_manager_$create_index (rel_opening_id, id_list_ptr, flags, style, index_collection_id, code); where: rel_opening_id (Input) is the opening identifier of the relation. id_list_ptr (Input) is a pointer to an id_list structure which contains an array of the attribute identifiers to be placed in the index. The order in which the attribute identifiers are given is the same order that the attributes will appear in the index key. The identifier of an attribute is the position of the attribute in the create_relation operation's | typed_vector_array.dimension_table. flags (Input) | is a structure containing bits for controlling the creation of | the index. It is declared in | dm_relation_index_flags.incl.pl1. (See Appendix B). style (Input) is the style of index management to be used for this index. The defined styles are: "multi-field sorting" (1) and "multi-field non-sorting" (2). Currently, only style 1 is supported. Style 2 will be a hash index. index_collection_id (Output) _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ is the identifier assigned by index_manager_ when called by relation_manager_ to create the index. Only the index manager should ever have need to do this directly. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$create_relation | Creates and opens a relation in a specified file. The attributes which make up tuples of the relation are specified at this time. No indices are created, these are created using the "create_index" operation. Usage dcl relation_manager_$create_relation entry (char(*), char(*), ptr, ptr, bit(36) aligned, bit(36) aligned, fixed bin(35)); call relation_manager_$create_relation (rel_dir, rel_name, rel_creation_info_ptr, typed_vector_array_ptr, rel_opening_id, record_collection_id, code); where: rel_dir (Input) is the directory in which to create the relation. rel_name (Input) is the name of the relation to be created. rel_creation_info_ptr (Input) | is a pointer to the rel_creation_info structure (declared in | dm_rel_creation_info.incl.pl1) which determines the attributes | of the file being created, as well as the method used for | storing it. typed_vector_array_ptr (Input) is a pointer to a typed_vector_array structure. This structure contains a dimension_table sub-structure, which is an array of descriptions of attributes. Each entry in the array contains a name field (the name of the attribute) and a descriptor_ptr field (a pointer to a Multics descriptor). The name field is the name of each attribute; the descriptor_ptr defines the data type of each attribute. The rest of the typed_vector_array is currently not used. rel_opening_id (Output) is the opening identifier of the relation. record_collection_id (Output) is the collection identifier for the record collection, which holds the data of the tuples, in contrast to the index collections which index the data in the tuples. Although no indices are created at this time, the record collection is _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ created. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$create_subset_index (unimplemented) Creates an index containing the identifiers of the tuples which satisfy the search specification as a subset. This index is for use in the subsets portion of the specification. The keys in this index are composed of a single field, the tuple identifier. Usage dcl relation_manager_$create_subset_index entry (ptr, ptr, bit(36) aligned, ptr, bit(36) aligned, fixed bin(35)); call relation_manager_$create_subset_index (relation_cursor_ptr, specification_ptr, subset_file_opening_id, id_list_ptr, subset_index_id, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. specification_ptr (Input) is a pointer to a specification. subset_file_opening_id (Input) is the file in which the subset index is to be placed. id_list_ptr (Input) is a pointer to an id_list structure which defines the relationship between the fields in the index from which the subset is being extracted and the fields of the keys of the subset index. id_list.id(N) is the identifier of the field in the "source" index which is associated with field N of the subset index. The id_list must specify at least one field to be extracted from the source index. subset_index_id (Output) is the index_id of the subset index created by this operation. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$delete_tuple_by_id Deletes the tuple identified by a tuple id and updates all indices for the relation to reflect its absence. Usage dcl relation_manager_$delete_tuple_by_id entry (ptr, bit(36) aligned, fixed bin(35)); call relation_manager_$delete_tuple_by_id | (relation_cursor_ptr, tuple_id, code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. tuple_id (Input) | is the identifier of the tuple to be deleted. | code (Output) is a standard system error code. It can be: dm_error_$tuple_not_found_id if the specified tuple is not present. Any other non-zero code may have left the relation inconsistent and should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$delete_tuples_by_id Deletes all of the tuples identified in a list of tuple ids and updates all indices for the relation to reflect their absence. Usage dcl relation_manager_$delete_tuples_by_id entry (ptr, ptr, fixed bin(35), fixed bin(35)); | call relation_manager_$delete_tuples_by_id | (relation_cursor_ptr, element_id_list_ptr, | number_of_tuples_processed, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. element_id_list_ptr (Input) is a pointer to an element_id_list structure which contains an array of identifiers of tuples to be deleted. | number_of_tuples_processed (Output) is the number of tuples that were deleted. code (Output) is a standard system error code. It can be: dm_error_$tuple_not_found_id if the specified tuple is not present. Any other non-zero code may have left the relation inconsistent and should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$delete_tuples_by_spec Deletes a set of tuples identified by a search specification and updates all of the indices for the relation to reflect their absence. Usage dcl relation_manager_$delete_tuples_by_spec entry (ptr, ptr, fixed bin(35), fixed bin(35)); call relation_manager_$delete_tuples_by_spec | (relation_cursor_ptr, specification_ptr, | number_of_tuples_processed, code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. specification_ptr (Input) is a pointer to a search specification structure. | number_of_tuples_processed (Output) is the number of tuples that were deleted. code (Output) is a standard system error code. It can be: dm_error_$invalid_cursor_position | if a relative specification is supplied but the cursor does not identify a valid tuple position. dm_error_$tuple_not_found if no tuples satisfied the specification constraints. Any other non-zero code may have left the relation inconsistent and should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$destroy_cursor Frees the storage occupied by a relation_cursor. This operation may not be necessary, depending on the application, as it may prove easier to just throw away the work_area. Usage dcl relation_manager_$destroy_cursor entry (ptr, ptr, fixed bin(35)); call relation_manager_$destroy_cursor (relation_cursor_ptr, work_area_ptr, code); where: relation_cursor_ptr (Input/Output) is a pointer to the cursor to be destroyed by this operation. The value is set to null on output. work_area_ptr (Input) is a pointer to the area in which the cursor is allocated. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$destroy_index Destroys an index associated with a particular relation. All of the space occupied by the index is freed. Usage dcl relation_manager_$destroy_index entry (bit(36) aligned, bit(36) aligned, fixed bin(35)); call relation_manager_$destroy_index (rel_opening_id, index_collection_id, code); where: rel_opening_id (Input) is the opening identifier of the relation associated with the index being destroyed. index_collection_id (Input) is the index_collection_id of the index being destroyed. code (Output) is a standard system error code. Notes Destroying an index makes all existing cursors for that index useless and the caller must not attempt to use them subsequent to index destruction, as the result of such a use is undefined. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$destroy_relation_by_opening Destroys a relation identified by a relation opening identifier. All of the storage associated with the relation is freed. Usage dcl relation_manager_$destroy_relation_by_opening entry (bit(36) aligned, fixed bin(35)); call relation_manager_$destroy_relation_by_opening (rel_opening_id, code); where: rel_opening_id (Input) is the opening identifier of the relation. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$destroy_relation_by_path Destroys a relation identified by a pathname. All of the storage | associated with the relation is freed. | Usage dcl relation_manager_$destroy_relation_by_path entry (char(*), char(*), fixed bin(35)); call relation_manager_$destroy_relation_by_path (rel_dir, rel_name, code); where: rel_dir (Input) is the directory of the relation to be destroyed. rel_name (Input) is the entry name of the relation to be destroyed. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_count Gets the count of an arbitrary set of tuples as defined by a specification and cursor. Usage dcl relation_manager_$get_count entry (ptr, ptr, fixed bin(35), fixed bin(35)); | call relation_manager_$get_count (relation_cursor_ptr, | specification_ptr, tuple_count, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. specification_ptr (Input) is a pointer to a specification structure. If null, the count of all tuples is returned. | tuple_count (Output) is the number of tuples which are identified by the specification and cursor. code (Output) is a standard system error code. It can be: | dm_error_$invalid_cursor_position if a relative specification is supplied but the cursor does not identify a valid tuple position. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_cursor_area_ptr | Returns a pointer to the area in which the cursor is allocated. | Usage | dcl relation_manager_$get_cursor_area_ptr entry (ptr) | returns (ptr); | area_ptr = relation_manager_$get_cursor_area_ptr | (relation_cursor_ptr); | where: | relation_cursor_ptr (Input) | is a pointer to a cursor for the relation. | area_ptr (Output) | is a pointer to the area in which the cursor is allocated. | _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ | Entry: relation_manager_$get_cursor_opening_id | Returns the opening identifier of the relation. | Usage | dcl relation_manager_$get_cursor_opening_id entry (ptr) | returns (bit(36) aligned); | rel_opening_id = relation_manager_$get_cursor_opening_id | (relation_cursor_ptr); | where: | relation_cursor_ptr (Input) | is a pointer to a cursor for the relation. | rel_opening_id (Output) | is the opening identifier of the relation. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_description Returns a description of the specified relation. The relation | must be open. | Usage dcl relation_manager_$get_description entry (bit(36) aligned, ptr, ptr, fixed bin(35)); call relation_manager_$get_description (rel_opening_id, | work_area_ptr, relation_description_ptr, code); | where: rel_opening_id (Input) is the opening identifier of the relation. work_area_ptr (Input) is a pointer to an area in which the relation_description is to be allocated. The area may be extensible. relation_description_ptr (Output) is a pointer to the relation_description structure, declared | in dm_relation_description.incl.pl1. | code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_duplicate_key_count Gets the number of keys that have their first number_of_duplication_fields identical to some other key's same fields. Keys that satisfy that constraint for fewer than all fields are called "partial duplicates". Complete duplicates are not possible in an index managed through relation_manager_. Usage dcl relation_manager_$get_duplicate_key_count entry (ptr, bit(36) aligned, fixed bin(17), fixed bin(35), fixed bin(35)); | call relation_manager_$get_duplicate_key_count | (relation_cursor_ptr, index_collection_id, | number_of_duplication_fields, tuple_count, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. index_collection_id (Input) is the collection identifier of the index for which to obtain the count of duplicate keys. number_of_duplication_fields (Input) is the number of fields, starting with the first field, of keys to be checked for duplication. A value of -1 means that all fields are to be considered. | tuple_count (Output) is the number of keys found to be partial duplicates under the given constraints. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_index_id | Returns the identifier of the index created by the create_index | entry point. | Usage | dcl relation_manager_$get_index_id entry (ptr, ptr) returns | (bit(36) aligned); | index_id = relation_manager_$get_index_id | (relation_cursor_ptr, id_list_ptr); | where: | relation_cursor_ptr (Input) | is a pointer to a cursor in the relation. | id_list_ptr (Input) | is a pointer to an id_list structure which contains an array | of the attribute identifiers to be placed in the index. The | order in which the attribute identifiers are given is the same | order that the attributes will appear in the index key. The | identifier of an attribute is the position of the attribute in | the create_relation operation's | typed_vector_array.dimension_table. | index_id (Output) | is the identifier of the index. If no index in the relation | matches the id_list, a value of "0"b is returned. | _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_max_and_min_attributes (unimplemented) Gets the maximum value and the minimum value in each attribute specified over all of the tuples which satisfy the caller-provided specification and cursor. Usage dcl relation_manager_$get_max_and_min_attributes entry (ptr, ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_max_and_min_attributes (relation_cursor_ptr, specification_ptr, id_list_ptr, work_area_ptr, min_typed_vector_ptr, max_typed_vector_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. specification_ptr (Input) is a pointer to a specification structure which identifies the tuples. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes to be included in the operation. work_area_ptr (Input) is a pointer to an area (of any kind) in which the returned typed_vectors will be allocated. min_typed_vector_ptr (Output) is a pointer to a simple_typed_vector structure which contains the minimum values of the specified tuples for the attributes identified in the id_list. max_typed_vector_ptr (Output) is a pointer to a simple_typed_vector structure which contains the maximum values of the specified tuples for the attributes identified in the id_list. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_population Gets the number of tuples in the relation. This count is not guaranteed to be exact, but in almost all cases will be very close. The precision of the count is compromised in order to make the operation a fast one. If an exact count is required, use relation_manager_$get_count. Usage dcl relation_manager_$get_population entry (ptr, fixed bin(35), fixed bin(35)); call relation_manager_$get_population (relation_cursor_ptr, tuple_count, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. tuple_count (Output) is the number of tuples in the relation. This number is not guaranteed to be exact, but will generally be quite close. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ | Entry: relation_manager_$get_record_collection_id | Returns the identifier of the record collection. | Usage | dcl relation_manager_$get_record_collection_id entry (ptr) | returns (bit(36) aligned); | record_collection_id = | relation_manager_$get_record_collection_id | (relation_cursor_ptr); | where: | relation_cursor_ptr (Input) | is a pointer to a cursor in the relation. | record_collection_id (Output) | is the identifier of the record collection. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuple_by_id Gets the value of the tuple specified by a tuple id. Usage dcl relation_manager_$get_tuple_by_id entry (ptr, bit(36) aligned, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuple_by_id (relation_cursor_ptr, tuple_id, id_list_ptr, work_area_ptr, simple_typed_vector_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. tuple_id (Input) is a tuple identifier which specifies the tuple to be retrieved. id_list_ptr (Input) is a pointer to an id_list structure, specifying which attributes of the tuple are to be returned. work_area_ptr (Input) is a pointer to an area in which the simple_typed_vector containing the retrieved tuple is allocated. Only return data are allocated in this area. The return area may be of any type. simple_typed_vector_ptr (Input/Output) | is a pointer to a simple_typed_vector containing the specified tuple. It can specify a pre-allocated structure into which | the retrieved data is stored; otherwise this pointer should be | set to null on input in which case the structure will be | allocated by relation_manager_. The simple_typed_vector | structure has only the attributes specified in the id_list, and the attribute (or dimension) values are in the same order as in the id_list. If id_list_ptr is equal to null, the attributes are returned in the order in which attributes were specified when the relation was created. code (Output) is a standard system error code. It can be: _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ dm_error_$tuple_not_found_id if the specified tuple is not present. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuple_id Gets the identifiers of tuples which satisfy the caller-provided constraints. The constraints are satisfied by searching the indices and/or record collection identified in the specification. If an index search fails to satisfy all of the constraints in an and-group, the remaining constraints are satisfied by searching the record collection containing the actual tuples. Only the tuples which satisfied the index search are examined in this record collection search. This operation is identical to the "get_tuple_by_spec" operation except that a list of tuple identifiers is returned instead of a list of tuples (i.e. a list of values of tuples). Usage dcl relation_manager_$get_tuple_id entry (ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuple_id (relation_cursor_ptr, specification_ptr, caller_area_ptr, element_id_list_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple for which an id was retrieved. specification_ptr (Input) is a pointer to the specification structure which identifies the tuples. return_area_ptr (Input) is a pointer to an area in which the element_id_list may be allocated. element_id_list_ptr (Input/Output) Input may be null or a pointer to a pre-allocated element_id_list | structure. If a null value is supplied, element_id_list is allocated in the supplied return area. If non-null, element_id_list.number_of_elements is changed to the number of tuples found, and element_id_list.id is filled with the identifiers of the tuples found. It is not assumed that the value of element_id_list.number_of_elements on input represents an upper bound on the number of identifiers to return. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Output is a pointer to an element_id_list structure, containing a list of the tuple identifiers found by the search. code (Output) is a standard system error code. It can be: | dm_error_$invalid_cursor_position if a relative specification is supplied but the cursor does not identify a valid tuple position. dm_error_$tuple_not_found if no tuples satisfied the specification constraints. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuples_and_ids Gets the values and identifiers of tuples which satisfy a search | specification and returns them in a typed_vector_list. The | constraints are satisfied by searching the indices and/or record collection identified in the specification. If an index search fails to satisfy all of the constraints, the remaining constraints are satisfied by searching the record collection containing the actual tuples. Only the tuples which satisfy the index search are examined in this record collection search. Usage dcl relation_manager_$get_tuples_and_ids entry (ptr, ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuples_and_ids (relation_cursor_ptr, specification_ptr, id_list_ptr, caller_area_ptr, element_id_list_ptr, typed_vector_list_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple retrieved. specification_ptr (Input) is a pointer to a specification structure which identifies the tuples. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes of the tuples to be returned. The simple_typed_vector structures which contain the returned data have only the attributes specified in id_list, and the attribute (or dimension) values are in the same order as they are "named" in id_list. caller_area_ptr (Input) is a pointer to an area in which the typed_vector_list of retrieved tuples will be placed. This can be any type of area. An extensible, non-freeing area allows for the most data and the fastest allocation scheme. element_id_list_ptr (Input/Output) Input may be null or a pointer to a pre-allocated element_id_list | _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ structure. If a null value is supplied, element_id_list is allocated in the supplied return area. If non-null, element_id_list.number_of_elements is changed to the number of tuples found, and element_id_list.id is filled with the identifiers of the tuples found. It is not assumed that the value of element_id_list.number_of_elements on input represents an upper bound on the number of identifiers to return. Output is a pointer to an element_id_list structure containing a list of the tuple identifiers found by the search. | typed_vector_list_ptr (Input/Output) | Input | specifies a pre-allocated typed_vector_list into which the | retrieved data is stored; otherwise this pointer should be | set to null on input in which case it will be allocated by | the relation_manager_. | Output | is a pointer to the typed_vector_list structure containing | pointers to simple_typed_vectors which represent the | returned tuples. code (Output) is a standard system error code. It can be: | dm_error_$invalid_cursor_position if a relative specification is supplied but the cursor does not identify a valid tuple position. dm_error_$tuple_not_found if no tuples satisfied the specification constraints. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuple_array_and_ids Gets the values and identifiers of tuples which satisfy a search specification and returns them in a typed_vector_array. Usage dcl relation_manager_$get_tuple_array_and_ids entry (ptr, ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuple_array_and_ids (relation_cursor_ptr, specification_ptr, id_list_ptr, caller_area_ptr, element_id_list_ptr, typed_vector_array_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple for which an id was retrieved. specification_ptr (Input) is a pointer to a specification structure which identifies the tuples. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes of the tuples to be returned. caller_area_ptr (Input) is a pointer to an area in which the typed_vector_array of retrieved tuples will be placed. element_id_list_ptr (Input/Output) Input may be null or a pointer to a pre-allocated element_id_list structure. If a null value is supplied, element_id_list is allocated in the supplied return area. If non-null, element_id_list.number_of_elements is changed to the number of tuples found, and element_id_list.id is filled with the identifiers of the tuples found. It is not assumed that the value of element_id_list.number_of_elements on input represents an upper bound on the number of identifiers to return. Output is a pointer to an element_id_list structure containing a list of the tuple identifiers found by the search. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ typed_vector_array_ptr (Input/Output) Input specifies a pre-allocated typed_vector_array into which the retrieved data is stored; otherwise this pointer should be set to null on input in which case it will be allocated by the relation_manager_. Output is a pointer to the typed_vector_array structure containing the retrieved tuples. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuple_array_by_id Gets the values of tuples identified in a list of tuple ids and returns them in a typed_vector_array. Usage dcl relation_manager_$get_tuple_array_by_id entry (ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuple_array_by_id (relation_cursor_ptr, element_id_list_ptr, id_list_ptr, work_area_ptr, typed_vector_array_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple for which an id was retrieved. element_id_list_ptr (Input) is a pointer to an element_id_list structure, containing a list of tuple identifiers to be retrieved. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes of the tuples to be returned. work_area_ptr (Input) is a pointer to an area in which the typed_vector_array of retrieved tuples will be placed. typed_vector_array_ptr (Input/Output) Input specifies a pre-allocated typed_vector_array into which the retrieved data is stored; otherwise this pointer should be set to null on input in which case it will be allocated by the relation_manager_. Output is a pointer to the typed_vector_array structure containing the retrieved tuples. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuple_array_by_spec Gets the values of the tuples identified by a search specification and returns them in a typed_vector_array structure. Usage dcl relation_manager_$get_tuple_array_by_spec entry (ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuple_array_by_spec (relation_cursor_ptr, specification_ptr, id_list_ptr, caller_area_ptr, typed_vector_array_ptr, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple for which an id was retrieved. specification_ptr (Input) is a pointer to a specification structure which identifies the tuples. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes of the tuples to be returned. caller_area_ptr (Input) is a pointer to an area in which the typed_vector_array of retrieved tuples will be placed. typed_vector_array_ptr (Input/Output) Input specifies a pre-allocated typed_vector_array into which the retrieved data is stored; otherwise this pointer should be set to null on input in which case it will be allocated by the relation_manager_. Output is a pointer to the typed_vector_array structure containing the retrieved tuples. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuples_by_id Gets the values of the tuples identified in a list of tuple ids and returns them in a typed_vector_list. | Usage dcl relation_manager_$get_tuples_by_id entry (ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuples_by_id | (relation_cursor_ptr, element_id_list_ptr, id_list_ptr, | work_area_ptr, typed_vector_list_ptr, code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. element_id_list_ptr (Input) is a pointer to an element_id_list structure which specifies the tuples to be retrieved. id_list_ptr (Input) is a pointer to an id_list structure specifying which attributes are to be returned of the tuples identified in the element_id_list. The simple_typed_vector structures which contain the returned data have only the attributes specified in the id_list, and the attribute (or dimension) values are in the same order as in the id_list. work_area_ptr (Input) is a pointer to an area in which the typed_vector_list containing all of the retrieved tuples is allocated. Only returned data are allocated in this area. The return area may be of any type. typed_vector_list_ptr (Input) | is a pointer to a typed_vector_list structure containing pointers to simple_typed_vectors which represent the returned tuples. The structure must be pre-allocated by the caller and | contain the same number of vectors as identifiers in the | element_id_list. | code (Output) is a standard system error code. It can be: _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ dm_error_$tuple_not_found_id if the specified tuple is not present. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$get_tuples_by_spec Gets the values of the tuples identified by a search specification and returns them in a typed_vector_list structure. | The constraints are satisfied by searching the indices and/or the record collection identified in the specification. If an index search fails to satisfy all of the constraints in an and-group, the remaining constraints are satisfied by searching the record collection containing the actual tuples. Only the tuples which satisfy the index search are examined in this record collection search. Usage dcl relation_manager_$get_tuples_by_spec entry (ptr, ptr, ptr, ptr, ptr, fixed bin(35)); call relation_manager_$get_tuples_by_spec | (relation_cursor_ptr, specification_ptr, id_list_ptr, | caller_area_ptr, typed_vector_list_ptr, code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the current position of the cursor is at the last tuple retrieved. specification_ptr (Input) is a pointer to a specification structure which identifies the tuples. id_list_ptr (Input) is a pointer to an id_list structure identifying the attributes of the tuples to be returned. The simple_typed_vector structures which contain the returned data have only the attributes specified in id_list, and the attribute (or dimension) values are in the same order as they are "named" in id_list. caller_area_ptr (Input) | is a pointer to an area in which the typed_vector_list of retrieved tuples will be placed. This can be any type of area. An extensible, non-freeing area allows for the most data and the fastest allocation scheme. typed_vector_list_ptr (Input/Output) | Input | specifies a pre-allocated typed_vector_list into which the | _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ | retrieved data is stored; otherwise this pointer should be | set to null in which case the structure will be allocated | by the relation_manager_. | Output is a pointer to the typed_vector_list structure containing pointers to simple_typed_vectors which represent the returned tuples. code (Output) is a standard system error code. It can be: dm_error_$invalid_cursor if a relative specification is supplied but the cursor does not identify a valid tuple position. dm_error_$tuple_not_found if no tuples satisfied the specification constraints. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$modify_tuple_by_id Modifies a tuple identified by a tuple id and updates all indices | of the relation to reflect the new value of the tuple. | Usage dcl relation_manager_$modify_tuple_by_id entry (ptr, bit(36) aligned, ptr, fixed bin(35)); call relation_manager_$modify_tuple_by_id | (relation_cursor_ptr, tuple_id, typed_vector_ptr, | code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. tuple_id (Input) | is the identifier of the tuple to be modified. typed_vector_ptr (Input) is a pointer to either a simple or general typed_vector structure. The dimensions identified in the typed_vector structure are the attributes to be modified, and the values of the typed vector are the values to which the attributes are to be set. code (Output) is a standard system error code. It can be: dm_error_$tuple_not_found_id if the specified tuple is not present. dm_error_$key_duplication if the modification would cause duplicate keys in a unique index, and may have left an index out of synch with the collection of tuples. A call to relation_manager_$modify_tuple_by_id using the original value will succeed in restoring the value of the tuple and any modified indices. Any other non-zero code may have left the relation inconsistent and the operation should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$modify_tuples_by_id Sets the value of one or more attributes in all of the tuples identified by a list of tuple identifiers. For each index of the relation which contains one or more of the attributes being modified as part of its key format, the key associated with the old value(s) of the attributes is/are deleted and new keys are inserted to correspond with the new value for the attributes. If the modification causes the new tuple to have a duplicate key in a unique index, then no modification is made and dm_error_$key_duplication is returned in the code argument. Tuples which had been successfully modified up to this point are left modified. Usage dcl relation_manager_$modify_tuples_by_id entry (ptr, ptr, ptr, fixed bin(35), fixed bin(35)); call relation_manager_$modify_tuples_by_id (relation_cursor_ptr, element_id_list_ptr, typed_vector_ptr, number_of_tuples_processed, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. The current position is not changed by this operation. element_id_list_ptr (Input) is a pointer to a element_id_list structure which identifies the tuples to be modified. typed_vector_ptr (Input) is a pointer to either a simple or general typed_vector structure. The dimensions identified in the typed_vector structure are the attributes to be modified, and the values of the typed vector are the values to which the attributes are to be set. number_of_tuples_processed (Output) is the number of tuples that were modified. code (Output) is a standard system error code. It can be: dm_error_$tuple_not_found_id if the specified tuple is not present. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ dm_error_$key_duplication if the modification would cause duplicate keys in a unique index, and may have left an index out of synch with the collection of tuples. A call to relation_manager_$modify_tuple_by_id with the number_of_tuples_modified + 1'th element_id and its original value should resynch the relation. Any other non-zero code may have left the relation inconsistent and the operation should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$modify_tuples_by_spec (unimplemented) | Modifies the tuples identified by a search specification and | updates all indices of the relation to reflect the new values. If the modification causes the new tuple to have a duplicate key in a unique index, then no modification is made and dm_error_$key_duplication is returned in the code argument. Usage dcl relation_manager_$modify_tuples_by_spec entry (ptr, ptr, ptr, fixed bin(35), fixed bin(35)); call relation_manager_$modify_tuples_by_spec (relation_cursor_ptr, specification_ptr, typed_vector_ptr, number_of_tuples_processed, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. specification_ptr (Input) is a pointer to a search specification structure which identifies the tuples. typed_vector_ptr (Input) is a pointer to either a simple or general typed_vector. The ids of the dimensions in the vector must be the same as the identifiers for the attributes in the relation. number_of_tuples_processed (Output) is the number of tuples modified in carrying out the requested modification. code (Output) is a standard system error code. It can be: dm_error_$invalid_cursor if a relative specification is supplied but the cursor does not identify a valid tuple position. dm_error_$tuple_not_found if no tuples satisfied the specification constraints. dm_error_$key_duplication if the modification would cause duplicate keys in a unique index. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Any other non-zero code may have left the relation inconsistent and the operation should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$open Opens the specified relation. The caller must open a relation before accessing the relation. Only one relation opening can exist for a given relation per process. The file in which the relation resides is opened and opening information is extracted from the relation header. It is not an error to attempt to open an already opened relation; the existing opening identifier is returned and a count of the number of openings is incremented by one if such an attempt is made. Usage dcl relation_manager_$open entry (char(*), char(*), bit(36) aligned, fixed bin(35)); call relation_manager_$open (rel_dir, rel_entry, rel_opening_id, code); where: rel_dir (Input) is the pathname of the directory which contains the relation. rel_entry (Input) is the entryname of the relation. rel_opening_id (Output) is the relation opening identifier. code (Output) is a standard system error code. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$put_tuple Puts a tuple into a relation and updates all of the indices for that relation to reflect the presence of the new tuple. Usage dcl relation_manager_$put_tuple entry (ptr, ptr, bit(36) aligned, fixed bin(35)); call relation_manager_$put_tuple (relation_cursor_ptr, | typed_vector_ptr, tuple_id, code); | where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. typed_vector_ptr (Input) is a pointer to either a simple or general typed_vector structure which contains the value of the tuple to be stored. If a simple_typed_vector, the attribute values are assumed to be in the same order as specified in the "create_relation" operation's typed_vector_array. tuple_id (Output) | is the identifier of the tuple just inserted. code (Output) is a standard system error code. It can be: dm_error_$key_duplication if an index may have been left out of synch with the collection of tuples. A call to relation_manager_$delete_tuple_by_id with element_id should resynch the relation. Any other non-zero code may have left the relation inconsistent and the operation should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$put_tuples Puts a set of tuples into a relation and updates all of the indices for that relation to reflect the presence of the new tuples. Usage dcl relation_manager_$put_tuples entry (ptr, ptr, ptr, bit(36) aligned, fixed bin(35), fixed bin(35)); call relation_manager_$put_tuples (relation_cursor_ptr, typed_vector_list_ptr, element_id_list_ptr, number_of_tuples_put, code); where: relation_cursor_ptr (Input) is a pointer to a cursor for the relation. After the operation, the cursor is left with no current position. typed_vector_list_ptr (Input) is a pointer to a typed_vector_list structure which contains pointers to simple_typed_vectors representing the new tuple values to be stored. The attribute values are assumed to be in the same order as specified in the "create_relation" operation's typed_vector_array. element_id_list_ptr (Input/Output) is a pointer to a element_id_list structure, which contains the identifiers of the tuples just inserted. This structure must be allocated by the caller to have the same number of entries as are in typed_vector_list. If an error is encountered, the first number_of_tuples_put element_ids returned were successfully put. number_of_tuples_put (Output) is the number of tuples successfully put. code (Output) is a standard system error code. It can be: dm_error_$key_duplication if an index may have been left out of synch with the collection of tuples. A call to relation_manager_$delete_tuple_by_id with element_id_list.id (number_of_tuples_put + 1) should resynch the relation. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Any other non-zero code may have left the relation inconsistent and the operation should be rolled back. _________________ _________________ relation_manager_ relation_manager_ _________________ _________________ Entry: relation_manager_$set_scope Advises the relation_manager_ what MRDS scope setting is in effect for a relation. If the relation is protected, this information is passed along to the file_manager_ where it is used to determine what automatic locks should be used. If the relation is unprotected, the relation_manager_ directly locks the entire relation before each operation and unlocks it after the operation. This scope setting is used as advice to determine what lock to use. In the case where a process has more than one opening for a single database, and more than one of these openings have active scope set on a relation, it is up to MRDS to determine the combined setting. This operation is to be used whenever the combined scope on a relation changes, whether scope is being set or being deleted. Usage dcl relation_manager_$set_scope entry (bit(36) aligned, bit(2) aligned, bit(2)aligned, fixed bin(35)); call relation_manager_$set_scope (rel_opening_id, this_process_permission, other_processes_permission, code); where: rel_opening_id (Input) is the opening identifier of the relation. this_process_permission (Input) are the operations permitted in this process. If the leftmost bit is on ("10"b or "11"b) read is permitted; if the rightmost is on ("01"b or "11"b) write is permitted. other_processes_permission (Input) are the operations permitted in other processes. See "Notes" below. code (Output) is a standard system error code. Notes The following relation level locks are used for the specified scope setting advices (R is "10"b; W is "01"b; RW is "11"b; N is "00"b): This process Other processes Relation level lock permission permission ------------ --------------- ------------------- R N Exclusive (X) R R Share (S) R W, RW Intend-share (IS) W, RW N Exclusive (X) W, RW R Share-intend-exclusive (SIX) W, RW W, RW Intend-exclusive (X) Appendix A - Specification Structures Searches are started with the tuple following the "current" tuple as identified by the cursor as either a key in an index or a record in a record collection. The following structures are used in specifying tuples. The specification_head structure The following structure is used in specifying keys. It is declared in the dm_specification_head.incl.pl1 include file: dcl 1 specification_head based (sh_ptr) aligned, 2 version fixed bin(35), 2 type fixed bin(17) unal, 2 pad bit(18) unal, 2 subset_specification_ptr ptr; where: version is the version of the structure. The current version is a static variable named SPECIFICATION_VERSION_4. type is the type of the specification. There are four types: absolute numeric positioning, relative numeric positioning, absolute (from the "root") searching, and relative (from the current position indicated by a cursor) searching. These constants are defined in dm_specification_head.incl.pl1. pad must be "0"b. subset_specification_ptr is a pointer to a subset_specification structure. This structure is used to constrain selected keys to either be members of a subset or not be members of a subset. The subset_specification structure Following is the structure to specify subset indices and their relation to a specification of keys. It is declared in dm_subset_specification.incl.pl1. dcl 1 subset_specification based (subset_specification_ptr), 2 version char (8), 2 number_of_subsets fixed bin, 2 subset (ss_number_of_subsets refer (subset_specification .number_of_subsets)), 3 id_list_ptr ptr, 3 is_member bit(1) unaligned, 3 pad bit(35) unaligned, 3 cursor_ptr ptr; where: version is the version of the structure. The version is given by the internal static constant SUBSET_SPECIFICATION_VERSION_1. number_of_subsets is the number of subsets used in defining the specification. Subsets may be used in either numeric or value, and absolute or relative positioning. subset.id_list_ptr is a pointer to an id_list structure which defines the relationship of the fields of the subset index to the index being searched. id_list.id(I) is the identifier of the field in the index being searched which is associated with the I'th field of the subset index. subset.is_member if on, indicates that keys which this specification identifies must be found in this subset. For a subset to have a (source index) key as a member, the subset index must contain as a key the data which is found in the attendant data fields of the source index key. This is a special case of the more general subset "membership" definition which allows the caller to define the way in which data from the source index is to match data in the subset index. This special case is useful for the relation manager. subset.pad must be "0"b. subset.cursor_ptr is a pointer to a cursor for the subset index. The relation_search_specification structure This structure is used to search for tuples based on the values of particular attributes. It is declared in | dm_relation_spec.incl.pl1. | | dcl 1 relation_search_specification aligned based (rss_ptr), 2 head like specification_head, 2 maximum_number_of_constraints fixed bin (17) unal, 2 number_of_and_groups fixed bin (17) unal, 2 flags unal, 3 return_unique_tuples bit (1) unal, 3 mbz bit (35) unal, 2 range, 3 type fixed bin (17), 3 size fixed bin (17), 2 and_group (rss_number_of_and_groups refer (relation_search_specification .number_of_and_groups)), 3 search_collection_id bit (36) aligned, 3 flags unal, 4 collection_id_supplied bit (1) unal, 4 mbz bit (17) unal, 3 number_of_constraints fixed bin (17) unal, 3 constraint (rss_maximum_number_of_constraints refer ( relation_search_specification .maximum_number_of_constraints)), 4 field_id fixed bin (17) unal, 4 operator_code fixed bin (17) unal, 4 value_field_id fixed bin (17) unal, 4 mbz bit (18) unal, 4 value_ptr ptr; where: maximum_number_of_constraints is the number of field specifications to be allocated for each and_group. number_of_and_groups is the number of and_groups used in the search specification. The elements satisfied by each and_group are joined by union to obtain the complete set to satisfy the search specification. flags.return_unique_tuples is a flag which indicates, if on, that no tuple can be selected more than once. It is possible for a tuple to satisfy the constraints of more than one and-group. flags.mbz is reserved for future use and must be "0"b. range.type is the type of range of the specified keys desired: 0 - all 1 - top 2 - bottom range.size is the size of the range. If the type is "all" (or 0), then the size is ignored. If the type is "top" and the value of size is N, then the highest N keys of the keys selected are returned. In the case of "bottom", the lowest N keys of the keys selected are returned. and_group.search_collection_id is the collection identifier of the index or record collection to use to satisfy the constraints of this and-group. and_group.flags.collection_id_supplied is a flag which indicates, if on, that and_group.search_collection_id actually contains a collection id. If this flag is off, relation_manager_ selects a collection to use to satisfy the constraints. and_group.flags.mbz is reserved for future use and must be "0"b. and_group.number_of_constraints is the number of constraints actually in use for this and_group. Each constraint of the and_group must be satisfied in order for an element to be a member of the and_group. and_group.constraint.field_id is the id for the field being constrained. and_group.constraint.operator_code is the relationship the value of the desired keys must have to the value specified in this constraint. The operator codes can be dealt with as either fixed binary number or as a bit string (which must be converted to a fixed binary number). When considered as a bit string the meaning of the bits are or'ed together. The right-most bits are given the following meaning: "00001"b - = (equals) "00010"b - > (greater than) "00100"b - ^ (not) "01000"b - regular expression match "10000"b - field may be absent An "absent" field always compares to false for any of the other four comparisons. If this bit is on, an "absent" field will compare "true" and a "present" field will compare false. Some combinations of operators "bits" are not defined to have any meaning, e.g. "regular expression match" or'ed with "greater than". The complete definition of the meanings of all of the combinations of the 5 right-most operator bits follows: 1 - "00001"b - = 2 - "00010"b - > 3 - "00011"b - >= 4 - "00100"b - ^ 5 - "00101"b - ^= (><) 6 - "00110"b - ^> (<=) 7 - "00111"b - ^>= (<) 8 - "01000"b - regular expression match 9 through 15 - undefined 16 - "10000"b - field is absent from key 17 - "10001"b - field is absent or = 18 - "10010"b - field is absent or > 19 - "10011"b - field is absent or >= 20 - "10100"b - field is not absent 21 - "10101"b - field is absent or ^> (<=) 22 - "10110"b - field is absent or ^= 23 - "10111"b - undefined 24 - "11000"b - if field is present, regular expression match 25 through 31 - undefined and_group.constraint.value_field_id if non-zero, is the identifier of a field, the value of which is to be compared with the value of the constraint.field_id field. This is used to specify a comparison of the values of two fields within a tuple. The value of constraint.value_ptr must be null. and_group.constraint.mbz is reserved for future use and must be "0"b. and_group.constraint.value_ptr if non-null, is a pointer to the value to be compared with the value of the constraint.field_id field. This is used to specify a comparison of the value of a field and a constant value. The value must be allocated according to the DM data types. The value of constraint.value_field_id must be zero. The relation_numeric_specification structure This structure is used when a search for tuples with a particular numeric position is to be done. It is declared in dm_relation_spec.incl.pl1. dcl 1 relation_numeric_specification based ( relation_numeric_specification_ptr), 2 head like specification_head, 2 collection_id bit (36) aligned, 2 range_size fixed bin (35), 2 position_number fixed bin (17) unal, 2 pad bit (18) unal; where: collection_id is the identifier of the collection (index or record collection) over which to position. A valid collection identifier must be supplied. range_size is the number of tuples to return. position_number is interpreted according to the absolute or relative nature of the specification. If absolute, it is the position_number'th key of the index to which the position is moved. If position_number is negative, the keys are counted backwards from the end of the index for position_number keys. If position_number is positive, the keys are counted forward from the beginning of the index. If the type is relative, it is the position_number'th key from the current position to which the position is moved. If position_number is negative, the position is moved backwards from the current position; if it is positive, it is moved forwards from the current position. If position_number moves the cursor beyond the index, i.e. it is either too large or too small, then the cursor is moved to the beginning or end of the index or record collection as appropriate and dm_error_$beginning_of_index or dm_error_$beginning_of_collection, or dm_error_$end_of_index or dm_error_$end_of_collection is returned. Appendix B - Information Structures The element_id_list structure Contains an array of "bit(36) aligned" identifiers to be used as record ids, tuple ids, key ids, or element ids. Its declaration follows, and it can be found in dm_element_id_list.incl.pl1. dcl 1 element_id_list aligned based (element_id_list_ptr), 2 version fixed bin(35), 2 number_of_ids fixed bin(17), 2 id (eil_number_of_ids refer (element_id_list.number_of_ids)) bit(36) aligned; where: version is the version of the structure, currently ELEMENT_ID_LIST_VERSION_1. number_of_ids is the number of identifiers. id is an array of element identifiers. The file_create_info structure | This structure describes the attributes of the file in which a | newly created relation will reside. It is found in the include | file dm_file_create_info.incl.pl1. dcl 1 file_create_info aligned based (file_create_info_ptr), 2 version bit (36), 2 ci_size_in_bytes fixed bin (35), 2 blocking_factor fixed bin, 2 protected bit unal, 2 no_concurrency bit unal, 2 no_rollback bit unal, 2 mbz_1 bit (33) unal, 2 mbz_2 (30) fixed bin (71); where: version is the current version of the structure. This must be set to FILE_CREATE_INFO_VERSION_1. ci_size_in_bytes is the control interval size of the new file in bytes. Currently, the only valid value for this parameter is 4096. blocking_factor is the number of control intervals in each segment. Currently, the only alternatives are 64 and 255. protected indiates, if on ("1"b), that access to the file must be on behalf of a running transaction. no_concurrency indicates, if on ("1"b), that Data Management System concurrency control is not to be used. no_rollback indicates, if on ("1"b), that before images are not to be taken when updating the file. mbz_1 must be "0"b. This is reserved for future use. mbz_2 must be 0. This is reserved for future use. The id_list structure The id_list structure contains an array of "fixed bin(17)" identifiers, which are used to identify attributes and fields. The declaration follows, and it is found in dm_id_list.incl.pl1. dcl 1 id_list aligned based (id_list_ptr), 2 version fixed bin(35), 2 number_of_ids fixed bin(17), 2 id (il_number_of_ids refer (id_list.number_of_ids)) fixed bin(17); where: version is the version of the structure, ID_LIST_VERSION_1. number_of_ids is the number of identifiers. id is an array of identifiers, used to identify attributes and fields. The rel_creation_info structure | This structure is used in the creation of a relation. It is | declared in dm_rel_creation_info.incl.pl1. | dcl 1 rel_creation_info aligned based ( rel_creation_info_ptr), 2 version fixed bin (35), 2 file_create_info_ptr ptr, 2 esm_info_ptr ptr, 2 cism_info_ptr ptr; where: version | is the version of the structure which is currently | REL_CREATION_INFO_VERSION_2. file_create_info_ptr is a pointer to a file_create_info structure (declared in dm_file_create_info.incl.pl1). This structure describes attributes of the file in which the relation will reside. If null, the described defaults are taken. esm_info_ptr is a pointer to a basic_esm_info structure. This structure is declared in the dm_cm_esm_info.incl.pl1 include file and is used to determine certain storage methods of the record | collection, namely the maximum length in bits of a tuple, whether tuples must be fixed-length, and whether tuples should | be threaded together. If a null pointer is supplied, | relation_manager_ figures the maximum length based on the | supplied descriptors. cism_info_ptr is a pointer to either a blocked_cism_info or unblocked_cism_info structure. Both are declared in the include file dm_cm_cism_info.incl.pl1. They specify the method of storing control intervals in the record collection. If cism_info_ptr is null, the unblocked method is assumed. The relation_description structure Following is the description of the relation_description structure found in the dm_relation_description.incl.pl1 include file: dcl 1 relation_description aligned based ( | relation_description_ptr), 2 version fixed bin (35), 2 maximum_number_of_attributes_per_index fixed bin (17) unal, 2 number_of_attributes fixed bin (17) unal, 2 number_of_indices fixed bin (17) unal, 2 maximum_attribute_name_length fixed bin (17) unal, 2 record_collection_id bit (36) aligned, 2 attribute (rd_number_of_attributes refer (relation_description .number_of_attributes)) 3 name char (rd_maximum_attribute_name_length refer (relation_description .maximum_attribute_name_length)) varying, 3 descriptor_ptr ptr, 2 index (rd_number_of_indices refer (relation_description .number_of_indices)), 3 collection_id bit (36) aligned, 3 style fixed bin (17) unal, | 3 number_of_attributes fixed bin (17) unal, | 3 flags, 4 is_unique bit (1) unal, 4 is_primary bit (1) unal, | 4 pad bit (34) unal, | 3 attribute (rd_maximum_number_of_attributes_per_index refer (relation_description .maximum_number_of_attributes_per_index)) fixed bin (17) unal; | where: version is the current version of the structure which must be set to RELATION_DESCRIPTION_VERSION_3. maximum_number_of_attributes_per_index is the maximum number of attributes per index and the extent of each relation_description.index.attribute array. number_of_attributes is the number of attributes in each tuple. number_of_indices is the number of indices defined for this relation. record_collection_id is the identifier of the record collection in which tuples are stored. attribute.name is the name of each attribute. Attribute names are specified when the relation is created. attribute.descriptor_ptr is a pointer to a Multics descriptor for each attribute. index.collection_id is the identifier of the index collection in which an index is stored. index.style is the style of index management employed by an index. index.number_of_attributes is the number of attributes per key in an index. The attributes correspond to fields in the key, with the key having one extra field for the tuple identifier. index.flags.is_unique is a flag which indicates, if on, that no two keys can have the same values for all attributes. index.flags.is_primary is a flag which indicates, if on, that this index is the primary index of the relation. index.flags.pad is reserved for future use, and must be "0"b. index.attribute is an array of indices into the attribute_descriptor_ptr array, defining the attributes which make up the key. The relation_index_flags structure This structure is used to control the creation of an index by the relation_manager_. It is declared in dm_relation_index_flags.incl.pl1. dcl 1 relation_index_flags aligned based (relation_index_flags_ptr), 2 relation_must_be_empty bit (1) unaligned, 2 index_is_clustering bit (1) unaligned, 2 index_is_unique bit (1) unaligned, 2 pad bit (33) unaligned; where: relation_must_be_empty indicates, if on, that there must be no data in the relation when this index is being created. index_is_clustering (not implemented) indicates, if on, that the index being created is to be used to control physical placement of tuples in the record collection. Tuples are stored physically in approximately the same order as the order maintained by the index. The order is not exact because scenarios exist where holding rigidly to the order would cause a wasteful use of space and performance degradation. There can only be one clustering index for a relation, and it need not be unique. If no clustering index is defined for a relation, tuples are stored in as close to chronological order as possible. index_is_unique indicates, if on, that no key in the index is a duplicate of another. The typed_vector structure There are two formats for the typed_vector, the simple_typed_vector and the general_typed_vector. Both are defined in vu_typed_vector.incl.pl1. In the simple_typed_vector there is only a pointer for each dimension value, no dimension identifier is provided. It can be used when all of the dimensions in a typed_vector_array are present in the typed_vector. The dimensions would be assumed to be in the order defined by the dimension_table of the typed_vector_array. In the general_typed_vector, any subset of the defined dimensions may be present, hence the dimension.identifier is required. dcl 1 simple_typed_vector based (simple_typed_vector_ptr), 2 type fixed bin (17) unal, 2 number_of_dimensions fixed bin (17) unal, 2 dimension (stv_number_of_dimensions refer (simple_typed_vector .number_of_dimensions)), 3 value_ptr ptr unal; dcl 1 general_typed_vector based (general_typed_vector_ptr), 2 type fixed bin (17) unal, 2 number_of_dimensions fixed bin (17) unal, 2 dimension (gtv_number_of_dimensions refer (general_typed_vector .number_of_dimensions)), 3 identifier fixed bin (17) unal, 3 pad bit (18) unal, 3 value_ptr ptr unal; where: type indicates the type of the vector structure. 2 indicates the general_typed_vector and 3 indicates the simple_typed_vector structure. number_of_dimensions is the number of dimensions present in the vector. dimension.identifier is the index in the dimension_table of the typed_vector_array of the dimension. dimension.pad must be "0"b. dimension.value_ptr is a pointer to the value of the dimension. The typed_vector_array structure The typed_vector_array structure (in vu_typed_vector_array.incl.pl1) is: dcl 1 typed_vector_array based (typed_vector_array_ptr) aligned, 2 version fixed bin (35), 2 number_of_dimensions fixed bin (17), 2 number_of_vectors fixed bin (17), 2 number_of_vector_slots fixed bin (17), 2 maximum_dimension_name_length fixed bin (17), 2 dimension_table (tva_number_of_dimensions refer (typed_vector_array .number_of_dimensions)), 3 name char ( tva_maximum_dimension_name_length refer (typed_vector_array .maximum_dimension_name_length)) varying, 3 descriptor_ptr ptr, 3 cv_to_print entry (ptr, ptr, ptr, fixed bin(35), char(*) varying, fixed bin(35)), 3 cv_to_typed entry (ptr, ptr, ptr, ptr, fixed bin(35)), 2 vector_slot (tva_number_of_vector_slots refer (typed_vector_array .number_of_vector_slots)) ptr; where: version is the version of this structure, currently TYPED_VECTOR_ARRAY_VERSION_2. number_of_dimensions is the number of dimensions in the dimension table. maximum_dimension_name_length is the maximum length of any of the dimensions named in the dimension table. number_of_vectors is the number of vector slots actually used to point at vectors. number_of_vector_slots is the number of vector slots allocated. dimension_table.name is the name of the dimension. dimension_table.descriptor_ptr is a pointer to standard Multics data type descriptor. dimension_table.cv_to_print is an entry for converting from typed format data to print format. dimension_table.cv_to_typed is an entry for converting from print format data to typed. vector_slot is a pointer to a typed_vector structure. The typed_vector_list structure The declaration and description of the typed_vector_list structure follows and can be found in the include file dm_typed_vector_list.incl.pl1. dcl 1 typed_vector_list aligned based (typed_vector_list_ptr), 2 version fixed bin (17), 2 maximum_number_of_vectors fixed bin (35), 2 number_of_vectors fixed bin (35), 2 pad fixed bin (35), 2 vector_ptr (tvl_maximum_number_of_vectors refer typed_vector_list .maximum_number_of_vectors) ptr; where: version is the version of the structure which is currently TYPED_VECTOR_LIST_VERSION_1, declared in the same include file. maximum_number_of_attributes is the extent of the array of vector_ptrs. number_of_vectors is the actual number of vector_ptrs present. pad is reserved for future use and must be 0. vector_ptr is an array of pointers to simple_typed_vector structures, which are declared in vu_typed_vector.incl.pl1.