Files
llm/docs/1c-sql-format-spec.md
T
2026-08-14 09:40:51 +03:00

1118 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 1C SQL Format Specification Draft
Date: 2026-06-20
The maintained evidence log for saved-state encoding, extension overlays,
Configurator reload behaviour, and failed protocol paths is split by topic in
[`docs/1c-sql-protocol/`](1c-sql-protocol/README.md). This specification keeps
only universal format rules.
This document describes universal 1C SQL storage rules observed and verified so
far. It must not contain knowledge about a particular infobase object such as
`АвансовыйОтчет`, except as test evidence in a separate report.
## Scope
The goal is a parser that understands 1C metadata storage, then applies that
understanding to any concrete infobase.
The parser should know:
- where metadata containers live in SQL;
- how to decode metadata payloads;
- how to read DBNames storage records;
- how to follow extension CAS manifests;
- how to map metadata objects and attributes to physical data tables/columns.
The parser should not hardcode:
- concrete configuration object names;
- concrete GUIDs from one customer base;
- physical table numbers from one infobase.
## SQL Containers
Observed top-level SQL containers:
- `Config`
- `ConfigSave`
- `ConfigCAS`
- `ConfigCASSave`
- `Params`
- `_ExtensionsInfo`
Current interpretation:
- `Config` stores direct metadata payloads for the main configuration.
- `ConfigSave` stores saved-but-not-applied configuration state when present.
- `ConfigCAS` stores content-addressed payload files.
- `ConfigCASSave` is the saved-state counterpart when present.
- `Params` stores platform metadata maps such as `DBNames`.
- `_ExtensionsInfo` stores extension registry rows and extension root package
pointers.
## Payload Encoding
Observed direct metadata payloads:
```text
SQL BinaryData -> raw deflate -> UTF-8 text with optional BOM -> brace tree
```
Known compression envelopes to try:
1. raw deflate
2. zlib
3. gzip
4. none
Known text encodings to try after decompression:
1. UTF-8 with BOM
2. UTF-8
3. UTF-16LE
4. UTF-16BE
5. CP1251
If UTF-8 BOM is present, it must take priority over heuristic encoding scores.
## Brace Tree Grammar
The decoded metadata text is a nested brace format:
```text
value = list | string | atom
list = "{" [value ("," value)*] "}"
string = '"' text-with-doubled-quotes '"'
atom = non-space text until one of "{", "}", ",", ":"
sequence = value+
```
The parser must preserve generic structure before assigning semantic names.
Generic node examples:
```json
{"type": "atom", "value": "1"}
{"type": "string", "value": "ru"}
{"type": "list", "items": [...]}
```
## DBNames
`Params/DBNames*` is the platform-maintained map from metadata/storage GUIDs to
storage roles and SQL numeric suffixes.
Observed decoded shape:
```text
{ root_number,
{ declared_count,
{ guid, storage_role, sql_number },
...
}
}
```
Parser output:
```json
{
"guid": "84e4c0c3-2a21-4aba-a7b0-f92b3f2878ec",
"storage_role": "Document",
"sql_number": 563,
"source": "DBNames"
}
```
Important rule: preserve `storage_role` exactly as stored by the platform. Do
not infer object kind from physical SQL table names.
Observed storage role families:
- table-like roles: `Document`, `Reference`, `Enum`, `InfoRg`, `AccumRg`,
`Const`, `Node`, `ScheduledJobs`;
- structural roles: `Fld`, `VT`, `LineNo`, `ByDims`, `ByField`,
`ByResource`, `ByProperty`.
Physical table/column names are derived after reading DBNames, for example:
```text
Document + 563 -> _Document563
Fld + 1234 -> _Fld1234
```
This mapping is a storage route, not a metadata object model by itself.
## Base Config Object Route
For main configuration metadata objects:
```text
Config.FileName = metadata_object_guid
Config.BinaryData = object payload
```
Observed object payload:
```text
root marker = 1
root list length = 8 or 9 for tested top-level objects
```
Object identity is inside the object body. Verified pattern:
```text
{1,0,<object_guid>}, "<name>", {1,"ru","<synonym>"}
```
This pattern has been observed for tested `Document`, `Catalog`, and
`InformationRegister` objects. The exact object-body position must be derived
from the tree and validated per object kind, not hardcoded from one sample.
## Extension Route
Extension metadata is not retrieved by `Config.FileName = object_guid` in the
tested cases. It is reached through the extension package path:
```text
_ExtensionsInfo
-> _ExtensionZippedInfo
-> root_cas_key
-> ConfigCAS[root_cas_key]
-> root manifest
-> object_id
-> cas_key
-> ConfigCAS[cas_key]
```
Observed `_ExtensionZippedInfo` binary structure:
```text
bytes 0..3 : marker
bytes 4..23 : root CAS SHA1 key
bytes 24.. : small extension metadata fragment
```
`ConfigCAS.FileName` equals `SHA1(BinaryData)` for the stored compressed bytes.
The root CAS file contains manifest pairs:
```text
object_id -> base64(20-byte sha1)
```
The decoded 20-byte SHA1 is the target ConfigCAS key.
`object_id` may be:
```text
<guid>
<guid>.0
<guid>.1
<guid>.2
<guid>.3
...
```
Suffix is only a part key. It is not a semantic label by itself.
## Extension/Object Part Payloads
Observed payload signatures:
- `root=1`: metadata object or child metadata object description;
- `root=4`: form payload structure;
- `root=5` with `#base64`: embedded help/text payload;
- `root=8` with `MOXCEL`: spreadsheet/template payload;
- `stream_headers`: binary/text stream container, often containing BSL module
payloads;
- `#base64`: embedded base64 data inside a brace tree.
Semantic assignment requires direct evidence:
- root shape;
- payload markers;
- declared stream sizes;
- exact SHA1 match with exported XML/BSL/HTML;
- normalized text match when byte-level line endings differ.
## Metadata Object Model
The universal parser should expose a model like:
```json
{
"guid": "...",
"kind": "Document",
"name": "...",
"synonyms": {"ru": "..."},
"attributes": [],
"tabular_sections": [],
"forms": [],
"templates": [],
"modules": [],
"storage": []
}
```
At the current stage only the following are accepted as proven fields:
- GUID;
- name;
- localized synonym where the identity block is found;
- generic root marker and root length;
- raw parsed tree;
- DBNames storage records;
- payload route.
Attributes, tabular sections, commands, forms, templates, and modules must be
added only after position-by-position validation against XML exports and SQL
routes.
## Position Validation Against XML
The parser must not globally assign section semantics from a single object
sample. The observed `root=1` payload shape is shared by multiple object kinds,
but section coordinates differ by kind.
Historical mechanical validation compared brace-tree positions with XML exports.
Those per-sample reports were removed from the current workspace; the stable
conclusions are kept here as format notes.
Observed examples:
- `Document`, 4 samples: XML-heavy top paths include `3`, `5`, and `1`.
- `Catalog`, 4 samples: XML-heavy top paths include `5`, `6`, and `1`.
- `InformationRegister`, 4 samples: XML-heavy top paths include `1`, `4`,
and `3`; path `7` appears in one tested sample.
- `ExchangePlan` extension sample: XML-heavy top paths include `3` and `5`.
These are evidence points, not final semantic names. A future object-kind parser
must attach names such as attributes or tabular sections only when the mapping is
confirmed across enough samples and matches XML structure.
Historical observed profiles with `min_support_ratio = 0.75`:
- `Document`: paths `3`, `5`, `1`.
- `Catalog`: paths `5`, `1`, `6`.
- `InformationRegister`: paths `1`, `4`, `3`.
The profile format keeps `semantic_status = unassigned`. It is a compact,
evidence-based section selector, not yet a semantic object-kind parser.
## XML Category Mapping
The next validation layer compares each observed profile section with structured
XML metadata categories. The XML extractor reads only stable metadata elements:
- the root object category, name, synonym, and UUID;
- generated types;
- standard attributes;
- child objects such as `Attribute`, `TabularSection`, `Form`, `Template`,
`Dimension`, and `Resource`.
The mapper scores a Config tree section against each XML category by exact name,
synonym, and UUID matches. This keeps the process mechanical: a section receives
a candidate semantic category only from direct evidence found in the XML export.
Historical evidence from 12 base objects, 4 per kind:
```text
Catalog path 1 -> Catalog 4/4
Catalog path 5 -> TabularSection 3/4 candidate
Catalog path 6 -> Attribute 4/4
Document path 1 -> Document 4/4
Document path 3 -> TabularSection 4/4
Document path 5 -> Attribute 4/4
InformationRegister path 1 -> InformationRegister 4/4
InformationRegister path 3 -> Resource 3/4 candidate
InformationRegister path 4 -> Dimension 4/4
```
Only 4/4 mappings are currently strong candidates for object-kind parser rules.
The 3/4 mappings remain candidate semantics until the missing or conflicting
sample is explained by object shape, optional sections, or a deeper path rule.
Follow-up parser projection reports:
- strict, only `support_ratio = 1.0`:
`reports/1c-sql/upo/structured-metadata-summary.json`
- candidate, `support_ratio >= 0.75`:
`reports/1c-sql/upo/structured-metadata-candidates-summary.json`
Strict projection currently extracts:
- `Document`: tabular sections from path `3`, attributes from path `5`;
- `Catalog`: attributes from path `6`;
- `InformationRegister`: dimensions from path `4`.
Candidate projection adds:
- `Catalog`: tabular sections from path `5`;
- `InformationRegister`: resources from path `3`.
The `Catalog path 5` 3/4 conflict is explained by nested content: the section
contains the tabular section object and may also contain attributes belonging to
that tabular section. A category scorer can therefore see more `Attribute`
matches than `TabularSection` matches, but the tabular section UUID is still
present in the section.
The `InformationRegister path 3` 3/4 result is explained by optional resources:
one tested register has no resource matches, while the other tested registers
map resources from the same path.
This means the next semantic parser step is not to add arbitrary conditions. It
is to represent section nesting explicitly:
```text
object section
-> child object list
-> child object identity
-> child attributes/properties
```
Until that nesting is decoded, the structured projection must keep evidence on
each item: source path, name hit, synonym hit, and UUID hit.
All-kind expansion was validated on 112 samples across 44 XML top object kinds.
The current retained summary used by SQL-read enrichment is
`reports/1c-sql/upo/structured-metadata-all-kinds-dbnames-summary.json`.
Examples of confirmed all-kind mappings:
```text
AccumulationRegister path 5 -> Resource
AccumulationRegister path 6 -> Attribute
AccumulationRegister path 7 -> Dimension
AccountingRegister path 3 -> Dimension
AccountingRegister path 5 -> Resource
AccountingRegister path 7 -> Attribute
BusinessProcess path 6 -> Attribute
Enum path 6 -> EnumValue
DocumentJournal path 4 -> Column
HTTPService path 3 -> URLTemplate
IntegrationService path 3 -> IntegrationServiceChannel
Report path 4 -> Attribute
Task path 5 -> Attribute
Task path 6 -> AddressingAttribute
Task path 8 -> Command
WebService path 3 -> Operation
```
For many metadata kinds, path `1` currently maps to the root object identity and
main properties. These mappings are useful for object identification but do not
yet expose child objects. Kinds with only root-object evidence still need deeper
payload analysis or related ConfigCAS/module payload routing.
## Child Record Boundaries
Many child-object sections use the same mechanical container shape:
```text
{ section_marker_guid, declared_count, record_0, record_1, ... }
```
The parser now detects these boundaries without assigning business semantics.
Semantic assignment is still evidence-based through XML category matching.
All 474 structured child items from the 112-sample batch are now attached to a
specific `record_path`:
```text
section_path = top-level section container
record_path = concrete child record inside that container
record_index = zero-based child record index
```
Examples:
```text
Enum value "Требуется" -> section 6, record 6.2
AccumulationRegister resource "Сумма" -> section 5, record 5.2
AccumulationRegister attribute "Подразделение" -> section 6, record 6.2
Document attribute "Автор" -> section 5, record 5.2
```
## DBNames Route Enrichment
Structured metadata reports can be enriched with `DBNames` routes:
- enrichment summary:
`reports/1c-sql/upo/structured-metadata-all-kinds-dbnames-summary.json`
- enriched reports:
`reports/1c-sql/upo/structured-metadata-all-kinds-dbnames/`
Current all-kind enrichment coverage:
```text
metadata items total: 474
items with DBNames routes: 420
object storage route count: 88
```
Observed child route coverage:
```text
attributes 338/341
tabular_sections 29/29
dimensions 19/19
resources 8/8
columns 17/17
addressing_attributes 4/4
accounting_flags 1/1
integration_service_channels 4/4
commands 0/4
enum_values 0/15
operations 0/15
url_templates 0/17
```
This is expected: persisted data fields have `DBNames` routes, while logical
metadata-only children such as enum values, web-service operations, commands,
and HTTP URL templates do not necessarily have independent SQL storage routes.
Known route families now classified:
```text
Fld -> field/column base name `_FldN`
Document, Reference, ... -> table names such as `_DocumentN`
AccumRg*, AccRg* -> register table families
VT, LineNo, ByField, ... -> structural routes needing parent context
IntegService*/IntegChannel* -> integration service tables
TurnoverDt/Ct/Turnover -> structural accounting-register routes
```
Column suffixes such as `_RRef`, `_TYPE`, `_RTRef`, and numeric/string value
columns are not inferred here. They require type decoding from the child record
and verification against the physical SQL table schema.
## Value Types And Simple Columns
The XML validation oracle now extracts value type information for child
metadata items:
```text
types = XML Type entries, for example xs:string or cfg:CatalogRef.Users
qualifiers = string length, number precision/scale, date fractions, etc.
is_composite = true when multiple Type entries are present
```
Validated simple column rules:
```text
single primitive type xs:string/xs:decimal/xs:boolean/xs:dateTime
+ DBNames Fld N
-> SQL column _FldN
single 1C reference type cfg:*Ref.Name
+ DBNames Fld N
-> SQL column _FldNRRef
```
Composite types are deliberately not guessed yet:
```text
multiple XML Type entries -> needs_composite_type_mapping
```
Validated composite column rules:
```text
multiple value types
-> _FldN_TYPE
multiple reference-capable value types
-> _FldN_TYPE
-> _FldN_RTRef
-> _FldN_RRRef
mixed string + reference value types
-> _FldN_TYPE
-> _FldN_S
-> _FldN_RRRef
```
`_RTRef` is present when the composite field needs to distinguish multiple
reference metadata types. When the composite type is a primitive/reference mix
with a single reference metadata type, `_TYPE` is enough to distinguish the
primitive vs reference branch, so `_RTRef` is not emitted.
Validated composite reference read rule:
```text
_FldN_TYPE -> branch marker
_FldN_RTRef -> DBNames SQL number of the selected reference target
_FldN_RRRef -> _IDRRef in the selected target table
```
For the current `Document.АвансовыйОтчет` smoke sample:
```text
Запасы.ЕдиницаИзмерения:
value types: cfg:CatalogRef.КлассификаторЕдиницИзмерения,
cfg:CatalogRef.ЕдиницыИзмерения
_TYPE: 08
_RTRef: 000000a6 -> decimal 166 -> DBNames Reference 166
target: Catalog.ЕдиницыИзмерения -> _Reference166
_RRRef: value _IDRRef in _Reference166
```
Composite reference smoke result:
- tool: `scripts/resolve_1c_sql_composite_references.ps1`;
- report: `reports/1c-sql/upo/sql-composite-reference-resolution-document-avansovy-otchet.json`;
- composite groups: `6`;
- resolved: `6`;
- target misses: `0`;
- row misses: `0`.
## SQL Composite Values
Composite value resolution is broader than composite reference resolution. A
single metadata field can have several physical columns:
```text
_FldN_TYPE -> type/branch marker
_FldN_S -> string branch
_FldN_N -> number branch
_FldN_L -> boolean branch
_FldN_T -> datetime branch
_FldN_RTRef -> reference target SQL number when multiple reference targets exist
_FldN_RRRef -> reference value id
```
The adapter currently selects the branch by observed physical values:
```text
non-zero RRRef -> reference
non-empty S/N/L/T -> primitive
otherwise -> empty_or_unknown
```
This intentionally avoids overclaiming the meaning of `_TYPE` until enough
non-empty examples are collected for every primitive/reference combination.
Current composite-value smoke result for `Document.АвансовыйОтчет`:
- tool: `scripts/resolve_1c_sql_composite_values.py`;
- report: `reports/1c-sql/upo/sql-composite-value-resolution-document-avansovy-otchet.json`;
- composite values: `11`;
- branch counts: `reference=6`, `empty_or_unknown=5`.
The only currently observed mixed primitive/reference metadata field in the
sample set is:
```text
BusinessProcess.ЗаявкаСотрудникаИзменитьЛичныеДанные.ДокументВид:
value types: xs:string, cfg:CatalogRef.ВидыДокументовФизическихЛиц
physical columns: _Fld46687_TYPE, _Fld46687_RRRef, _Fld46687_S
```
The target table has no rows in the current UPO SQL snapshot, so this remains a
structural rule without non-empty value observations.
## SQL Read View
`onec_sql_read_view.v1` is the first agent-facing read result. It combines:
```text
onec_sql_read_result.v1
+ onec_sql_reference_resolution.v1
+ onec_sql_composite_reference_resolution.v1
+ onec_sql_composite_value_resolution.v1
-> onec_sql_read_view.v1
```
The view keeps two row shapes:
```text
cells:
original physical-cell map from SQL aliases/columns, with resolved evidence
attached to the exact source cell when available
fields:
logical metadata_path groups, where multi-column fields such as composite
references are represented as one field with column evidence underneath
```
The view does not erase raw SQL evidence. It attaches presentations next to the
raw values:
```text
attributes.ВалютаДокумента -> resolved.presentation = "руб."
attributes.Организация -> resolved.presentation = "АЙЭФСИЭМ ГРУПП ООО"
Запасы.ЕдиницаИзмерения -> resolved.presentation = "шт" or "кг"
```
Every logical field also gets `display_value`, selected in this order:
```text
resolved.presentation
resolved.selected_presentation
composite primitive value
raw single-column value
null
```
For SQL date/time strings with the 1C SQL year offset, raw cell values are
preserved unchanged and only `display_value` is normalized by subtracting 2000
years from years `>= 3000`. Example: raw `4025-09-16T08:00:00.0000000` is
displayed as `2025-09-16T08:00:00.0000000`.
For one-byte SQL binary boolean values, raw cell values are also preserved
unchanged. `display_value` maps `00` to `false` and `01` to `true` only when
the field is a known standard boolean (`_Marked`, `_Posted`, `_Active`) or the
metadata value type contains `xs:boolean`.
## Enum Presentation
SQL enum tables store `_EnumOrder`, but agent-facing output needs enum value
names. The adapter builds:
```text
onec_enum_presentation_map.v1
```
from enum XML routes in the unified object route index:
```text
Enum.<Name>.ChildObjects.EnumValue order
-> value uuid
-> value name
-> ru synonym
```
When the same enum name exists in the base configuration and extensions, base
configuration XML has priority for the presentation map. Extension evidence is
not discarded from the route index; it is only not allowed to overwrite the
base enum presentation by name.
Current smoke examples:
```text
EnumRef.ТипыНалогообложенияНДС, _EnumOrder = 0
-> Облагается (с НДС)
EnumRef.ПоложениеРеквизитаНаФорме, _EnumOrder = 0
-> В шапке
```
Read views expose enum presentations as agent-facing display values. Example
shape:
```text
attributes.НалогообложениеНДС.display_value = Облагается (с НДС)
attributes.ПоложениеПроекта.display_value = В шапке
```
For declared-target misses with extension table hits, the view keeps both:
```text
resolved.found = false
resolved.selected_alternate = _Reference348X1 / other observed hit
resolved.selected_presentation = ...
```
The full read pipeline is available as one orchestrated command:
```text
scripts/read_1c_object_view.py
--kind <Kind>
--name <Name>
--summary <structured metadata DBNames batch summary>
--validation <predicted column validation>
--route-index <unified object route index>
--output-dir <run output directory>
```
For shells with uncertain Unicode handling, pass object names as UTF-8 base64:
```text
--name-b64 0JDQstCw0L3RgdC+0LLRi9C50J7RgtGH0LXRgg==
```
The orchestrator intentionally writes ASCII-only artifact file names. Russian
metadata names remain inside JSON payloads as data.
Current orchestrated smoke result:
- tool: `scripts/read_1c_object_view.py`;
- output directory: `reports/1c-sql/upo/object-read-runs`;
- object: `Document.АвансовыйОтчет`;
- final schema: `onec_sql_read_view.v1`;
- main rows: `5`;
- table parts: `5`;
- simple reference cells: `55`;
- composite reference groups: `6`;
- sample presentations: `attributes.Автор = Evgeniya.Matyushina`,
`Запасы.ЕдиницаИзмерения = шт`.
Validated tabular-section table rule:
```text
object primary table + DBNames VT N -> <object_table>_VTN
```
Only primary object tables are used for this prediction. Change tables and
auxiliary tables such as `ChngR`, `SInf`, `BPrPoints`, totals/options tables,
and similar companions are excluded from tabular-section table prediction.
Validated tabular-section attribute rule:
```text
TabularSection XML ChildObjects/Attribute
-> parent TabularSection UUID
-> nested SQL child record under the tabular section record
-> DBNames Fld N
-> parent tabular-section table column
```
The parser keeps both levels:
```text
tabular section:
section_path, record_path, VT/LineNo routes, physical table
tabular section attribute:
parent tabular section UUID/name
nested record_path
value type
Fld route
physical column in the parent tabular-section table
```
Physical column validation against the live SQL schema:
- script: `scripts/validate_1c_predicted_columns.ps1`
- report: `reports/1c-sql/upo/predicted-column-validation.json`
Current result:
```text
predicted columns: 695
found in SQL schema: 695
predicted tabular-section tables: 29
found in SQL schema: 29
```
Validated by kind:
```text
AccountingRegister columns 9/9
AccumulationRegister columns 25/25
BusinessProcess columns 136/136
Catalog columns 81/81, table parts 9/9
ChartOfAccounts columns 7/7, table parts 1/1
ChartOfCalculationTypes columns 27/27, table parts 2/2
Document columns 388/388, table parts 17/17
InformationRegister columns 3/3
Task columns 19/19
```
Validated by metadata field:
```text
attributes 361/361
tabular_section_attributes 304/304
dimensions 17/17
resources 8/8
addressing_attributes 4/4
accounting_flags 1/1
```
This gives a proven read route for simple persisted fields:
```text
metadata object GUID
-> Config payload
-> child section
-> child record
-> XML value type
-> DBNames Fld route
-> object DBNames table route
-> physical SQL column
```
## SQL Read Projection
The adapter can now build a read projection from enriched metadata:
- tool: `plugins/1c/tools/build_sql_read_projection.py`
- sample report:
`reports/1c-sql/upo/sql-read-projection-document-avansovy-otchet.json`
The projection contains:
```text
main_table
main_columns[]:
metadata_path
metadata_uuid
value_type
physical column
SQL type
stable SQL select alias
table_parts[]:
tabular section name/uuid
physical table
owner/line columns
nested tabular-section attribute columns
SELECT statement
```
SQL aliases are ASCII-only (`c001`, `c002`, ...). Human-readable Russian names
stay in JSON metadata fields. This avoids client encoding problems while keeping
the query result mechanically mappable back to metadata.
Smoke-tested generated SQL:
```text
Document.АвансовыйОтчет main table
SELECT FROM _Document563
result: 37 columns, 5 rows
Document.АвансовыйОтчет.Запасы tabular section
SELECT FROM _Document563_VT1614
result: 33 columns, 5 rows
```
This is the first end-to-end read chain:
```text
task asks for object data
-> metadata object identity
-> SQL storage table
-> metadata fields and tabular-section fields
-> physical SQL columns/tables
-> generated SELECT
-> result columns mapped back through projection JSON
```
Examples:
```text
Document.АвансовыйОтчет.Автор
cfg:CatalogRef.Пользователи + Fld 1584 -> _Document563._Fld1584RRef
Document.АвансовыйОтчет.Комментарий
xs:string + Fld 1587 -> _Document563._Fld1587
Document.АвансовыйОтчет.ДокументОснование
composite DocumentRef + Fld 1586
-> _Document563._Fld1586_TYPE
-> _Document563._Fld1586_RTRef
-> _Document563._Fld1586_RRRef
Document.АвансовыйОтчет.ВыданныеАвансы
VT 1610 -> _Document563_VT1610
Document.АвансовыйОтчет.ВыданныеАвансы.Документ
composite DocumentRef + Fld 1612
-> _Document563_VT1610._Fld1612_TYPE
-> _Document563_VT1610._Fld1612_RTRef
-> _Document563_VT1610._Fld1612_RRRef
Document.АвансовыйОтчет.ВыданныеАвансы.Сумма
xs:decimal(15,2) + Fld 1613
-> _Document563_VT1610._Fld1613
AccumulationRegister.АвансовыеПлатежиИностранцевПоНДФЛ.Сумма
xs:decimal(15,2) + Fld 45848 -> _AccumRg45843._Fld45848
```
## Metadata To Data Mapping
The target runtime chain is:
```text
metadata object -> DBNames storage role -> physical table
metadata field -> DBNames Fld/VT/LineNo records -> physical column/table part
```
Example shape, without hardcoded concrete values:
```text
Document object GUID
-> DBNames role Document, sql_number N
-> _DocumentN
Attribute GUID
-> DBNames role Fld, sql_number M
-> _FldM or _FldMRRef depending on stored value type
```
Implemented mechanical route helpers:
```text
Document + N -> _DocumentN
DocumentChngR + N -> _DocumentChngRN
Reference + N -> _ReferenceN
InfoRg + N -> _InfoRgN
Node + N -> _NodeN
Fld + N -> _FldN base column candidate
```
Structural roles such as `VT`, `LineNo`, and `ByDims` are not standalone
physical names in the parser core. They require parent object/section context.
The suffixes such as `RRef`, `_TYPE`, `_RTRef`, and version/deletion columns
must be specified from observed SQL schema and value type evidence before write
support is allowed.
## Safety Boundary
## SQL Read Result
The read path has three separate layers:
```text
structured metadata + DBNames + SQL schema
-> onec_sql_read_projection.v1
-> SQL SELECT execution
-> onec_sql_read_result.v1
```
`onec_sql_read_projection.v1` is the deterministic query plan. It contains the
main physical table, table-part physical tables, selected physical columns, SQL
aliases, and the metadata evidence for every selected column.
`onec_sql_read_result.v1` is the executed result. It must not add new metadata
guesses. Each returned cell is keyed as:
```text
<metadata_path>::<physical_column>
```
The cell body keeps:
- `alias`: generated SQL alias, for example `c006`;
- `column`: physical SQL column, for example `_Fld1584RRef`;
- `metadata_path`: logical metadata path, for example `attributes.Автор`;
- `metadata_name`, `metadata_uuid`, `metadata_field`;
- `value_type`: value type evidence from metadata;
- `sql_type`: SQL schema evidence;
- `value`: serialized SQL value.
Binary SQL values are serialized as:
```json
{"kind": "binary", "length": 16, "hex": "..."}
```
This keeps 1C references stable without pretending that a raw `RRef` is already
a resolved presentation. Reference resolution is a later layer that must use
metadata/DBNames type evidence to choose the target table and presentation
fields.
## SQL Reference Resolution
Reference resolution starts from `value_type`, not from the physical SQL column
name.
Observed single-reference mapping:
```text
cfg:CatalogRef.<Name> -> XML kind Catalog -> DBNames role Reference -> _ReferenceN
cfg:DocumentRef.<Name> -> XML kind Document -> DBNames role Document -> _DocumentN
cfg:EnumRef.<Name> -> XML kind Enum -> DBNames role Enum -> _EnumN
```
The declared target is selected through the unified object route index:
```text
value_type name -> XML top object -> object GUID -> DBNames storage role
```
The resolver then reads `_IDRRef` in the declared target table and returns only
available presentation columns, for example `_Code`, `_Description`,
`_Number`, `_Date_Time`, `_Posted`, `_Marked`, or `_EnumOrder`.
Extension-aware databases can contain physical table variants such as
`_Reference348X1`. Therefore a failed lookup in the declared target table is
not enough evidence that the value is invalid. The resolver records
`alternate_hits` across the same table family:
```text
Catalog -> _Reference%
Document -> _Document%
Enum -> _Enum%
```
The current smoke test found `attributes.Автор` declared as
`cfg:CatalogRef.Пользователи` with target `_Reference348`, while the same
`_IDRRef` also exists in `_Reference348X1`. The adapter must keep this evidence
explicit instead of silently replacing the declared target.
Current read support is implemented through `scripts/read_1c_object_view.py`.
The command must keep declared metadata targets, selected effective physical
tables, alternate extension hits, raw SQL values, and resolved presentations as
separate evidence fields.
SQL write support is out of scope until all of the following are proven:
- round-trip decode/encode for target payload type;
- validation against 1C Designer/Enterprise;
- backup and rollback workflow;
- saved-state handling for `ConfigSave`/`ConfigCASSave`;
- extension package rebuild validation.
## Implementation Status
This document is the SQL-format reference for the current adapter. The active
agent API is documented in `docs/1c-adapter-api-contract.md`, and the active
tool list is in `plugins/1c/tools/README.md`.
Current parser/library core:
- `plugins/1c/parser/payload.py`
- `plugins/1c/parser/dbnames.py`
- `plugins/1c/parser/extensions.py`
- `plugins/1c/parser/config_object.py`
- `plugins/1c/parser/storage.py`
- `plugins/1c/parser/config_sections.py`
- `plugins/1c/parser/xml_metadata.py`
- `plugins/1c/parser/structured_metadata.py`
- `plugins/1c/parser/child_records.py`
Current adapter-facing build/read tools:
- `scripts/extract_1c_dbnames.py`
- `scripts/build_1c_xml_guid_index.py`
- `scripts/compare_1c_sql_xml_guids.py`
- `scripts/build_1c_unified_object_route_index.py`
- `scripts/build_1c_metadata_from_resolved_object.py`
- `plugins/1c/tools/build_sql_read_projection.py`
- `scripts/validate_1c_predicted_columns.ps1`
- `scripts/execute_1c_sql_read_projection.ps1`
- `scripts/resolve_1c_sql_read_references.ps1`
- `scripts/resolve_1c_sql_composite_references.ps1`
- `scripts/resolve_1c_sql_composite_values.py`
- `scripts/build_1c_enum_presentation_map.py`
- `scripts/build_1c_sql_read_view.py`
- `scripts/read_1c_object_view.py`
Current required evidence artifacts:
- `reports/1c-sql/upo/dbnames.json`
- `reports/1c-sql/upo/xml-guid-index-combined.json`
- `reports/1c-sql/upo/sql-xml-guid-compare-combined.json`
- `reports/1c-sql/upo/unified-object-route-index.json`
- `reports/1c-sql/upo/structured-metadata-all-kinds-dbnames-summary.json`
- `reports/1c-sql/upo/predicted-column-validation.json`
- `reports/1c-sql/upo/enum-presentation-map.json`
The current adapter confirms:
- DBNames records are the authoritative bridge from metadata/storage GUIDs to
physical SQL table and column roles.
- XML and extension manifest evidence provide configurator-visible Russian
names, forms, modules, templates, and object relationships.
- `effective` metadata must apply active extension overlays before returning
attributes, forms, modules, or data views.
- SQL reads are allowed only through generated projections plus live
table-column validation.
- SQL writes to configuration/data storage remain outside the safe workflow.