Имя: Пароль:
1C
 
Недокументированная функция _StrToId() и _IdToStr()
0 Torquader
 
10.04.09
19:38
Возник вопрос с кодированием данных в текстовые строки.
Вспомнил, что есть функции _StrToId() и _IdToStr(), но что-то возникли проблемы с пониманием результата.
Насколько я понял, _IdToStr() переводит число в 36-ричную систему ?
И 00000 всегда 0.
Далее, интересно, что _StrToId(-1) выдаёт какое-то значение, то есть отрицальность не проверяется ?
Ожидалось, что _IdToStr() переводит число в "систему без ноля", как например нумерация колонок в Excel, но, видимо, ожидания не оправдались ?
P.S. _StrToId("0000")=_StrToId("0") ???
2 КонецЦикла
 
10.04.09
19:48
Какой-то поток сознания...
Вот сам подумай 000 это число? Равно ли оно 0?
3 dk
 
10.04.09
19:49
_idtostr("15") =      F
_idtostr(15) =      F
_idtostr(0) =      0
_strtoid("F") = 15
_strtoid("f") = 0
----
думай, решай, есть ограничения на длину
4 Torquader
 
10.04.09
20:05
(2) я просто ожидал, что "000" != "00", но оказалось, что РАВНО.
Ограничения на длину там тоже странные - для целых положительных чисел ограничений нет.
Все символы, кроме 1-9 A-Z считаются, как 0.
Однако, _IdToStr(-1)=Z141Z3, а _StrToId("Z141Z3")=2118184959
удивляет то, что проверки на отрицательность аргумента нет.
5 Cthulhu
 
10.04.09
20:59
Указанные функции служат для преобразования предствлений Id объектов данных (10-тичное представление - это формат внутреннего представления, из которых составлено ЗначениеВСтрокуВнутр(<объект данных>); 36-ричное представление -- это формат, в котором внутренние представления хранятся в таблицах базы данных) и метаданных 1с -- а вовсе не для преобразоывания чисел.. поэтому ожидать от них того, что они будут корректно преобразовывать отрицательные числа -- извините, но глупо... (кстати в равной мере глупо ожидать от этих функций преодразования Id, превышающих некоторые "граничные")
6 Cthulhu
 
10.04.09
21:01
(3): ограничения на длину легко вычисляются: 10 и 6
7 orefkov
 
11.04.09
09:33
(0)
Искренне завидиую - имееть время докапываться, почему недокументированные фичи  1С ведут себя не так, как ты ожидал - мне бы так.
8 orefkov
 
11.04.09
10:12
Ладно уж, даю справку.
1. Всякий уважающий себя программист знает, что для 32-битных чисел в машинном виде -1 хранится точно также, как 0xFFFFFFFF (4294967295). Представление этого числа в 36ричной системе есть 1Z141Z3.
2. 1С для идшников используются только положительные знаковые целые (а не беззнаковые), то есть числа от 0 до 2147483647, то для их 36ричного представления отводится только 6 символов.

Таким образом видно, что эти функции заточены именно под п.2, то есть всегда выдают результат 6-символной строкой. Поэтому в п. 1 ведущая 1ца откидывается. Обратное преобразование 36ричного числа Z141Z3 и есть 2118184959.

Про "0000" и "0" даже не берусь пояснять.
Это либо дано понять сразу, либо не понять никогда.
9 ДенисЧ
 
11.04.09
10:15
(8) А вот философский вопрос... Если они отводят 6 знаков для ИД, то почему всё в базе лежит в char(9)...
10 Ковычки
 
11.04.09
10:18
(0) а как выглядят отрицательные значения к примеру в 16-и разрядной ?
11 orefkov
 
11.04.09
10:22
(9)
6 знаков идшник + 3 знака dbsign, код распределенной базы.

И кстати, для хранения идшников объектов метаданных (ну там вид справочника и тп) отводится только 4 символа, отсюда видно, что максимальный возможный идшник для объекта метаданных есть _strtoid("ZZZZ") = 1679615. Берегите конфу, не правьте метаданные слишком часто, а то их тупо не хватит :)
12 Torquader
 
14.04.09
22:12
А, кстати, об ИД-метаданных как раз вопрос и возник.
Как, не разбирая MD-файл, получить ИД-объекта метаданных и ИД-реквизита объекта.
Для справочника, например, можно ValueToStringInternal(GetEmptyValue("Reference."+Metadata.Reference(i).Identifier))
в получаемом наборе четвёртый параметр обозначает ID справочника.
А как получить ИД реквизита справочника ?

(5) Внутри в базе всё хранится в двоичном представлении, так как функция _StrToId выдаёт не строку, а число, а число хранится внутри машины в том формате, который удобнее машине, а вот когда мы его хотим увидеть, нам машина выводит его в десятичном формате.
Про _IdToStr меня поразило, что отрицательные числа переводятся не в 0, а также что _StrToId(_IdToStr(-1)) даёт число, которое никак на -1 не похоже, как его не переводи в 16 - мне стало интересно - почему так.

