Why TEXT column returns only 4096 bytes? - php

I'm storing a long text with mssql_query();
And Using the field with datatype called 'text'.
I tried with different long strings by using str_repeat(), the page takes long time, but in the end submits the result.
When I retrieve the result however, I get only 4096 bytes nomatterwhat.
I tried to retrieve the value with management studio too, and it gets the same outcome.
It looks to me like a storing problem to me. Please advice something... I'm confused.
EDIT for these who asked, this is what I'm using:
function sql_escape($sql) {
/* De MagicQuotes */
$fix_str = stripslashes($sql);
$fix_str = str_replace("'","''",$sql);
$fix_str = str_replace("\0","[NULL]",$fix_str);
return "'".$fix_str."'";
}
$query=mssql_query('update prod_cat set htmlbottom='.sql_escape(str_repeat('\'choose_cat ', 122000)).
' where ID=1' );
$query=mssql_query('select htmlbottom from prod_cat where ID=1');
$a=mssql_fetch_assoc($query);
echo strlen($a['htmlbottom']);

Microsoft's PHP driver (for reference): http://www.microsoft.com/en-us/download/details.aspx?id=20098
But if you don't want to (or can't) change drivers, from this site:
You need to increase the maximum size of a text column to be returned from
SQL Server by PHP. You can do this with a simple SQL query:
SET TEXTSIZE 2147483647
Which you can run with the following PHP (best run just after you make a
connection).
mssql_query("SET TEXTSIZE 2147483647");
A better way to work around the issue is to change the "textlimit" and
"textsize" settings within php.ini, like so:
mssql.textlimit = 2147483647
mssql.textsize = 2147483647
Your MSSQL driver is truncating the text. If you can't change datatypes, drivers, etc., this should fix the issue for you.

Related

ODBC array fetch of VARBINARY column causes server timeout

I have an app that fetches a VARBINARY(max) data from SQL Server database. On my local environment the app connects via SQL Driver. Connection string of odbc_connect contains:
DRIVER={SQL Server}
I am fetching the VARBINARY data like this:
// Hexadecimal data of attachment
$query = 'SELECT * FROM attachments WHERE LOC_BLOB_ID = ' . $blob_id;
$attach_result = odbc_exec($connection, $query);
odbc_binmode($attach_result, ODBC_BINMODE_CONVERT);
odbc_longreadlen ($attach_result, 262144);
$attach_row = odbc_fetch_array($attach_result);
$hex_data = $attach_row['attachment_value'];
$binary = hex2bin($hex_data);
It works well. Now I need to run this app on a server where my only option is to use the ODBC driver 17 for SQL Server. Connection string contains:
DRIVER={ODBC Driver 17 for SQL Server}
And it doesn't work. It fails on line number 6 of the preview above (on odbc_fetch_array). I've tried commenting out the odbc_binmode and odbc_longreadlen lines (I assumed this driver might handle those data natively), but no luck, same result: Service unavailable timeout error.
Is there a different approach to this width ODBC Driver 17?
Edit: I found out it hangs on ODBC_BINMODE_CONVERT. If I change it to ODBC_BINMODE_RETURN, it runs within few seconds - however the output is wrong. The ODBC_BINMODE_CONVERT is indeed what I need, but it doesn't process the entire data in time (the timeout is 30 seconds), which is strange, because the VARBINARY field in the database is only 65K characters long, and it runs extremely fast on my local environment.
*Edit2: I've tried to convert the incomplete binary data fetched from the database to hexadecimal and then to PNG and it displays half of the image. So I am positive it is fetching the correct data, it just takes incredibly long to fetch that column, resulting in timeouts in almost every case.
OK. Finaly figured it out. What ended up working for me was using ODBC_BINMODE_RETURN flag instead of ODBC_BINMODE_CONVERT, and NOT using hex2bin() conversion at the end.
The code in my original question worked fine with {SQL Server}, and the following code works with {ODBC Driver 17 for SQL Server}:
$query = 'SELECT * FROM attachments WHERE LOC_BLOB_ID = ' . $blob_id;
$attach_result = odbc_exec($connection, $query);
odbc_binmode($attach_result, ODBC_BINMODE_RETURN);
odbc_longreadlen ($attach_result, 262144);
$attach_row = odbc_fetch_array($attach_result);
$binary = $attach_row['attachment_value'];

Using PHP & ODBC_RESULT, Why am I losing the 4th decimal place

