Skip to content

Commit

Permalink
Fix mssql concurrent insert id
Browse files Browse the repository at this point in the history
The implementation of db_insert_id() in mssql relied on IDENT_CURRENT
making it not thread safe.
Modify it to use ADOdb native implementation, based on SCOPE_IDENTITY()
which is session independent.

Fixes: #25442
  • Loading branch information
cproensa authored and atrol committed Feb 11, 2019
1 parent 6dd420c commit c0c7eb1
Showing 1 changed file with 22 additions and 13 deletions.
35 changes: 22 additions & 13 deletions core/database_api.php
Expand Up @@ -451,32 +451,41 @@ function db_result( $p_result, $p_row_index = 0, $p_col_index = 0 ) {
}

/**
* return the last inserted id for a specific database table
* Return the last inserted ID after a insert statement.
* Warning: this function must be used immediately after the insert statement
*
* This relies on ADOdb to get the entity id when this functionality is available
* for the specific driver, and it makes sense in our model.
* Natively supported:
* - mysqli, using: mysqli_insert_id(connection).
* - mssqlnative, using SCOPE_IDENTITY().
* Not natively supported:
* - pgsql, oracle, using the underlying sequence for the table.
*
* Since the table is needed for those drivers where a sequence is used, the
* $p_table parameter is mandatory to ensure portability.
* Warning: $p_table is not expected to be a different table than the one used
* for the previous insert. Note that it's not even used by some drivers.
*
* @param string $p_table A valid database table name.
* @param string $p_field A valid field name (default 'id').
* @return integer last successful insert id
*/
function db_insert_id( $p_table = null, $p_field = 'id' ) {
function db_insert_id( $p_table, $p_field = 'id' ) {
global $g_db, $g_db_functional_type;

if( isset( $p_table ) ) {
switch( $g_db_functional_type ) {
switch( $g_db_functional_type ) {
case DB_TYPE_ORACLE:
$t_query = 'SELECT seq_' . $p_table . '.CURRVAL FROM DUAL';
break;
case DB_TYPE_PGSQL:
$t_query = 'SELECT currval(\'' . $p_table . '_' . $p_field . '_seq\')';
break;
case DB_TYPE_MSSQL:
$t_query = 'SELECT IDENT_CURRENT(\'' . $p_table . '\')';
break;
}
if( isset( $t_query ) ) {
$t_result = db_query( $t_query );
return (int)db_result( $t_result );
}
default:
return $g_db->Insert_ID();
}
return $g_db->Insert_ID();
$t_result = db_query( $t_query );
return (int)db_result( $t_result );
}

/**
Expand Down

0 comments on commit c0c7eb1

Please sign in to comment.