(11) А почему для хранения типа "Неопределённый" используется 23+3 байта ?
Я сколько ломал голову, так и не понял.

Кстати, ValueFromStringInternal("{""UU"",""""}"); роняет 1С моментально.
13 Torquader
 
14.04.09
22:14
(13) P.S. я пытаюсь написать систему логирования изменения объектов, которая будет "застрахована" от внесения изменений в конфигурацию, но пока получается только фигня.
14 Guk
 
14.04.09
22:15
(13) мне кажется ты придумываешь велосипед с трапециидальными колесами...
15 ДенисЧ
 
14.04.09
22:17
(13) надёжное логирование делается только через триггеры.
16 Torquader
 
15.04.09
16:56
(15) у меня семейство баз, причём разных, и не все даже 1С. Они работают вместе и обмениваются данными, при загрузке данных в 1С хочется, чтобы записывались данные об изменении определённых справочников, причём, если в конфигурации что-то поменяют, то система записи продолжала бы работать.
17 Ёпрст
 
гуру
15.04.09
17:00
>>>Берегите конфу, не правьте метаданные слишком часто, а то их тупо не хватит :)

Пять балов! :)
18 Mikeware
 
15.04.09
17:03
(12) Ты не поверишь, но ПолучитьПустоеЗначение(вид) как раз берет ид из мд
Для хранения нопределенного 23 потому, что тип+вид+ид.
19 romix
 
модератор
15.04.09
17:04
20 ДенисЧ
 
15.04.09
17:04
(16) Так сложно сделать автоматическую генерацию триггеров?
21 Torquader
 
15.04.09
17:16
(18) у меня как-то не получается 23:
ИД - 3+6=9
Вид=4 и откуда ещё 10 ?
У меня было подозрение, что максимальное число - это 19 цифр+знак+точка=21 и ещё один байт признак типа.
А там, если смотреть в DD получается 23+3 (насколько я понял, вторая часть - это органичение типа).
(19) спасибо за ссылки - именно это я и пытался проверить.
(20) у меня не SQL, а DBF-версия, причём часть из них вообще локальные однопользовательские, чтобы работали, когда отключат сеть - и весь этот зверинец, конечно, "глючит" так, что "мама не горюй".
Возникла идея - хранить ID не в 36-ричной, а в 95-ричной системе (127-32), так они меньше места занимают.
22 ДенисЧ
 
15.04.09
17:17
23 Ёпрст
 
гуру
15.04.09
17:19
24 Torquader
 
15.04.09
17:35
Больше всего радует 9 символов для хранения перечисления - обычно, элементы перечисления могут ограничиваться одним или двумя десятками.
25 Mikeware
 
15.04.09
17:37
(24) Общий принцип - если значение типизированное, то ид - 9 символов
26 Torquader
 
15.04.09
18:13
(25) понятно - просто обидно, когда куча места расходуется понапрасну.
Когда dbf размер файла быстро "накручивается" до двух гигов (особенно хороши строки неограниченной длины - все строки в одном файле)

А конфу "беречь" не за чем - если мы что-то правим, то новые ID расходуются только на новые объекты, а если мы что-то переименовываем или меняем тип, то ID не меняется.
27 Torquader
 
15.04.09
18:16
Вообще я уже понял, что или приводить всё в порядок, то есть ставить сервер и SQL, чтобы все "яйца в одной корзине" - просто и ясно, только вот денег это стоит.
28 Cthulhu
 
15.04.09
19:18
Mikeware, хорош пургу гнать...
1. Ид в виде внутреннего представдения объекта данных (ЛЮБОГО!) состоит из следующих частей:
Ид типа объекта (1 символ)
Ид вида объекта (10 символов)
Ид объекта (10 символов)
Код ИБ (3 символа)
ИТОГО: 24 символа.
2. Этот Ид (внутреннего представления) для хранения в данных(!) раскладывается на составные части и сохраняется (в общем случае, причем не всегда полностью) в разных полях(колонках таблиц данных): Ид вида объекта - 4 символа(см.(11)), Ид объекта - 6 символов и Код ИБ (3 символа).. Иды вида объекта и объекта данных получаются из соответствующих частей Ид-а внутр.представления посредством _IdToStr(..).
Отсюдова вывод: для оперирования объектами данных используется Ид из п.1 (единый собранный Ид фиксированной длины 24 символа); для поиска данных в таблицах данных нужно преобразовавать нужные составные чати этого Ид при помощи _IdToStr(..) и искать в соответствующих колонках таблиц данных (или писать в них))).
29 Torquader
 
15.04.09
21:17
Да, 24 уже похоже на правду, хотя, вид объекта, всё-таки, должен быть 9 символов (он вообще 4, но 4 хранят в поле 9, почему-то).
30 Torquader
 
15.04.09
21:31
А IdToStr сдалась на 2147483649 (0x80000001)
Не совпало i=2147483649 => ZIK0ZL => -2147483647
То есть Id для 1С это четырёхбайтовое целое со знаком, но при этом отрицательные значения не допускаются.
Удачи.
31 КонецЦикла
 
15.04.09
21:36
(28) Вот значение в самую длинную строку БД, char(23)
'B1  NA    3X001        '
Не поднимай пыль
32 Torquader
 
15.04.09
21:43
(31) он, видимо, считал не в упакованном виде, а в реальном (десятичные числа), только я как-то внутрь 1С настолько глубоко не лазил, чтобы увидеть, что там есть, а у функции ValueToStringInternal получается набор из семи параметров.
33 КонецЦикла
 
15.04.09
21:46
(32) Ну дык пора залазить :)
Внутри ж не десятичные, запаришься триггеровать
34 Torquader
 
15.04.09
21:48
(33) конечно, хорошая идея - запускать отладку процесса 1С и ловить момент изменения данных, чтобы записать его в файл. Но это уже слишком - тормоза будут - просто супер.
35 Sadovnikov
 
15.04.09
22:06
Нда. Веселая веточка...
36 Cthulhu
 
15.04.09
22:12
(31): не надо бабушку лохматить, PARENTVAL - это не совсем ID (хотя и "по мотивам").
В базе все реквизиты агрегатных типов определенного вида хранятся в виде свернутого в 36-ричное представление Ид объекта данных (длина 6) +Код ИБ (три символа); объекты агрегатных типов не указанного вида хранятся в том же виде плюс(слева, в начало) 4-символьное 36-ричное представление Ид вида объекта...
37 orefkov
 
15.04.09
23:10
(30)
Ты (8) что, невнимательно читал.
Я это вроде там еще разъяснял.

А 23 для неопределенных - ну видимо из расчета 'N' + 20 символов под число 19.9 + 2 про запас.
38 КонецЦикла
 
15.04.09
23:28
(36) Об этом в курсе, зачем пудришь автору голову десятичными вещицами?
23 знака - это неопределенный тип как таковой (не только парентвал), проще уже так и хранить чем все время триммить при соединениях и проч.
Если уж хранить неопределенное... а вообще я ниасилел что автор хочет сделать
39 Cthulhu
 
16.04.09
12:50
(38): "десятичные вещицы" - суть внутреннее представление, как раз ералаш с разбивкой Ид внутреннего представления по полям(колонкам) таблиц бОльшее пудрение; и для правильной интерпретации Ид из колонок таблиц в данные(!!) агрегатных типов как раз через "денсятичные вещицы" только и решается.
23 знака - это НЕ Ид.
Зранить неопределенное как раз лехко - в тех самых "числовых вещицах", которые для любого агрегатного типа данных одинаковой длины и структуры и позволяют выдернуть кратчайшим путем сам объект данных... ну или в более коротком виде, свернув в 36-ричное представление Ид вида (до 4 симв) и Ид объекта(до 6 симв).
40 Torquader
 
16.04.09
21:05
(39) таки в памяти же хранится "объект", то есть структура данных - байтов.
И поля всех данных наверняка по 4 байта выровнены, чтобы процессору было удобно.

Кстати, что у документов общий "номератор" ИД ?
А у справочников, получается - у каждого свой.

А во внутреннем представлении система различает документ, спозиционированный на определённом документе, и определённый документ (после CurrentDocument()). То есть там разные структуры.

(38) автор хотел в другой базе данных сохранить ИД-объектов из базы 1С, чтобы было проще ссылаться на данные (просто есть объекты-справочники, у которых были отключены и код и наименование - и остаётся только ИД) - или добавить поле КОД (или КодУчёта) и перекодировать (занимает где-то 30 секунд на копии базы).

А функцию IdToStr я перепутал с функциями нумерации колонок по Excel-евскому принципу - там без нуля, то есть сначала 0-9A-Z потом 00, и так далее. Получается шкала с геометрической прогрессией - которая ни в одну сторону быстро не преобразуется, но интересна тем, что в ней все символы значащие и не нужно передавать длину строки.
41 Torquader
 
16.04.09
21:17
И ещё проблема в том, что в некоторых случаях применяется изменение номера или даты документа (резерв за вчера превращается в заказ сегодня просто переносом в другую дату и заменой номера, так как нумерация каждый день с единицы, и простановкой флага в работе).
Хотелось бы, чтобы другие системы, в которые попадает этот документ, понимали, что произошёл перенос, а не то, что создали новый документ.
Эта проблема легко решается загоном всех пользователей в одну базу (видимо, из 1С будет устанавливаться соединение в SQL-сервером, в который будут отправляться изменения, а уже все остальные с этого сервера получат информацию). Если "сервер" навернётся, то просто перестанет работать обмен, потому как надёжность сети оставляет желать лучшего.
Успехов в работе.