I'm hoping this is an easy question.
If I run an ODBC connection via Excel I get exactly what I would expect to see from the database. When I port the query over to Xampp for testing I can not get the query to display the 4th decimal place in the results.
Here is my SQL query defined in Excel:
SELECT MC_BOM_DETAIL.finished_item, MC_BOM_DETAIL.item_num, MC_BOM_DETAIL.quantity, MC_BOM_DETAIL.line_num, IC_INVENTRY_MAST.um_stocking
FROM IC_INVENTRY_MAST IC_INVENTRY_MAST, MC_BOM_DETAIL MC_BOM_DETAIL
WHERE IC_INVENTRY_MAST.company = MC_BOM_DETAIL.company AND IC_INVENTRY_MAST.item_num = MC_BOM_DETAIL.item_num
ORDER BY MC_BOM_DETAIL.finished_item, MC_BOM_DETAIL.line_num
The php page executing the query is as follows
//Define ODBC Connection
$mas_conn = odbc_connect("odbc_connection", "user_name", "password");
//Define Query
$query = "SELECT mbd.finished_item, mbd.item_num, mbd.line_num, mbd.quantity, icm.um_stocking
FROM IC_INVENTRY_MAST icm, MC_BOM_DETAIL mbd
WHERE icm.company = mbd.company AND icm.item_num = mbd.item_num
ORDER BY mbd.finished_item, mbd.line_num";
if($result=odbc_exec($mas_conn, $query)) {
while(odbc_fetch_row($result)){
echo odbc_result($result,'quantity') .'<br>';
}
}
odbc_free_result($result);
odbc_close($mas_conn);
The results are always truncated (not rounded) to the 3rd decimal place, however I need precision to the 4th.
I looked through the php.ini file to see if that maybe the cause but came up short.
Does anybody have an suggestions?
Thank you for your time.
Solution:
The issue in my case was with the Data Definitions inside the source data. This is a bit tricky as the database is read only, and the ODBC driver is provided by 3rd party (ProvideX). After speaking with a tech at the software manufacture, I was able to change the data definitions which was set to decimal(8,3). Why Excel could read the 4th decimal and the php odbc connection could not is still unanswered. My only thought would be since Excel is running locally.
Check You Windows Localization Settings:
Panel Control->Region and Language -> Formats -> Additional Settings -> No of digits after decimal...

PHP String Limitation On odbc_fetch_array

