|
|
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
Всем привет ! Встала вот такая задача: Есть средних размеров проект, который до недавнего времени был на Delphi 2007 (точнее, на C++Builder'е, но это не важно). В качестве БД используется DBISAM от ElevateSoftware, который всем устраивает кроме того, что не поддерживает юникод т.е. данные хранятся в ANSI с использованием системной кодировки. Сейчас идет перевод проекта на 10.3.3 Rio и юникод и возникла проблема с хранением данных в БД: поскольку весь интерфейс стал поддерживать юникод - пользователь может ввести любые строки в т.ч. содержащие юникодные эмоджи и т.д. Если сохранять их базу как есть - все, что выходит за пределы ANSI будет вопросиками. Чтобы этого избежать - строковые данные необходимо приводить из юникода в UTF-8 перед сохранением в базу и из UTF-8 в юникод - при чтении, отображении в db-aware контролах, при поиске и т.д. В этой связи вопрос: может быть у кого-то была подобная проблема и элегантный способ ее решения чтобы не писать UTF8ToString/StringToUTF8 в тысяче местах ? Или это таит в себе геморой внутри гемороя обернутый в геморой и все-таки стоит перейти на другой движек БД с поддержкой юникода из коробки ? Хотя с переходом проблем не меньше если не больше... Большое спасибо за советы ! ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 13:34 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
amsdev, вопрос в том, что там у этого DBISAM с кодировками коннекта. Если их вообще нет, тогда да, придется конвертировать. Или написать своего наследника (что кмк проще), который будет это делать для всех данных, переправляемых в базу и обратно. А поскольку юникодная Дельфи 2009 существует уже 10 лет, вероятно, кто-то это уже сделал. Например, у IBX с Firebird если чарсет коннекта win1251, то в базу ничего юникодного не залезет по определению. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 14:22 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
Я бы рассмотрел по порядку приоритетов следующие подходы: 1. Если архитектура приложения правильная, и в используются собственные компоненты-обёртки, то либо на уровне "своей обёртки над полем ввода" блокировать ввод неансишных символов, либо на уровне "своей обёртки над датасетом" убирать их перед сохранением, сообщать об ошибке и недопустимом значении итп. 2. Если архитектура приложения частично правильная, то на уровне базового класса формы развешать по полям ввода какие-нибудь OnChange, которые блокируют ввод неансишных символов. 3. Рассмотреть сложность и трудоёмкость рефакторинга на правильную архитектуру (с обёртками), потом см. пункт 1 4. Забить. В небольших проектах со стабильными пользователями такие неаккуратности несолидны, но не существенны. Ну вопросики и вопросики - у нас что, нет более актуальных задач? 5. Подумать над переходом на какую-нибудь более вменяемую СУБД, в том числе с поддержкой юникода. Когда-нибудь всё равно придётся. 6. Отпинать вендора этого чуда на предмет поддержки юникода. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 14:23 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
авторвопрос в том, что там у этого DBISAM с кодировками коннекта. Нет, данные приводятся к системной кодировке и сохраняются как ANSI. автор Если архитектура приложения правильная, и в используются собственные компоненты-обёртки, то либо на уровне "своей обёртки над полем ввода" блокировать ввод неансишных символов, либо на уровне "своей обёртки над датасетом" убирать их перед сохранением, сообщать об ошибке и недопустимом значении итп. Вопрос не в том, чтобы запретить ввод тех или иных символов, наоборот, нужно чтобы пользователь мог ввести любую строку на любом языке. Но чтобы при записи/чтении данных в БД конверсия в UTF8 происходила прозрачно и не заметно, чтобы не вызывать конверсию вручную... В хэлпе нарыл TStringField.Transliterate и TDataSet.Translate, которые делают почти то, что мне нужно, но проблема в том, что у TDataSet функция объявлена: function Translate(Src, Dest: PAnsiChar; ToOem: Boolean): Integer; На вход приходит текст в UTF8, но как его отдать в Dest как юникод ? Видимо никак ((( Вероятно придется делать своего наследника TDataSet... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 15:14 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
Когда я конвертировал базу Firebird, я делал это в два подхода через SQL-скрипты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 16:26 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
авторКогда я конвертировал базу Firebird, я делал это в два подхода через SQL-скрипты. Это понятно, что нужно будет имеющиеся данные конвертировать в UTF-8. Вопрос в том, как избежать правки Table.FieldByName('SomeField').AsString:=StringToUTF8(SomeValue); и SomeValue:=UTF8ToString(Table.FieldByName('SomeField').AsString); Как избавиться от StringToUTF8 и UTF8ToString чтобы не править код в тысяче мест ? Для db-aware контролов можно использовать эвент TStringField.OnGetText и все будет показано нормально, но во всех остальных местах править это караул. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 17:26 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
amsdev Вопрос не в том, чтобы запретить ввод тех или иных символов, наоборот, нужно чтобы пользователь мог ввести любую строку на любом языке. И сохранять их в неюникодной базе, для чего конвертировать в какую-нибудь хрень? Нет, тогда бы я однозначно поставил бы вопрос о миграции на какую-нибудь вменяемую СУБД. Не потому, что иначе не сделать, а потому, что не стал бы плодить ещё большую фигню. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 17:33 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
Тут важно понимать, используются ли строковые поля в базе только для хранения строк, или же еще и для поиска и других серверных операций с символьными последовательностями. Если только для хранения, то то проблемы почти и нет, строки можно рассматривать как байтовые массивы, и засовывать в них вообще все, что угодно, не глядя на кодировки. Единственная, правда, существенная, проблема - нулевой символ 0x00. Данные могут обрезаться по нему. А могут и не обрезаться, зависит от реализации, надо проверять экспериментально. Если же для строк требуется сравнение на стороне сервера (поиск, индекс), то оно возможно только для для той кодировки, которую сервер поддерживает. ANSI, значит, ANSI (win1251?), и никакого UTF-8. Зачем приводить к UTF-8, если сервер все равно не умеет с ней работать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2020, 18:02 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
Задачу решил вот таким образом, все работает быстро, ровно и без глюков ! Может кому окажется полезным. Мне были нужны только прозрачные запись и отображение. Для поиска (locate) или SQL запросов - можно аналогичным образом переопределить нужные методы и вставить туда кодирование в UTF8, мне это было не нужно поэтому пока все работает в таком варианте. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.06.2020, 01:22 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
если база не поддерживает UTF8, то при таком подходе могут неправильно строковые функции внутри SQL запросов. например SUBSTRING('текст', 3, 4) будет брать часть строки не с стретьего символа, а с третьего байта, в результате чего получите половинку буквы Е и букву К. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.06.2020, 10:54 |
|
||
|
Сохранение данных в БД c автоматическим приведением к UTF-8
|
|||
|---|---|---|---|
|
#18+
amsdev Для поиска (locate) или SQL запросов - можно аналогичным образом переопределить нужные методы и вставить туда кодирование в UTF8 Поиск на клиенте работать будет, но любой запрос вида Код: sql 1. 2. 3. 4. 5. 6. или Код: sql 1. 2. 3. 4. 5. 6. вас огорчит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.06.2020, 19:33 |
|
||
|
|

start [/forum/topic.php?fid=58&msg=39965020&tid=2038209]: |
0ms |
get settings: |
8ms |
get forum list: |
17ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
168ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
46ms |
get tp. blocked users: |
2ms |
| others: | 217ms |
| total: | 479ms |

| 0 / 0 |
