<commit_before>// ***************************************************************************
// Copyright (c) 2014 SAP AG or an SAP affiliate company. All rights reserved.
// ***************************************************************************
#include "utils.h"

using namespace v8;

SQLAnywhereInterface api;
unsigned openConnections = 0;
uv_mutex_t api_mutex;

extern Persistent<String> HashToString( Local<Object> obj );

struct executeBaton {
    Persistent<Function> 		callback;
    bool 				err;
    std::string 			error_msg;
    bool 				callback_required;
    
    Connection 				*obj;
    a_sqlany_stmt 			*sqlany_stmt;
    std::string				stmt;
    std::vector<char*> 			string_vals;
    std::vector<double*> 		num_vals;
    std::vector<int*> 			int_vals;
    std::vector<size_t*> 		string_len;
    std::vector<a_sqlany_bind_param> 	params;
    
    std::vector<char*> 			colNames;
    int 				rows_affected;
    std::vector<a_sqlany_data_type> 	col_types;

    executeBaton() {
	err = false;
	callback_required = false;
	obj = NULL;
	sqlany_stmt = NULL;
	rows_affected = -1;
    }

    ~executeBaton() {
	obj = NULL;
	// the StmtObject will free sqlany_stmt
	sqlany_stmt = NULL;
	CLEAN_STRINGS( string_vals );
	CLEAN_STRINGS( colNames );
	CLEAN_NUMS( num_vals );
	CLEAN_NUMS( int_vals );
	CLEAN_NUMS( string_len );
	col_types.clear();

	for( size_t i = 0; i < params.size(); i++ ) {
	    if( params[i].value.is_null != NULL ) {
		delete params[i].value.is_null;
		params[i].value.is_null = NULL;
	    }
        }
	params.clear();
    }
};

bool fillResult( executeBaton *baton, Local<Value> &ResultSet ) 
{
    
    if( baton->err ) {
	callBack( &( baton->error_msg ), baton->callback, Local<Value>::New( Undefined() ), baton->callback_required );
	return false;
    }
    
    if( !getResultSet( ResultSet, baton->rows_affected, baton->colNames, baton->string_vals, baton->num_vals, baton->int_vals, baton->string_len, baton->col_types ) ) {
	getErrorMsg( JS_ERR_RESULTSET, baton->error_msg );
	callBack( &( baton->error_msg ), baton->callback , Local<Value>::New( Undefined() ), baton->callback_required );
	return false;
    }
    
    callBack( NULL, baton->callback, ResultSet,  baton->callback_required );
    return true;
}

