942 lines
23 KiB
PHP
942 lines
23 KiB
PHP
<?php
|
|
|
|
// Numeric values that corresponds to a SQL type:
|
|
define("_SQL_BIGINT", -5);
|
|
define("_SQL_BINARY", -2);
|
|
define("_SQL_BIT", -7);
|
|
define("_SQL_CHAR", 1);
|
|
define("_SQL_TYPE_DATE", 91);
|
|
define("_SQL_TYPE_TIMESTAMP", 93);
|
|
define("_SQL_DECIMAL", 3);
|
|
define("_SQL_FLOAT", 6);
|
|
define("_SQL_LONGVARBINARY", -4);
|
|
define("_SQL_INTEGER", 4);
|
|
define("_SQL_WCHAR", -8);
|
|
define("_SQL_WLONGVARCHAR", -10);
|
|
define("_SQL_NUMERIC", 2);
|
|
define("_SQL_WVARCHAR", -9);
|
|
define("_SQL_REAL", 7);
|
|
define("_SQL_SMALLINT", 5);
|
|
define("_SQL_LONGVARCHAR", -1);
|
|
define("_SQL_TINYINT", -6);
|
|
define("_SQL_VARBINARY", -3);
|
|
define("_SQL_VARCHAR", 12);
|
|
define("_SQL_SS_XML", -152);
|
|
define("_SQL_GUID", -11);
|
|
define("_SQL_SS_TIME2", -154);
|
|
define("_SQL_SS_TIMESTAMPOFFSET", -155);
|
|
|
|
define("_CHUNK_SIZE", 8192);
|
|
define("_EPSILON", 0.00001);
|
|
|
|
function StartTest($testName)
|
|
{
|
|
echo "\n...Starting '$testName' test...\n";
|
|
if (!extension_loaded("sqlsrv"))
|
|
{
|
|
die("sqlsrv driver cannot be loaded.");
|
|
}
|
|
}
|
|
|
|
function EndTest($testName)
|
|
{
|
|
echo "...Test '$testName' completed successfully.\n";
|
|
}
|
|
|
|
function GetTempTableName($table = '', $temporary = true)
|
|
{
|
|
// A temporary table name with the '#' prefix will be automatically
|
|
// dropped once the connection is closed. Otherwise, the caller
|
|
// should take care of dropping the temp table afterwards.
|
|
|
|
$timestamp = round(microtime(true)*1000);
|
|
|
|
$prefix = '';
|
|
if ($temporary)
|
|
$prefix = '#';
|
|
|
|
if (strlen($table) == 0)
|
|
$table = 'php_test_table';
|
|
|
|
return $prefix . $table . '_' . $timestamp;
|
|
}
|
|
|
|
function GetTempProcName($proc = '', $temporary = true)
|
|
{
|
|
// A temporary stored procedure name with the '#' prefix will be
|
|
// automatically dropped once the connection is closed. Otherwise,
|
|
// the caller should take care of dropping the temp procedure afterwards.
|
|
|
|
$timestamp = round(microtime(true)*1000);
|
|
|
|
$prefix = '';
|
|
if ($temporary)
|
|
$prefix = '#';
|
|
|
|
if (strlen($proc) == 0)
|
|
$proc = 'php_test_proc';
|
|
|
|
return $prefix . $proc . '_' . $timestamp;
|
|
}
|
|
|
|
function FatalError($errorMsg)
|
|
{
|
|
handle_errors();
|
|
die($errorMsg);
|
|
}
|
|
|
|
function handle_errors()
|
|
{
|
|
$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
|
|
if(count($errors) == 0)
|
|
{
|
|
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
|
|
}
|
|
$count = count($errors);
|
|
for($i = 0; $i < $count; $i++)
|
|
{
|
|
echo $errors[$i]['message'];
|
|
}
|
|
}
|
|
|
|
function Verify($stmt, $metadata, $numFields, $encoding)
|
|
{
|
|
$i = 0;
|
|
while ($result = sqlsrv_fetch($stmt))
|
|
{
|
|
echo "Comparing data in row " . ++$i . "\n";
|
|
$data = GetInputData($i);
|
|
$dataArray = SimplifyDataArray($data, $metadata, $i);
|
|
for ($j = 0; $j < $numFields; $j++)
|
|
{
|
|
$value = sqlsrv_get_field($stmt, $j, SQLSRV_PHPTYPE_STRING($encoding));
|
|
CompareData($metadata, $i, $j, $value, $dataArray[$j], False, False);
|
|
}
|
|
}
|
|
// returns the number of rows fetched
|
|
return $i;
|
|
}
|
|
|
|
function ConvertDataToString($type, $data)
|
|
{
|
|
if ($data === null)
|
|
return "";
|
|
|
|
// Convert raw data to strings for datetime and binary types only
|
|
// Do nothing for other types
|
|
//
|
|
if (IsDateTime($type))
|
|
{
|
|
if ($type != _SQL_SS_TIME2)
|
|
return date_format( $data, 'Y-m-d H:i:s' );
|
|
else
|
|
return date_format( $data, 'H:i:s' );
|
|
}
|
|
else if (IsBinary($type))
|
|
{
|
|
return bin2hex($data);
|
|
}
|
|
else
|
|
{
|
|
return $data;
|
|
}
|
|
}
|
|
|
|
function CompareCharacterData($actual, $expected, $errorMode = false)
|
|
{
|
|
// $errorMode is true if an error is expected
|
|
$matched = false;
|
|
if ($actual === $expected)
|
|
{
|
|
$matched = true;
|
|
}
|
|
else
|
|
{
|
|
$len = strlen($expected);
|
|
|
|
$result = strncmp($expected, $actual, $len);
|
|
if ($result == 0)
|
|
{
|
|
$matched = true;
|
|
}
|
|
}
|
|
|
|
// echo "Expected: $expected\nActual: $actual\n";
|
|
if ($matched)
|
|
{
|
|
if ($errorMode)
|
|
{
|
|
echo "Data corruption expected...\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (! $errorMode)
|
|
{
|
|
echo "Data corruption!! Expected: $expected\nActual: $actual\n";
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareNumericData($actual, $expected)
|
|
{
|
|
if (! is_numeric($actual))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// only compare up to the length of the expected value, especially for floats
|
|
if (is_float($expected))
|
|
{
|
|
$len = strlen($expected);
|
|
$actual = substr($actual, 0, $len);
|
|
}
|
|
|
|
$f_actual = floatval($actual);
|
|
$f_expected = floatval($expected);
|
|
|
|
$matched = ($f_actual == $f_expected);
|
|
if (! $matched)
|
|
{
|
|
// compare floating point values
|
|
$diff = abs(($f_actual - $f_expected) / $f_expected);
|
|
$matched = ($diff < _EPSILON);
|
|
|
|
if (! $matched)
|
|
{
|
|
echo "Data corruption: values don't match\n";
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CheckData($colType, $actual, $expected)
|
|
{
|
|
$success = true;
|
|
|
|
if (IsNumeric($colType))
|
|
{
|
|
if (! CompareNumericData($actual, $expected))
|
|
{
|
|
$success = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$actual = trim($actual);
|
|
$len = strlen($expected);
|
|
|
|
if (IsDateTime($colType))
|
|
{
|
|
if ($colType != _SQL_SS_TIME2)
|
|
$len = min(strlen("YYYY-MM-DD HH:mm:ss"), $len);
|
|
else
|
|
$len = min(strlen("HH:mm:ss"), $len);
|
|
}
|
|
if (strncasecmp($actual, $expected, $len) != 0)
|
|
{
|
|
$success = false;
|
|
}
|
|
}
|
|
return ($success);
|
|
}
|
|
|
|
function ReadBinaryStream($filename)
|
|
{
|
|
$handle = fopen($filename, "rb");
|
|
$contents = fread($handle, filesize($filename));
|
|
fclose($handle);
|
|
|
|
return $contents;
|
|
}
|
|
|
|
function ToByteArray($input)
|
|
{
|
|
// this should be int[] which can be converted
|
|
// to byte[] in C# since values are range of 0 - 255
|
|
return unpack('C*', $input);
|
|
}
|
|
|
|
function CompareByteArrays($actual, $expected)
|
|
{
|
|
$actualArray = ToByteArray($actual);
|
|
$expectedArray = ToByteArray($expected);
|
|
|
|
echo "Data read:\t";
|
|
print_r($actualArray);
|
|
echo "Expected:\t";
|
|
print_r($expectedArray);
|
|
}
|
|
|
|
function CompareDataStream($colType, $rowIndex, $colName, $stream, $expected)
|
|
{
|
|
$len = strlen($expected);
|
|
$matched = false;
|
|
|
|
if ($len == 0)
|
|
{
|
|
$contents = fread($stream, _CHUNK_SIZE);
|
|
$contents = trim($contents); // removes all whitespace
|
|
if (strlen($contents) == 0)
|
|
{
|
|
$matched = true;
|
|
}
|
|
}
|
|
else if ($len < _CHUNK_SIZE)
|
|
{
|
|
$contents = fread($stream, $len);
|
|
$matched = CompareDataValue($colType, $rowIndex, $colName, $contents, $expected);
|
|
}
|
|
else
|
|
{
|
|
$matched = true;
|
|
$pos = 0;
|
|
while (! feof($stream) && $pos < $len)
|
|
{
|
|
$contents = fread($stream, _CHUNK_SIZE);
|
|
$contents = ConvertDataToString($colType, $contents);
|
|
|
|
$contents_len = strlen($contents);
|
|
$result = substr_compare($expected, $contents, $pos, $contents_len, TRUE);
|
|
if ($result != 0)
|
|
{
|
|
break;
|
|
$matched = false;
|
|
}
|
|
$pos += $contents_len;
|
|
}
|
|
}
|
|
|
|
if (! $matched)
|
|
{
|
|
echo "Data corruption on row $rowIndex column $colName\n";
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareBinaryData($actual, $expected)
|
|
{
|
|
// this function assumes $actual is a stream of hex
|
|
$len = strlen($expected);
|
|
$pos = 0;
|
|
|
|
$matched = true;
|
|
while (! feof($actual) && $pos < $len)
|
|
{
|
|
$contents = fread($actual, _CHUNK_SIZE);
|
|
$result = 0;
|
|
|
|
$str = unpack("H*", $contents);
|
|
|
|
$contents = $str[1];
|
|
$contents_len = strlen($contents);
|
|
|
|
$count = $contents_len;
|
|
if ($len < ($pos + $contents_len))
|
|
{
|
|
$count = $len - $pos;
|
|
}
|
|
$result = substr_compare($expected, $contents, $pos, $count, TRUE);
|
|
if ($result != 0)
|
|
{
|
|
//echo "Expected: " . substr($expected, $pos, $count) . "\nActual: $contents\n";
|
|
$matched = false;
|
|
break;
|
|
}
|
|
|
|
$pos += $count;
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareStreamData($actual, $expected, $isUnicode)
|
|
{
|
|
// this function assumes $actual is a stream of character data
|
|
$matched = true;
|
|
|
|
// convert $expected to UCS-2LE (Little Endian)
|
|
$str = iconv("UTF-8", "UCS-2LE", $expected);
|
|
|
|
// every character of $str consists of two bytes but if
|
|
// it's unicode, the character of data is also two bytes
|
|
|
|
$shift = 1;
|
|
if ($isUnicode)
|
|
$shift = 2;
|
|
|
|
$len = strlen($str);
|
|
$pos = 0;
|
|
while ($matched && ! feof($actual) && $pos < $len)
|
|
{
|
|
$contents = fread($actual, _CHUNK_SIZE);
|
|
$contents_len = strlen($contents);
|
|
|
|
$i = 0;
|
|
while ($matched && $i < $contents_len && $pos < $len)
|
|
{
|
|
if ($contents[$i] != $str[$pos])
|
|
{
|
|
//echo "Expected at [$pos]: $str[$pos]\nActual at [$i]: $contents[$i]\n";
|
|
$matched = false;
|
|
break;
|
|
}
|
|
$pos += 2;
|
|
$i += $shift;
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareBinaryStream($metadata, $rowIndex, $colIndex, $actual, $expected)
|
|
{
|
|
// unlike CompareDataStream(), this method assumes $actual is a stream
|
|
// and no non-updatable fields (timestamp column)
|
|
|
|
if (is_null($actual))
|
|
{
|
|
if ($expected === "")
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
$colName = $metadata[$colIndex]['Name'];
|
|
$colType = $metadata[$colIndex]['Type'];
|
|
|
|
$matched = false;
|
|
if (IsBinary($colType))
|
|
{
|
|
$matched = CompareBinaryData($actual, $expected);
|
|
}
|
|
else
|
|
{
|
|
// stream of characters
|
|
$matched = CompareStreamData($actual, $expected, IsUnicode($colType));
|
|
}
|
|
|
|
if (! $matched)
|
|
{
|
|
echo "Data not matching on row $rowIndex column $colName\n";
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareStringToFile($rowIndex, $colName, $actual, $file, $isBinary)
|
|
{
|
|
$matched = true;
|
|
$pos = 0;
|
|
while ($matched && ! feof($file))
|
|
{
|
|
$expected = fread($file, _CHUNK_SIZE);
|
|
if ($isBinary)
|
|
{
|
|
$str = unpack("H*", $expected);
|
|
$expected = $str[1];
|
|
}
|
|
$len = strlen($expected);
|
|
|
|
$contents = substr($actual, $pos, $len);
|
|
$result = strcasecmp($expected, $contents);
|
|
|
|
$matched = ($result == 0);
|
|
$pos += $len;
|
|
}
|
|
|
|
if (! $matched)
|
|
{
|
|
echo "Data not matching on row $rowIndex column $colName\n";
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareStreamToFile($rowIndex, $colName, $stream, $file, $colType)
|
|
{
|
|
// This function is complicated because it's comparing two stream data
|
|
// one from stream resource and one from a file
|
|
// Moreover, the data can be binary or character/unicode character
|
|
|
|
$isBinary = IsBinary($colType);
|
|
|
|
$matched = true;
|
|
while ($matched && ! feof($file) && ! feof ($stream))
|
|
{
|
|
$expected = fread($file, _CHUNK_SIZE);
|
|
$actual = fread($stream, _CHUNK_SIZE);
|
|
|
|
if ($isBinary)
|
|
{
|
|
$str = unpack("H*", $expected);
|
|
$expected = $str[1];
|
|
|
|
$str = unpack("H*", $actual);
|
|
$actual = $str[1];
|
|
|
|
$matched = ($expected == $actual);
|
|
}
|
|
else
|
|
{
|
|
// not reading binary hex data here
|
|
// similar to CompareStreamData(), except comparing two chunks at a time
|
|
// first convert $expected to UCS-2LE (Little Endian)
|
|
$expected = iconv("UTF-8", "UCS-2LE", $expected);
|
|
|
|
// every character of $expected consists of two bytes but if
|
|
// it's unicode, the character of data is also two bytes
|
|
|
|
$shift = 1;
|
|
if (IsUnicode($colType))
|
|
$shift = 2;
|
|
|
|
$i = 0;
|
|
$pos = 0;
|
|
$data_len = strlen($actual);
|
|
while ($matched && $i < $data_len)
|
|
{
|
|
if ($actual[$i] != $expected[$pos])
|
|
{
|
|
echo "Expected at [$pos]: $expected[$pos]\nActual at [$i]: $actual[$i]\n";
|
|
$matched = false;
|
|
break;
|
|
}
|
|
$pos += 2;
|
|
$i += $shift;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! $matched)
|
|
{
|
|
echo "Data not matching on row $rowIndex column $colName\n";
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, $bConvert = true)
|
|
{
|
|
if ($bConvert)
|
|
{
|
|
$actual = ConvertDataToString($colType, $actual);
|
|
}
|
|
$matched = CheckData($colType, $actual, $expected);
|
|
if (! $matched)
|
|
{
|
|
echo "Data corruption on row $rowIndex column $colName\n";
|
|
echo "Expected: $expected\nActual: $actual\n";
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function CompareData($metadata, $rowIndex, $colIndex, $actual, $expected, $isStream, $bConvert = true)
|
|
{
|
|
if (is_null($actual))
|
|
{
|
|
if ($expected === "")
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
$colName = $metadata[$colIndex]['Name'];
|
|
$colType = $metadata[$colIndex]['Type'];
|
|
|
|
if ($actual === false)
|
|
{
|
|
FatalError("Field $colName of row $rowIndex is missing\n");
|
|
}
|
|
if (! IsUpdatable($colName))
|
|
{
|
|
return true; // do nothing for non-IsUpdatable fields
|
|
}
|
|
|
|
if ($isStream)
|
|
{
|
|
return CompareDataStream($colType, $rowIndex, $colName, $actual, $expected);
|
|
}
|
|
else
|
|
{
|
|
return CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, $bConvert);
|
|
}
|
|
}
|
|
|
|
function CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, $readStream)
|
|
{
|
|
$isBinary = IsBinary($colType);
|
|
$mode = ($isBinary)? "rb" : "r";
|
|
$file = fopen($filename, $mode);
|
|
|
|
echo "...reading LOB data from '$filename'...";
|
|
|
|
$matched = false;
|
|
if ($readStream)
|
|
{
|
|
$matched = CompareStreamToFile($rowIndex, $colName, $actual, $file, $colType);
|
|
}
|
|
else
|
|
{
|
|
$matched = CompareStringToFile($rowIndex, $colName, $actual, $file, $isBinary);
|
|
}
|
|
|
|
fclose($file);
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function VerifyLOBData($metadata, $rowIndex, $colIndex, $lobColumn, $actual, $expected, $filename, $readStream)
|
|
{
|
|
$colName = $metadata[$colIndex]['Name'];
|
|
$colType = $metadata[$colIndex]['Type'];
|
|
|
|
$matched = false;
|
|
if ($readStream && IsStreamable($colType))
|
|
{
|
|
if ($colIndex != $lobColumn)
|
|
{
|
|
echo "...reading binary stream...";
|
|
$matched = CompareBinaryStream($metadata, $rowIndex, $colIndex, $actual, $expected);
|
|
}
|
|
else
|
|
{
|
|
$matched = CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($colIndex != $lobColumn)
|
|
{
|
|
echo "...reading string value...";
|
|
$matched = CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, false);
|
|
}
|
|
else
|
|
{
|
|
$matched = CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, false);
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function SimplifyDataArray($data, $metadata, $row)
|
|
{
|
|
$dataArray = array();
|
|
$numFields = count($metadata);
|
|
|
|
$skipCount = 0;
|
|
for ($j = 0; $j < $numFields; $j++)
|
|
{
|
|
$colName = $metadata[$j]['Name'];
|
|
$colType = $metadata[$j]['Type'];
|
|
|
|
if (!IsUpdatable($colName))
|
|
{
|
|
$skipCount++;
|
|
array_push($dataArray, "");
|
|
}
|
|
else
|
|
{
|
|
// only need the first element of each array
|
|
$value = $data[$j - $skipCount][0];
|
|
if (is_a($value, 'DateTime'))
|
|
{
|
|
$value = date_format( $value, 'Y-m-d H:i:s' );
|
|
}
|
|
|
|
array_push($dataArray, $value);
|
|
}
|
|
}
|
|
|
|
return $dataArray;
|
|
}
|
|
|
|
function InsertDataToArray($query, $metadata, $row)
|
|
{
|
|
$dataArray = array();
|
|
$numFields = count($metadata);
|
|
|
|
$skipCount = 0;
|
|
for ($j = 0; $j < $numFields; $j++)
|
|
{
|
|
$colName = $metadata[$j]['Name'];
|
|
$type = $metadata[$j]['Type'];
|
|
|
|
$col = $j + 1;
|
|
if (!IsUpdatable($colName))
|
|
{
|
|
$skipCount++;
|
|
array_push($dataArray, "");
|
|
}
|
|
else
|
|
{
|
|
$data = GetInsertData($query, $type, $row, $col, $skipCount);
|
|
array_push($dataArray, $data);
|
|
}
|
|
}
|
|
|
|
return $dataArray;
|
|
}
|
|
|
|
function GetInsertData($query, $colType, $rowIndex, $colIndex, $skip)
|
|
{
|
|
$data = strstr($query, "((");
|
|
$pos = 1;
|
|
if ($data === false)
|
|
{
|
|
die("Failed to retrieve data on row $rowIndex");
|
|
}
|
|
$data = substr($data, 2);
|
|
|
|
while ($pos < ($colIndex - $skip))
|
|
{
|
|
$data = strstr($data, ", (");
|
|
$pos++;
|
|
|
|
if ($data === false)
|
|
{
|
|
die("Failed to retrieve data on column $pos");
|
|
}
|
|
$data = substr($data, 3);
|
|
}
|
|
|
|
// Is it's XML type, we can't use the closing bracket as the next delimiter
|
|
// because a bracket can be part of the xml data, unless the data is null
|
|
$str = ")";
|
|
$pos = strpos($data, $str);
|
|
if ($pos === false)
|
|
{
|
|
die("Failed to isolate data on row $rowIndex, column $pos");
|
|
}
|
|
$tmp = substr($data, 0, $pos);
|
|
if ((strcasecmp($tmp, "null") == 0) || strlen($tmp) == 0)
|
|
{
|
|
$tmp = "";
|
|
}
|
|
else if (IsXml($colType))
|
|
{
|
|
$str = ">')";
|
|
$pos = strpos($data, $str);
|
|
$tmp = substr($data, 0, $pos + 2);
|
|
}
|
|
|
|
$data = $tmp;
|
|
|
|
if (IsDataUnicode($colType, $data)) // this includes unicode data type and XML data that is in Unicode
|
|
{ // N'data'
|
|
$data = substr($data, 2, strlen($data) - 3);
|
|
}
|
|
else if (IsLiteral($colType))
|
|
{ // 'data'
|
|
$data = substr($data, 1, strlen($data) - 2);
|
|
}
|
|
else if (IsBinary($colType))
|
|
{ // 0xdata
|
|
$data = substr($data, 2);
|
|
}
|
|
|
|
return (trim($data));
|
|
}
|
|
|
|
function IsStreamable($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_CHAR: // char
|
|
return true;
|
|
case _SQL_WCHAR: // nchar
|
|
return true;
|
|
case _SQL_VARCHAR: // varchar
|
|
return true;
|
|
case _SQL_WVARCHAR: // nvarchar
|
|
return true;
|
|
case _SQL_LONGVARCHAR: // text
|
|
return true;
|
|
case _SQL_WLONGVARCHAR: // ntext
|
|
return true;
|
|
case _SQL_BINARY: // binary
|
|
return true;
|
|
case _SQL_VARBINARY: // varbinary
|
|
return true;
|
|
case _SQL_LONGVARBINARY: // image
|
|
return true;
|
|
case _SQL_SS_XML: // xml
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsNumeric($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_INTEGER : // int
|
|
return true;
|
|
case _SQL_TINYINT : // tinyint
|
|
return true;
|
|
case _SQL_SMALLINT : // smallint
|
|
return true;
|
|
case _SQL_BIGINT : // bigint
|
|
return true;
|
|
case _SQL_BIT : // bit
|
|
return true;
|
|
case _SQL_FLOAT : // float
|
|
return true;
|
|
case _SQL_REAL : // real
|
|
return true;
|
|
case _SQL_DECIMAL : // decimal
|
|
return true;
|
|
case _SQL_NUMERIC : // numeric, money, smallmoney
|
|
return true;
|
|
default: break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsChar($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_WCHAR: // nchar
|
|
return true;
|
|
case _SQL_VARCHAR: // varchar
|
|
return true;
|
|
case _SQL_WVARCHAR: // nvarchar
|
|
return true;
|
|
case _SQL_LONGVARCHAR: // text
|
|
return true;
|
|
case _SQL_WLONGVARCHAR: // ntext
|
|
return true;
|
|
case _SQL_SS_XML: // xml
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsBinary($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_BINARY: // binary
|
|
return true;
|
|
case _SQL_VARBINARY: // varbinary
|
|
return true;
|
|
case _SQL_LONGVARBINARY: // image
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsDateTime($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_TYPE_TIMESTAMP: // datetime, smalldatetime
|
|
return true;
|
|
case _SQL_TYPE_DATE: // date
|
|
return true;
|
|
case _SQL_SS_TIME2: // time
|
|
return true;
|
|
case _SQL_SS_TIMESTAMPOFFSET: // datetimeoffset
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsDataUnicode($colType, $data)
|
|
{
|
|
if (IsUnicode($colType))
|
|
return true;
|
|
|
|
// This input string may be an XML string in unicode (i.e. // N'<xmldata>...</xmldata>')
|
|
$letterN = 'N';
|
|
$index = strpos($data, $letterN);
|
|
|
|
// Note the use of ===. Simply == would not work as expected
|
|
// because the position of letterN 'N' may be the 0th (first) character
|
|
// and strpos will return false if not found.
|
|
if ($index === 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function IsUnicode($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_WCHAR: // nchar
|
|
return true;
|
|
case _SQL_WVARCHAR: // nvarchar
|
|
return true;
|
|
case _SQL_WLONGVARCHAR: // ntext
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
function IsXml($type)
|
|
{
|
|
return ($type == _SQL_SS_XML);
|
|
}
|
|
|
|
function IsUpdatable($colName)
|
|
{
|
|
$pos = strpos($colName, "_");
|
|
$type = substr($colName, $pos + 1);
|
|
|
|
return (strcasecmp($type, "timestamp") != 0);
|
|
}
|
|
|
|
function IsLiteral($type)
|
|
{
|
|
switch ($type)
|
|
{
|
|
case _SQL_CHAR: // char
|
|
return true;
|
|
case _SQL_WCHAR: // nchar
|
|
return true;
|
|
case _SQL_VARCHAR: // varchar
|
|
return true;
|
|
case _SQL_WVARCHAR: // nvarchar
|
|
return true;
|
|
case _SQL_LONGVARCHAR: // text
|
|
return true;
|
|
case _SQL_WLONGVARCHAR: // ntext
|
|
return true;
|
|
case _SQL_GUID: // uniqueidentifier
|
|
return true;
|
|
case _SQL_TYPE_TIMESTAMP: // datetime, smalldatetime
|
|
return true;
|
|
case _SQL_TYPE_DATE: // date
|
|
return true;
|
|
case _SQL_SS_TIME2: // time
|
|
return true;
|
|
case _SQL_SS_TIMESTAMPOFFSET: // datetimeoffset
|
|
return true;
|
|
case _SQL_SS_XML: // xml
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
?>
|