in source/shared/core_stmt.cpp [3475:3579]
bool sqlsrv_param_tvp::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
{
if (sql_data_type != SQL_SS_TABLE) {
// This is one of the constituent columns of the table-valued parameter
// Check current_row first
if (current_row >= num_rows) {
return false;
}
// Find the row from the TVP data based on current_row
zval* row_z = zend_hash_index_find(Z_ARRVAL_P(parent_tvp->param_ptr_z), current_row);
if (Z_ISREF_P(row_z)) {
ZVAL_DEREF(row_z);
}
// Now find the column value based on param_pos
zval* value_z = zend_hash_index_find(Z_ARRVAL_P(row_z), param_pos);
// First check if value_z is NULL
if (Z_TYPE_P(value_z) == IS_NULL) {
core::SQLPutData(stmt, NULL, SQL_NULL_DATA);
current_row++;
} else {
switch (param_php_type) {
case IS_RESOURCE:
{
num_bytes_read = 0;
param_stream = NULL;
// Get the stream from the zval value
core::sqlsrv_php_stream_from_zval_no_verify(*stmt, param_stream, value_z);
// Keep sending the packets until EOF is reached
while (sqlsrv_param::send_data_packet(stmt)) {
}
current_row++;
}
break;
case IS_OBJECT:
{
// This method updates placeholder_z as a string
bool succeeded = convert_datetime_to_string(stmt, value_z);
// Conversion failed so assume the input was an invalid PHP type
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1) {
throw core::CoreException();
}
core::SQLPutData(stmt, Z_STRVAL(placeholder_z), SQL_NTS);
current_row++;
}
break;
case IS_STRING:
{
int type = Z_TYPE_P(value_z);
if (type != IS_STRING) {
convert_to_string(value_z);
}
SQLLEN value_len = Z_STRLEN_P(value_z);
if (value_len == 0) {
// If it's an empty string
core::SQLPutData(stmt, Z_STRVAL_P(value_z), 0);
} else {
if (encoding == CP_UTF8 && !is_a_numeric_type(sql_data_type)) {
if (value_len > INT_MAX) {
LOG(SEV_ERROR, "Convert input parameter to utf16: buffer length exceeded.");
throw core::CoreException();
}
// This method would change the member placeholder_z
bool succeeded = convert_input_str_to_utf16(stmt, value_z);
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_STRING_ENCODING_TRANSLATE, parent_tvp->param_pos + 1, param_pos + 1, get_last_error_message()) {
throw core::CoreException();
}
send_string_data_in_batches(stmt, &placeholder_z);
} else {
send_string_data_in_batches(stmt, value_z);
}
}
current_row++;
}
break;
default:
// Do nothing for basic types as they should be processed elsewhere
break;
}
} // else not IS_NULL
} else {
// This is the table-valued parameter
if (current_row < num_rows) {
// Loop through the table parameter columns and populate each cell's placeholder whenever applicable
for (size_t i = 0; i < tvp_columns.size(); i++) {
tvp_columns[i]->populate_cell_placeholder(stmt, current_row);
}
// This indicates a TVP row is available
core::SQLPutData(stmt, reinterpret_cast<SQLPOINTER>(1), 1);
current_row++;
} else {
// This indicates there is no more TVP row
core::SQLPutData(stmt, reinterpret_cast<SQLPOINTER>(0), 0);
}
}
// Return false to indicate that the current row has been sent
return false;
}