PHP / SQL - преобразование EBCDIC в ASCII

У нас есть код сервера PHP, выполняющий операторы SQL для нашей системы iSeries среднего уровня.

Вот упрощенная версия SQL-запроса

SELECT 'Regular' "sales_type", sum(sales_type1) "sales" FROM salesTable

Запрос выполняется нормально, проблема в том, что при использовании статического поля / значения, такого как «SomeText» «Заголовок», и результаты возвращаются в PHP, они не в желаемом формате

string(7) "م�����" 

Для подключения к системе и получения результатов

db2_connect ( '*LOCAL', 'user', 'pass' );
if (! $connection) {[error code]}
$stmt = db2_prepare ( $connection, $strSql );
if (! db2_execute ( $stmt ) ) { [error code ]
while ( $row = db2_fetch_array ( $stmt ) ) {
   var_dump($row[1]);
}

Мы на PHP версии 5.2.17

Наш iSeries - это V7R1M0

Решение для преобразования серверной части с помощью PHP или самого SQL-запроса было бы отличным.

Спасибо!


Изменить

Из предложения баксов мы изменили CCSID профиля пользователя на 37 вместо 65535.

Теперь вернемся (ниже), что немного ближе ...

string(7) "Ù…‡¤“™"

Возможно, это потому, что мы только изменили пользователя? Нужно ли также менять систему, задание или таблицу?


Изменить 2

Вот вывод phpinfo

_COOKIE["ZDEDebuggerPresent"]   php,phtml,php3
_SERVER["ZendEnablerConfig"]    /www/zendserver/conf/fastcgi.conf
_SERVER["PHPRC"]    /usr/local/ZendSvr/etc/
_SERVER["PHP_FCGI_CHILDREN"]    40
_SERVER["PHP_FCGI_MAX_REQUESTS"]    0
_SERVER["CCSID"]    819
_SERVER["LANG"] C
_SERVER["INSTALLATION_UID"] 20101203131436121338
_SERVER["LDR_CNTRL"]    MAXDATA=0x40000000
_SERVER["LIBPATH"]  /usr/local/ZendSvr/lib
_SERVER["DB2NOEXITLIST"]    TRUE
_SERVER["ORACLE_HOME"]  .
_SERVER["ORA_NLS10"]    no value
_SERVER["ORA_NLS_PROFILE33"]    no value
_SERVER["FCGI_ROLE"]    RESPONDER
_SERVER["REDIRECT_UNIQUE_ID"]   UYKvWcCoAQIAAnZHWG8AABS@
_SERVER["REDIRECT_STATUS"]  200
_SERVER["UNIQUE_ID"]    UYKvWcCoAQIAAnZHWG8AABS@
_SERVER["QIBM_USE_DESCRIPTOR_STDIO"]    Y
_SERVER["HTTP_HOST"]    vmas400.vm.com:10090
_SERVER["HTTP_CONNECTION"]  keep-alive
_SERVER["HTTP_X_REQUESTED_WITH"]    XMLHttpRequest
_SERVER["HTTP_USER_AGENT"]  Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
_SERVER["CONTENT_TYPE"] application/x-www-form-urlencoded
_SERVER["HTTP_ACCEPT"]  */*
_SERVER["REFERER"]  http://vmas400.vm.com:10090ZendServer/Index/Index
_SERVER["HTTP_REFERER"] http://vmas400.vm.com:10090/ZendServer/Index/Index
_SERVER["REFERER_URL"]  http://vmas400.vm.com:10090/ZendServer/Index/Index
_SERVER["HTTP_ACCEPT_ENCODING"] gzip,deflate,sdch
_SERVER["HTTP_ACCEPT_LANGUAGE"] en-US,en;q=0.8
_SERVER["HTTP_ACCEPT_CHARSET"]  ISO-8859-1,utf-8;q=0.7,*;q=0.3
_SERVER["HTTP_COOKIE"]  ZENDSERVERSESSID=7asfv608qffhv556msem6evi66; CosmeticContest=16062; CompanyWithStoreDetail=16061; TYLYClassAnalysis=16068; OrderDetail=17220; RmsOrders=17221; DailyReceipts=16063; DailySales=17562; OnOrder=16064; OpenPurchaseOrders=17566; RegularPriceRankings=17568; ReviewStatistics=17570; SalesAndStock=17573; StocksByPeriod=17575; Top10BestSellers=17577; ReplenishmentAssortment=17269; RABS=17616; FreeFormatSku=16473; TYLYSalesAndOH=21294; SalesRecapByDate=16312; VendorAgendaSummary=23219; BasicStock=23474; InStock=16067; RegSalesAvgStockSummary=21270; TYLYSalesMDGMByStore=23822; VendorAgenda=23826; Header=16066; usc=adam; hudi[u]=d106b7a04c0d94b8a0e7624a017ead98324b57e8; hudi[i]=fec51923e58c84db4647d2b3e11fe03ec3f0c202; FreeFormat=16506; __utma=118969486.352613215.1355776933.1365626094.1367348033.12; __utmz=118969486.1355776933.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); ZDEDebuggerPresent=php,phtml,php3
_SERVER["PATH"] /bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin
_SERVER["SERVER_SIGNATURE"] no value
_SERVER["SERVER_SOFTWARE"]  Apache
_SERVER["SERVER_NAME"]  vmas400.vm.com
_SERVER["SERVER_ADDR"]  192.168.1.2
_SERVER["SERVER_PORT"]  80
_SERVER["REMOTE_ADDR"]  172.16.129.193
_SERVER["DOCUMENT_ROOT"]    /www/zendserver/htdocs/prod
_SERVER["SERVER_ADMIN"] [no address given]
_SERVER["SCRIPT_FILENAME"]  /usr/local/zendsvr/gui/html/index.php
_SERVER["DOCUMENT_NAME"]    /usr/local/zendsvr/gui/html/index.php
_SERVER["REMOTE_PORT"]  14259
_SERVER["REDIRECT_QUERY_STRING"]    dojo.preventCache=1367519066445
_SERVER["REDIRECT_URL"] /ZendServer/Information/Phpinfo
_SERVER["GATEWAY_INTERFACE"]    CGI/1.1
_SERVER["SERVER_PROTOCOL"]  HTTP/1.1
_SERVER["REQUEST_METHOD"]   GET
_SERVER["QUERY_STRING"] dojo.preventCache=1367519066445
_SERVER["REQUEST_URI"]  /ZendServer/Information/Phpinfo?dojo.preventCache=1367519066445
_SERVER["SCRIPT_NAME"]  /ZendServer/index.php
_SERVER["DOCUMENT_URI"] /ZendServer/index.php
_SERVER["RULE_FILE"]    conf/httpd.conf
_SERVER["PHP_SELF"] /ZendServer/index.php
_SERVER["REQUEST_TIME"] 1367519066

ИЗМЕНИТЬ

РЕШЕНИЕ

Решение заключалось в изменении профиля пользователя на использование CCSID 37 и серверных заданий на использование CCSID 37. Мы внесем изменения вручную, чтобы при перезапуске заданий они не возвращались.


person adam    schedule 02.05.2013    source источник


Ответы (2)


Преобразование может произойти автоматически, если сторона IBM настроена правильно. Попросите администратора IBM проверить системное значение QCCSID. Если он установлен на 65535, то перевод не выполняется. 65535 говорит, что все данные в системе являются двоичными и никогда не должны переводиться. Есть иерархия CCSID. Он начинается на системном уровне с QCCSID, перемещается вниз к профилю пользователя и, наконец, к отдельной таблице. Это для работы с системами, в которых используется несколько языков.

Основная причина, по которой системы находятся на 65535, заключается в том, что, когда был развернут далекий предок нынешних машин среднего уровня, был единый язык; один EBCDIC, а когда было введено несколько языков, язык по умолчанию был установлен на «не переводить».

EBCDIC больше не является односимвольным набором. Для каждого языка существует своя кодировка. Американский английский - CCSID (37). Если выяснится, что проблема в CCSID, попросите администратора создать тестовый профиль пользователя с правильным CCSID и попробуйте это.

РЕДАКТИРОВАТЬ 1: Я только что провел тест на своей машине.

ИЗМЕНИТЬ 2: добавлен литерал к возвращаемым столбцам.

<?php
  //Establish connection to database
  $host = "midrange";
  $conn = db2_connect ($host, user, pass);
?>

<table width="75%" border="1" cellspacing="1" cellpadding="1" bgcolor="#eeeeee">
<tr>
  <td><b>Name</b></td>
  <td><b>Email</b></td>
  <td><b>3rd column</b></td>
</tr>

<?php
$query = 'Select name, email, \'Markdown\' "THIRD" from table';

//Execute query
$queryexe = db2_exec($conn, $query) ;

//Fetch results
while(db2_fetch_row($queryexe)) {
 $name  = db2_result($queryexe, 'NAME');
 $email = db2_result($queryexe, 'EMAIL');
 $const = db2_result($queryexe, 'THIRD');

//Put the results in an HTML table.
print("<tr bgcolor=#ffffff>\n");
print("<td>$name</td>\n");
print("<td>$email</td>\n");
print("<td>$const</td>\n");
print("</tr>\n");
}
?>
</table>

Все мои таблицы имеют CCSID (37) IBM i 7.1.
phpinfo () отчеты IBM_DB2 1.9.0, PHP 5.3.3 Я заметил, что у меня включена поддержка iconv, а CCSID моего сервера - 819 - US ASCII.

Редактировать 3: очень частичное phpinfo ()

ibm_db2
IBM DB2, Cloudscape and Apache Derby support    enabled
Module release  1.9.0
Module revision     $Revision: 297218 $
Binary data mode (ibm_db2.binmode)  DB2_BINARY
DB2 instance name (ibm_db2.instance_name)   no value

iconv
iconv support   enabled
iconv implementation    IBM iconv
iconv library version   unknown

Directive   Local Value Master Value
iconv.input_encoding    ISO8859-1   ISO8859-1
iconv.internal_encoding ISO8859-1   ISO8859-1
iconv.output_encoding   ISO8859-1   ISO8859-1
Environment
Variable    Value
ZendEnablerConfig   /www/zendsvr/conf/fastcgi.conf
PHPRC   /usr/local/ZendSvr/etc/
PHP_FCGI_CHILDREN   5
PHP_FCGI_MAX_REQUESTS   0
CCSID   819
LANG    en_US
INSTALLATION_UID    20101215125734236656
LIBPATH     /usr/local/ZendSvr/lib
DB2NOEXITLIST   TRUE

PHP Variables
Variable    Value
_REQUEST["TJE"] no value
_REQUEST["TE3"] no value
_REQUEST["ZDEDebuggerPresent"]  php,phtml,php3
_COOKIE["TJE"]  no value
_COOKIE["TE3"]  no value
_COOKIE["ZDEDebuggerPresent"]   php,phtml,php3
_SERVER["ZendEnablerConfig"]    /www/zendsvr/conf/fastcgi.conf
_SERVER["PHPRC"]    /usr/local/ZendSvr/etc/
_SERVER["PHP_FCGI_CHILDREN"]    5
_SERVER["PHP_FCGI_MAX_REQUESTS"]    0
_SERVER["CCSID"]    819
_SERVER["LANG"] en_US
_SERVER["INSTALLATION_UID"] 20101215125734236656
_SERVER["LIBPATH"]  /usr/local/ZendSvr/lib
_SERVER["DB2NOEXITLIST"]    TRUE
_SERVER["FCGI_ROLE"]    RESPONDER
_SERVER["SCRIPT_URL"]   /hello.php
_SERVER["QIBM_USE_DESCRIPTOR_STDIO"]    Y
_SERVER["HTTP_USER_AGENT"]  Mozilla/5.0 (Windows NT 6.1; rv:20.0) Gecko/20100101 Firefox/20.0
_SERVER["HTTP_ACCEPT"]  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
_SERVER["HTTP_ACCEPT_LANGUAGE"] en-US,en;q=0.5
_SERVER["HTTP_ACCEPT_ENCODING"] gzip, deflate
_SERVER["HTTP_DNT"] 1
_SERVER["HTTP_CONNECTION"]  keep-alive
_SERVER["HTTP_PRAGMA"]  no-cache
_SERVER["HTTP_CACHE_CONTROL"]   no-cache
_SERVER["PATH"] /bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin
_SERVER["SERVER_SIGNATURE"] no value
_SERVER["SERVER_SOFTWARE"]  Apache
_SERVER["DOCUMENT_ROOT"]    /www/zendsvr/htdocs
_SERVER["SERVER_ADMIN"] [no address given]
_SERVER["SCRIPT_FILENAME"]  /www/zendsvr/htdocs/hello.php
_SERVER["DOCUMENT_NAME"]    /www/zendsvr/htdocs/hello.php
_SERVER["REMOTE_PORT"]  54747
_SERVER["GATEWAY_INTERFACE"]    CGI/1.1
_SERVER["SERVER_PROTOCOL"]  HTTP/1.1
_SERVER["REQUEST_METHOD"]   GET
_SERVER["QUERY_STRING"] no value
_SERVER["REQUEST_URI"]  /hello.php
_SERVER["SCRIPT_NAME"]  /hello.php
_SERVER["DOCUMENT_URI"] /hello.php
_SERVER["RULE_FILE"]    conf/httpd.conf
_SERVER["PHP_SELF"] /hello.php
_SERVER["REQUEST_TIME"] 1367514482

Редактировать 4: Как сделать серверные задания CCSID (37)

Есть несколько способов заставить серверные задания работать на американском английском. Решение о том, какое из них меньше всего влияет на работу сервера в целом, принимает администратор. Я установил в своей системе только на английском языке (США) переход на QCCSID 37 через IPL и не обнаружил никаких проблем.

  1. CHGSYSVAL QCCSID 37 - при этом для всего сервера будет установлен английский язык (США). Чтобы изменения вступили в силу, перезапустите сервер Apache.
  2. CHGUSRPRF QTMHHTTP CCSID(37) - все задания HTTP-сервера будут переведены на английский (США). Чтобы изменения вступили в силу, перезапустите сервер Apache.
  3. Перенастройте сервер Apache. Установите CgiConvMode EBCDIC, DefaultNetCCSID 819 и CGIJobCCSID 37 Перезапустите сервер Apache, чтобы вступили в силу. См. Преобразование данных CGI. для подробностей. Это установит рабочие места одного сервера Apache на английский (США).
  4. CHGPF ... CCSID(37) - для файла будет установлен английский (США). Нужно их все переделать.

Это не означает, что все включено. Больше похоже на краткое изложение того, как иерархия сочетается друг с другом.

person Buck Calabro    schedule 02.05.2013
comment
Ну ... думаю, на шаг ближе. (см. правки в OP) Мы изменили профиль пользователя на 37 вместо * SYSVAL, и теперь мы получаем строку (7) Ù… ‡ ¤ “™ string (8) Ô ™ '„ - ¦ • что немного ближе к фактическому персонажи ... какие-нибудь идеи? - - заранее спасибо! - person adam; 02.05.2013
comment
Какие ценности вы ожидаете увидеть? Оператор SELECT имеет только 2 столбца, но переменные - «строка (7)» и «строка (8)». Можете ли вы показать шестнадцатеричное значение того, что возвращается? - person Buck Calabro; 02.05.2013
comment
Я ожидал увидеть Regular и Markdown от OP. или, по крайней мере, обычные английские буквы :) ... У меня в примере были разные заголовки, чем у моего живого кода, извините. Я внес правки, чтобы показать правильное название. Ответ короткий на один символ, что является нечетным. Возвращаются два шестнадцатеричных значения: d98587a4938199 и d48199928496a695, которые просто повторяются. Убраны повторы, чтобы не было путаницы. - person adam; 02.05.2013
comment
Я добавил рабочий пример на свою машину 7.1. Может быть, просмотр phpinfo () поможет. Ваши шестнадцатеричные строки на самом деле являются US EBCDIC CCSID 37. - person Buck Calabro; 02.05.2013
comment
Обычные запросы, подобные этому, работают нормально. Это когда вы указываете статические значения в запросе SQL вместо извлечения из столбца. - person adam; 02.05.2013
comment
Я получаю сообщение о том, что 819 не является допустимым CCSID для профиля пользователя. Продолжим экспериментировать. - person adam; 02.05.2013
comment
Для переводов нужны две кодировки. Сторона DB2 - это US EBCDIC (37), а веб-сторона - US ASCII (819). См. Дополнительное редактирование, показывающее вывод phpinfo (). - person Buck Calabro; 02.05.2013
comment
Я проверил раздел phpinfo, и он уже был установлен на 819 = [внес изменения в мой OP, чтобы показать - person adam; 02.05.2013
comment
Хорошо, для проверки возвращаются два столбца: буквальная и сумма продаж. Литерал возвращается как EBCDIC, а сумма продаж читается как ASCII? Или проблема в том, что все столбцы возвращаются EBCDIC, но только тогда, когда в SELECT есть литерал? Проверьте задание веб-сервера (WRKSBSJOB QHTTPSVR), чтобы убедиться, что оно использует CCSID 37. Затем проверьте файл .php (WRKLNK) на сервере, чтобы убедиться, что это 819 или 1252. - person Buck Calabro; 02.05.2013
comment
ГЕНИЙ! Я прошел и изменил задания на CCSID 37 и запустил его, и все заработало! Когда сервер перезапустится, он вернется. Можете ли вы отредактировать свой ответ, указав свое исправление и, возможно, как сделать это изменение постоянным (если возможно?) Большое спасибо за вашу помощь! 1000 голосов! - person adam; 02.05.2013

Я нашел лучший способ сделать это ... Используя ПЕРЕВЕСТИ или ключевое слово ForceTranslation в вашем DSN. Например:

odbc:DRIVER={iSeries Access ODBC Driver};SYSTEM=as400.myserver.local;TRANSLATE=1;

Вам не нужно изменять какие-либо файлы, настройки системы или использовать CAST в ваших запросах.

person Todd    schedule 08.12.2015