Недокументированная функция _StrToId() и _IdToStr() #401819


#0 by Torquader
Возник вопрос с кодированием данных в текстовые строки. Вспомнил, что есть функции _StrToId и _IdToStr, но что-то возникли проблемы с пониманием результата. Насколько я понял, _IdToStr переводит число в 36-ричную систему ? И 00000 всегда 0. Далее, интересно, что _StrToId(-1) выдаёт какое-то значение, то есть отрицальность не проверяется ? Ожидалось, что _IdToStr переводит число в "систему без ноля", как например нумерация колонок в Excel, но, видимо, ожидания не оправдались ?
#2 by КонецЦикла
Какой-то поток сознания... Вот сам подумай 000 это число? Равно ли оно 0?
#3 by dk
---- думай, решай, есть ограничения на длину
#4 by Torquader
я просто ожидал, что "000" != "00", но оказалось, что РАВНО. Ограничения на длину там тоже странные - для целых положительных чисел ограничений нет. Все символы, кроме 1-9 A-Z считаются, как 0. Однако, _IdToStr(-1)=Z141Z3, а _StrToId("Z141Z3")=2118184959 удивляет то, что проверки на отрицательность аргумента нет.
#5 by Cthulhu
Указанные функции служат для преобразования предствлений Id объектов данных (10-тичное представление - это формат внутреннего представления, из которых составлено ЗначениеВСтрокуВнутр(<объект данных>); 36-ричное представление -- это формат, в котором внутренние представления хранятся в таблицах базы данных) и метаданных 1с -- а вовсе не для преобразоывания чисел.. поэтому ожидать от них того, что они будут корректно преобразовывать отрицательные числа -- извините, но глупо... (кстати в равной мере глупо ожидать от этих функций преодразования Id, превышающих некоторые "граничные")
#6 by Cthulhu
: ограничения на длину легко вычисляются: 10 и 6
#7 by orefkov
Искренне завидиую - имееть время докапываться, почему недокументированные фичи  1С ведут себя не так, как ты ожидал - мне бы так.
#8 by orefkov
Ладно уж, даю справку. 1. Всякий уважающий себя программист знает, что для 32-битных чисел в машинном виде -1 хранится точно также, как 0xFFFFFFFF (4294967295). Представление этого числа в 36ричной системе есть 1Z141Z3. 2. 1С для идшников используются только положительные знаковые целые (а не беззнаковые), то есть числа от 0 до 2147483647, то для их 36ричного представления отводится только 6 символов. Таким образом видно, что эти функции заточены именно под п.2, то есть всегда выдают результат 6-символной строкой. Поэтому в п. 1 ведущая 1ца откидывается. Обратное преобразование 36ричного числа Z141Z3 и есть 2118184959. Про "0000" и "0" даже не берусь пояснять. Это либо дано понять сразу, либо не понять никогда.
#9 by ДенисЧ
А вот философский вопрос... Если они отводят 6 знаков для ИД, то почему всё в базе лежит в char...
#10 by Ковычки
а как выглядят отрицательные значения к примеру в 16-и разрядной ?
#11 by orefkov
6 знаков идшник + 3 знака dbsign, код распределенной базы. И кстати, для хранения идшников объектов метаданных (ну там вид справочника и тп) отводится только 4 символа, отсюда видно, что максимальный возможный идшник для объекта метаданных есть _strtoid("ZZZZ") = 1679615. Берегите конфу, не правьте метаданные слишком часто, а то их тупо не хватит :)
#12 by Torquader
А, кстати, об ИД-метаданных как раз вопрос и возник. Как, не разбирая MD-файл, получить ИД-объекта метаданных и ИД-реквизита объекта. Для справочника, например, можно ValueToStringInternal(GetEmptyValue("Reference."+Metadata.Reference(i).Identifier)) в получаемом наборе четвёртый параметр обозначает ID справочника. А как получить ИД реквизита справочника ? Внутри в базе всё хранится в двоичном представлении, так как функция _StrToId выдаёт не строку, а число, а число хранится внутри машины в том формате, который удобнее машине, а вот когда мы его хотим увидеть, нам машина выводит его в десятичном формате. Про _IdToStr меня поразило, что отрицательные числа переводятся не в 0, а также что _StrToId(_IdToStr(-1)) даёт число, которое никак на -1 не похоже, как его не переводи в 16 - мне стало интересно - почему так. А почему для хранения типа "Неопределённый" используется 23+3 байта ? Я сколько ломал голову, так и не понял. Кстати, ValueFromStringInternal("{""UU"",""""}"); роняет 1С моментально.
#13 by Torquader
P.S. я пытаюсь написать систему логирования изменения объектов, которая будет "застрахована" от внесения изменений в конфигурацию, но пока получается только фигня.
#14 by Guk
мне кажется ты придумываешь велосипед с трапециидальными колесами...
#15 by ДенисЧ
надёжное логирование делается только через триггеры.
#16 by Torquader
у меня семейство баз, причём разных, и не все даже 1С. Они работают вместе и обмениваются данными, при загрузке данных в 1С хочется, чтобы записывались данные об изменении определённых справочников, причём, если в конфигурации что-то поменяют, то система записи продолжала бы работать.
#17 by Ёпрст
>>>Берегите конфу, не правьте метаданные слишком часто, а то их тупо не хватит :)
#18 by Mikeware
Ты не поверишь, но ПолучитьПустоеЗначение(вид) как раз берет ид из мд Для хранения нопределенного 23 потому, что тип+вид+ид.
#19 by romix
Может, пригодится...
#20 by ДенисЧ
Так сложно сделать автоматическую генерацию триггеров?
#21 by Torquader
у меня как-то не получается 23: ИД - 3+6=9 Вид=4 и откуда ещё 10 ? У меня было подозрение, что максимальное число - это 19 цифр+знак+точка=21 и ещё один байт признак типа. А там, если смотреть в DD получается 23+3 (насколько я понял, вторая часть - это органичение типа). спасибо за ссылки - именно это я и пытался проверить. у меня не SQL, а DBF-версия, причём часть из них вообще локальные однопользовательские, чтобы работали, когда отключат сеть - и весь этот зверинец, конечно, "глючит" так, что "мама не горюй". Возникла идея - хранить ID не в 36-ричной, а в 95-ричной системе (127-32), так они меньше места занимают.
#22 by ДенисЧ
#23 by Ёпрст
ну тогда до кучи .
#24 by Torquader
Больше всего радует 9 символов для хранения перечисления - обычно, элементы перечисления могут ограничиваться одним или двумя десятками.
#25 by Mikeware
Общий принцип - если значение типизированное, то ид - 9 символов
#26 by Torquader
понятно - просто обидно, когда куча места расходуется понапрасну. Когда dbf размер файла быстро "накручивается" до двух гигов (особенно хороши строки неограниченной длины - все строки в одном файле) А конфу "беречь" не за чем - если мы что-то правим, то новые ID расходуются только на новые объекты, а если мы что-то переименовываем или меняем тип, то ID не меняется.
#27 by Torquader
Вообще я уже понял, что или приводить всё в порядок, то есть ставить сервер и SQL, чтобы все "яйца в одной корзине" - просто и ясно, только вот денег это стоит.
#28 by Cthulhu
Mikeware, хорош пургу гнать... 1. Ид в виде внутреннего представдения объекта данных (ЛЮБОГО!) состоит из следующих частей: Ид типа объекта (1 символ) Ид вида объекта (10 символов) Ид объекта (10 символов) Код ИБ (3 символа) ИТОГО: 24 символа. 2. Этот Ид (внутреннего представления) для хранения в данных(!) раскладывается на составные части и сохраняется (в общем случае, причем не всегда полностью) в разных полях(колонках таблиц данных): Ид вида объекта - 4 символа(см.), Ид объекта - 6 символов и Код ИБ (3 символа).. Иды вида объекта и объекта данных получаются из соответствующих частей Ид-а внутр.представления посредством _IdToStr(..). Отсюдова вывод: для оперирования объектами данных используется Ид из п.1 (единый собранный Ид фиксированной длины 24 символа); для поиска данных в таблицах данных нужно преобразовавать нужные составные чати этого Ид при помощи _IdToStr(..) и искать в соответствующих колонках таблиц данных (или писать в них))).
#29 by Torquader
Да, 24 уже похоже на правду, хотя, вид объекта, всё-таки, должен быть 9 символов (он вообще 4, но 4 хранят в поле 9, почему-то).
#30 by Torquader
А IdToStr сдалась на 2147483649 (0x80000001) Не совпало i=2147483649 => ZIK0ZL => -2147483647 То есть Id для 1С это четырёхбайтовое целое со знаком, но при этом отрицательные значения не допускаются. Удачи.
#31 by КонецЦикла
Вот значение в самую длинную строку БД, char 'B1  NA    3X001        ' Не поднимай пыль
#32 by Torquader
он, видимо, считал не в упакованном виде, а в реальном (десятичные числа), только я как-то внутрь 1С настолько глубоко не лазил, чтобы увидеть, что там есть, а у функции ValueToStringInternal получается набор из семи параметров.
#33 by КонецЦикла
Ну дык пора залазить :) Внутри ж не десятичные, запаришься триггеровать
#34 by Torquader
конечно, хорошая идея - запускать отладку процесса 1С и ловить момент изменения данных, чтобы записать его в файл. Но это уже слишком - тормоза будут - просто супер.
#35 by Sadovnikov
Нда. Веселая веточка...
#36 by Cthulhu
: не надо бабушку лохматить, PARENTVAL - это не совсем ID (хотя и "по мотивам"). В базе все реквизиты агрегатных типов определенного вида хранятся в виде свернутого в 36-ричное представление Ид объекта данных (длина 6) +Код ИБ (три символа); объекты агрегатных типов не указанного вида хранятся в том же виде плюс(слева, в начало) 4-символьное 36-ричное представление Ид вида объекта...
#37 by orefkov
Ты что, невнимательно читал. Я это вроде там еще разъяснял. А 23 для неопределенных - ну видимо из расчета 'N' + 20 символов под число 19.9 + 2 про запас.
#38 by КонецЦикла
Об этом в курсе, зачем пудришь автору голову десятичными вещицами? 23 знака - это неопределенный тип как таковой (не только парентвал), проще уже так и хранить чем все время триммить при соединениях и проч. Если уж хранить неопределенное... а вообще я ниасилел что автор хочет сделать
#39 by Cthulhu
: "десятичные вещицы" - суть внутреннее представление, как раз ералаш с разбивкой Ид внутреннего представления по полям(колонкам) таблиц бОльшее пудрение; и для правильной интерпретации Ид из колонок таблиц в данные(!!) агрегатных типов как раз через "денсятичные вещицы" только и решается. 23 знака - это НЕ Ид. Зранить неопределенное как раз лехко - в тех самых "числовых вещицах", которые для любого агрегатного типа данных одинаковой длины и структуры и позволяют выдернуть кратчайшим путем сам объект данных... ну или в более коротком виде, свернув в 36-ричное представление Ид вида (до 4 симв) и Ид объекта(до 6 симв).
#40 by Torquader
таки в памяти же хранится "объект", то есть структура данных - байтов. И поля всех данных наверняка по 4 байта выровнены, чтобы процессору было удобно. Кстати, что у документов общий "номератор" ИД ? А у справочников, получается - у каждого свой. А во внутреннем представлении система различает документ, спозиционированный на определённом документе, и определённый документ (после CurrentDocument). То есть там разные структуры. автор хотел в другой базе данных сохранить ИД-объектов из базы 1С, чтобы было проще ссылаться на данные (просто есть объекты-справочники, у которых были отключены и код и наименование - и остаётся только ИД) - или добавить поле КОД (или КодУчёта) и перекодировать (занимает где-то 30 секунд на копии базы). А функцию IdToStr я перепутал с функциями нумерации колонок по Excel-евскому принципу - там без нуля, то есть сначала 0-9A-Z потом 00, и так далее. Получается шкала с геометрической прогрессией - которая ни в одну сторону быстро не преобразуется, но интересна тем, что в ней все символы значащие и не нужно передавать длину строки.
#41 by Torquader
И ещё проблема в том, что в некоторых случаях применяется изменение номера или даты документа (резерв за вчера превращается в заказ сегодня просто переносом в другую дату и заменой номера, так как нумерация каждый день с единицы, и простановкой флага в работе). Хотелось бы, чтобы другие системы, в которые попадает этот документ, понимали, что произошёл перенос, а не то, что создали новый документ. Эта проблема легко решается загоном всех пользователей в одну базу (видимо, из 1С будет устанавливаться соединение в SQL-сервером, в который будут отправляться изменения, а уже все остальные с этого сервера получат информацию). Если "сервер" навернётся, то просто перестанет работать обмен, потому как надёжность сети оставляет желать лучшего. Успехов в работе.
Тэги:
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С