I have the following sql
SELECT
bw_imp_step as imp_action,
FROM cm3rm1 m1 INNER JOIN cm3rm2 m2 ON m1.number=m2.number
WHERE m1.number='$id'
when this same query is returned in DbVisualizer it returns the entire string however running this same query in my php limits the string and cuts it off towards the end.
The string that is returned is roughly 5500 characters.
Below is the php script that runs the above query:
$connection = odbc_connect("Driver={SQL Server};Provider=SQLNCLI;Server=sname;Database=cbname;","username","password")
$sql = "SELECT
bw_imp_step as imp_action,
FROM cm3rm1 m1 INNER JOIN cm3rm2 m2 ON m1.number=m2.number
WHERE m1.number='$id'";
$result = odbc_exec ($connection,$sql);
if ($row = odbc_fetch_array($result){
$imp_action = $row["imp_action"];
}
When I put put $imp_action to the page or even to a file it cuts off the string at around 5000charactes.
So my question is: Does PHP limit the size of a string being returned by a resultset? I have read that php can handle a string size of 2GB and this string is not even close to that size.
I know this is an old post, but I just ran into this too and the situation was sufficiently complex to warrant a complete answer.
There are several places where the your data could be getting truncated.
ODBC Long Read Length
ODBC has a default long read length (lrl) for large columns. Make sure the lrl for your fetch is sufficiently large, by doing one of the following:
Set the default in php.ini to something bigger, like odbc.defaultlrl = 10000.
Or use ini_set("odbc.defaultlrl", "10000"); to set it in your code before making your connection.
Or use odbc_longreadlen($result, "10000"); to set it in your code before fetching your result.
FreeTDS
If you're using FreeTDS to connect to an MS SQL DB from a Linux environment, there's a text size limit set in your freetds.conf file. Double check that your configuration is large enough here.
php_mssql
As in #Anujan's answer, some people (not the OP, I think) may be using php_mssql to make their connection, in which case you want to make sure your mssql.textlimit and mssql.textsize are sufficiently large, either by settings them in your php.ini or with the following in your code (before making your connection):
ini_set('mssql.textlimit', "10000");
ini_set('mssql.textsize', "10000");
SQL Server
The SQL Server itself sets a default text size and you may need to explicitly bump it up (especially if using ODBC without php_mssql and the configuration given for it above). In this case, add the following to the beginning of your query string:
SET TEXTSIZE 10000
SELECT big_ol_column FROM wherever
...
Note that some changes (like to php.ini) may require you to reload/restart PHP/Nginx/Apache to take effect.
You should be able to figure out which of these is capping your result by looking at your truncated result size. For me, everything kept coming back 4096 characters long, so I new whatever was capping me was set to that.
Also note that "10000" in the example above is not a magic number—adjust it to suit your needs.
You can set the max text size through php.ini like this
mssql.textlimit = 2147483647
mssql.textsize = 2147483647
If you don't have access to php.ini, you can just run this query.
SET TEXTSIZE 2147483647
Another option is just to use ini_set with the values like this
ini_set('mssql.textlimit', '2147483647');
ini_set('mssql.textsize', '2147483647');
If you're going to do it the ini_set way, make sure it's done before a database connection is established.

How to display 'text' data correctly with Microsoft ODBC driver for Linux? Currently displaying as random characters

I am trying to display the contents of a field in a MS SQL database, the data type of which is 'text'. When I connect to the database with MS Excel on a PC the value looks something like:
Shipped on the: 18/10/12 Toll IPEC Connote Number: XXX XXX XXXX
When I connect to the database with PHP using the Microsoft ODBC driver for Linux, the output of the text field will display random characters, which are slightly different each time I run the exact same script. Here is what it output the last four times:
Xisep)!ØwXment.class.php))
5isep)!ment.class.php))
µ}isep)!Ø}ment.class.php))
t)!!Owner_IDt)Ø©Ø8
Not sure where it's getting the 'ment.class.php' bit from. That looks like the end of the name of one of my classes, but not one that is included in this particular script. Is the driver broken or what? All other data types (int, varchar, datetime etc) seem to display correctly, the problem only seems to happen with this one text field.
Here is the code:
<?php
require('ConnectWise.inc.php');
$config = new CW_Config;
// Connect to database
$dbcnx = odbc_connect("ConnectWise", $config->db_username, $config->db_password);
// Query database
$query = "select * from Billing_Log where Invoice_Number = '24011'";
$result = odbc_exec($dbcnx, $query);
while ($row = odbc_fetch_array($result)) {
echo $row['Top_Comment'] . "\n";
}
odbc_close($dbcnx);
Here is the output of my last few attempts:
\3ȶä!!¶äY!
öÈö§!!ö§Y!
&Èö×!!ö×Y!
Looks like you're getting an overflow. For some reason SQL is passing the length of your text field as 0, which to SQL means "long" but to PHP means "I dont know" and so PHP is showing whatever is in its memory at the location its expecting data (or something like that - any PHP experts care to explain?).
I've seen this with varchar(max) before but not text. (Converting to) Text is normally the way to fix it. So maybe I'm wrong.
Hope this is of some help. Im not a PHP developer, I just have to use it occasionally, and this sounds much like a painful experience I've gone through before :)

PHP/json My field names are being truncated to 30 characters. Can I stop this?

Ok so I got this piece of vendor software that they said should be run on an apache php server and MySql database.
I didn't have either of those so I put it on a PHP IIS server and I converted the code to work on SQL server.
ex.
mysql_select_db -> mssql_select_db
(among other things)
So I have the following code in a php file
$query = "SELECT * FROM TableName WHERE KEY_FIELD = '".$keyField."';";
$result = mssql_query($query);
$arr = array();
while ( $obj = mssql_fetch_object($result) )
{
$arr[] = $obj;
}
echo '{"results":'.json_encode($arr).'}';
and my results look something like this (captured with fiddler 2)
{"results":[{"KEY_FIELD":"57", "My30characterlongfieldthatiscu":"GoodValue"}]}
"My30characterlongfieldthatiscu" should be "My30characterlongfieldthatiscutoff"
Kinda weird, no?
The vendor claims that the app works perfectly on their end.
I'm thinking this is some sort of IIS PHP limit, is there a way around it or can I expand it?
I found this solution
http://www.php.net/manual/en/ref.mssql.php#74834
but I don't understand it.
Thanks!
See http://bugs.php.net/bug.php?id=33060 - this is what's causing your issue.
You might also want to consider changing the column names - more than 30 characters sounds excessively long.
http://docs.php.net/manual/en/mssql.requirements says:
Note: On Windows, the DBLIB from Microsoft is used. Functions that return a column name are based on the dbcolname() function in DBLIB. DBLIB was developed for SQL Server 6.x where the max identifier length is 30. For this reason, the maximum column length is 30 characters. On platforms where FreeTDS is used (Linux), this is not a problem.
Is using the sqlsrv extension instead of mssql an option?

Categories