void executeWork( uv_work_t *req ) 
{
    executeBaton *baton = static_cast<executeBaton*>(req->data);
    scoped_lock lock( baton->obj->conn_mutex );
    
   if( baton->obj->conn == NULL ) {
	baton->err = true;
	getErrorMsg( JS_ERR_NOT_CONNECTED, baton->error_msg );
	return;
    }
    
    if( baton->sqlany_stmt == NULL && baton->stmt.length() > 0 ) {
	baton->sqlany_stmt = api.sqlany_prepare( baton->obj->conn, baton->stmt.c_str() );
	if( baton->sqlany_stmt == NULL ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
	
    } else if( baton->sqlany_stmt == NULL ) {
	baton->err = true;
	getErrorMsg( JS_ERR_INVALID_OBJECT, baton->error_msg );
	return;
    }
    
    if( !api.sqlany_reset( baton->sqlany_stmt) ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }

    for( unsigned int i = 0; i < baton->params.size(); i++ ) {
	a_sqlany_bind_param 	param;
	
	if( !api.sqlany_describe_bind_param( baton->sqlany_stmt, i, &param ) ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
	
	param.value.type = baton->params[i].value.type;
	param.value.buffer = baton->params[i].value.buffer;
	
	if( param.value.type == A_STRING || param.value.type == A_BINARY ) {
	    param.value.length = baton->params[i].value.length;
	    param.value.buffer_size = baton->params[i].value.buffer_size;
	}
	
	if( baton->params[i].value.is_null != NULL ) {
	    param.value.is_null = baton->params[i].value.is_null;
	}
	
	if( !api.sqlany_bind_param( baton->sqlany_stmt, i, &param ) ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
    }
    
    sacapi_bool success_execute = api.sqlany_execute( baton->sqlany_stmt );
    CLEAN_STRINGS( baton->string_vals );
    CLEAN_NUMS( baton->int_vals );
    CLEAN_NUMS( baton->num_vals );
    baton->string_len.clear();
    
    if( !success_execute ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }
    
    if( !fetchResultSet( baton->sqlany_stmt, baton->rows_affected, baton->colNames, baton->string_vals, baton->num_vals, baton->int_vals, baton->string_len, baton->col_types ) ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }
}

void executeAfter( uv_work_t *req ) 
{
    executeBaton *baton = static_cast<executeBaton*>( req->data );
    Local<Value> ResultSet;
    fillResult( baton, ResultSet );

    scoped_lock	lock( baton->obj->conn_mutex );

    if( baton->sqlany_stmt != NULL ) {
     	api.sqlany_free_stmt( baton->sqlany_stmt );
	baton->sqlany_stmt = NULL;
    }

    delete baton;
    delete req;
}

Handle<Value> StmtObject::exec( const Arguments &args ) 
{<commit_msg>Fixes #3<commit_after>// ***************************************************************************
// Copyright (c) 2014 SAP AG or an SAP affiliate company. All rights reserved.
// ***************************************************************************
#include "utils.h"

using namespace v8;

SQLAnywhereInterface api;
unsigned openConnections = 0;
uv_mutex_t api_mutex;

extern Persistent<String> HashToString( Local<Object> obj );

struct executeBaton {
    Persistent<Function> 		callback;
    bool 				err;
    std::string 			error_msg;
    bool 				callback_required;
    
    Connection 				*obj;
    a_sqlany_stmt 			*sqlany_stmt;
    std::string				stmt;
    std::vector<char*> 			string_vals;
    std::vector<double*> 		num_vals;
    std::vector<int*> 			int_vals;
    std::vector<size_t*> 		string_len;
    std::vector<a_sqlany_bind_param> 	params;
    
    std::vector<char*> 			colNames;
    int 				rows_affected;
    std::vector<a_sqlany_data_type> 	col_types;

    executeBaton() {
	err = false;
	callback_required = false;
	obj = NULL;
	sqlany_stmt = NULL;
	rows_affected = -1;
    }

    ~executeBaton() {
	obj = NULL;
	// the StmtObject will free sqlany_stmt
	sqlany_stmt = NULL;
	CLEAN_STRINGS( string_vals );
	CLEAN_STRINGS( colNames );
	CLEAN_NUMS( num_vals );
	CLEAN_NUMS( int_vals );
	CLEAN_NUMS( string_len );
	col_types.clear();

	for( size_t i = 0; i < params.size(); i++ ) {
	    if( params[i].value.is_null != NULL ) {
		delete params[i].value.is_null;
		params[i].value.is_null = NULL;
	    }
        }
	params.clear();
    }
};

bool fillResult( executeBaton *baton, Local<Value> &ResultSet ) 
{
    
    if( baton->err ) {
	callBack( &( baton->error_msg ), baton->callback, Local<Value>::New( Undefined() ), baton->callback_required );
	return false;
    }
    
    if( !getResultSet( ResultSet, baton->rows_affected, baton->colNames, baton->string_vals, baton->num_vals, baton->int_vals, baton->string_len, baton->col_types ) ) {
	getErrorMsg( JS_ERR_RESULTSET, baton->error_msg );
	callBack( &( baton->error_msg ), baton->callback , Local<Value>::New( Undefined() ), baton->callback_required );
	return false;
    }
    
    callBack( NULL, baton->callback, ResultSet,  baton->callback_required );
    return true;
}

void executeWork( uv_work_t *req ) 
{
    executeBaton *baton = static_cast<executeBaton*>(req->data);
    scoped_lock lock( baton->obj->conn_mutex );
    
   if( baton->obj->conn == NULL ) {
	baton->err = true;
	getErrorMsg( JS_ERR_NOT_CONNECTED, baton->error_msg );
	return;
    }
    
    if( baton->sqlany_stmt == NULL && baton->stmt.length() > 0 ) {
	baton->sqlany_stmt = api.sqlany_prepare( baton->obj->conn, baton->stmt.c_str() );
	if( baton->sqlany_stmt == NULL ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
	
    } else if( baton->sqlany_stmt == NULL ) {
	baton->err = true;
	getErrorMsg( JS_ERR_INVALID_OBJECT, baton->error_msg );
	return;
    }
    
    if( !api.sqlany_reset( baton->sqlany_stmt) ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }

    for( unsigned int i = 0; i < baton->params.size(); i++ ) {
	a_sqlany_bind_param 	param;
	
	if( !api.sqlany_describe_bind_param( baton->sqlany_stmt, i, &param ) ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
	
	param.value.type = baton->params[i].value.type;
	param.value.buffer = baton->params[i].value.buffer;
	
	if( param.value.type == A_STRING || param.value.type == A_BINARY ) {
	    param.value.length = baton->params[i].value.length;
	    param.value.buffer_size = baton->params[i].value.buffer_size;
	}
	
	if( baton->params[i].value.is_null != NULL ) {
	    param.value.is_null = baton->params[i].value.is_null;
	}
	
	if( !api.sqlany_bind_param( baton->sqlany_stmt, i, &param ) ) {
	    baton->err = true;
	    getErrorMsg( baton->obj->conn, baton->error_msg );
	    return;
	}
    }
    
    sacapi_bool success_execute = api.sqlany_execute( baton->sqlany_stmt );
    CLEAN_STRINGS( baton->string_vals );
    CLEAN_NUMS( baton->int_vals );
    CLEAN_NUMS( baton->num_vals );
    baton->string_len.clear();
    
    if( !success_execute ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }
    
    if( !fetchResultSet( baton->sqlany_stmt, baton->rows_affected, baton->colNames, baton->string_vals, baton->num_vals, baton->int_vals, baton->string_len, baton->col_types ) ) {
	baton->err = true;
	getErrorMsg( baton->obj->conn, baton->error_msg );
	return;
    }
}

void executeAfter( uv_work_t *req ) 
{
    executeBaton *baton = static_cast<executeBaton*>( req->data );
    Local<Value> ResultSet;
    fillResult( baton, ResultSet );

    scoped_lock	lock( baton->obj->conn_mutex );

    if( baton->sqlany_stmt != NULL ) {
      if( api.initialized ) {
     	    api.sqlany_free_stmt( baton->sqlany_stmt );
      }
	baton->sqlany_stmt = NULL;
    }

    delete baton;
    delete req;
}

Handle<Value> StmtObject::exec( const Arguments &args ) 
{
{'fraction_non_alphanumeric': 0.17316274918179114, 'fraction_numerical': 0.0020827134781315083, 'mean_word_length': 3.513876454789615, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 213, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7349398', 'n_tokens_mistral': 3855, 'n_tokens_neox': 3695, 'n_words': 657}