'use strict';
var crypto = require( 'crypto' );
/**
* Class representing a prepared statement
*
* @constructor
* @param {Connection} conn - Connection object
* @param {object} [opts] - Constructor options
* @param {boolean} [opts.reusable=true] - Flag to indicate whether this statement
* should be reusable.
*/
var Statement = function ( conn, opts ) {
// privileged data
this.$ = {
conn : conn,
id : false,
ifx : conn.ifx()
};
this.options( opts );
};
/**
* Return the context ID associated with this statement
*
* @return {string} - Context ID
*/
Statement.prototype.context = function () {
return this.$.opts.context;
};
/**
* Execute the prepared statement
*
* @param {string|Array} [args] - Arguments to be used when executing the
* prepared statement.
* @return {Promise.<Cursor, Error>} - A promise to a results cursor object or
* an Error if rejected.
*/
Statement.prototype.exec = function ( args ) {
var self = this;
return self.$.conn.acquire( self.context() )
.then( function ( conn ) {
return new Promise( function ( resolve, reject ) {
var Cursor = require( './cursor' );
var cursor = new Cursor( self.$.conn, self );
if ( args !== undefined ) {
self.$.ifx.exec( conn.id(), self.$.id, cursor.id(), args, function ( err, curid ) {
if ( err ) {
return reject( err );
}
self.$.conn.release( self.context() );
resolve( cursor );
} );
} else {
self.$.ifx.exec( conn.id(), self.$.id, cursor.id(), function ( err, curid ) {
if ( err ) {
return reject( err );
}
self.$.conn.release( self.context() );
resolve( cursor );
} );
}
} );
} )
.catch( function ( err ) {
self.$.conn.release( self.context() );
throw err;
} );
};
/**
* Return statement flags
*
* @return {object} flags - Statement flags
* @return {boolean} flags.reusable - Flag to indicate whether this statement
* should be reusable.
*/
Statement.prototype.flags = function () {
var flags = {
reusable : ( this.$.opts.reusable === false ? false : true )
};
return flags;
};
/**
* Free the prepared statement
*
* @return {Promise.<string, Error>} - A promise to a string which would
* contain the statement ID freed or an Error if rejected.
*/
Statement.prototype.free = function () {
var self = this;
return self.$.conn.acquire( self.context() )
.then( function ( conn ) {
return new Promise( function ( resolve, reject ) {
self.$.ifx.free( conn.id(), self.$.id, function ( err, stmtid ) {
if ( err ) {
return reject( err );
}
self.$.conn.release( self.context() );
resolve( stmtid );
} );
} );
} )
.catch( function ( err ) {
self.$.conn.release( self.context() );
throw err;
} );
};
/**
* Set options
*
* @param {object} opts - Options
*/
Statement.prototype.options = function ( opts ) {
this.$.opts = opts || {};
if ( (typeof this.$.opts.id) === 'string' ) {
this.$.id = this.$.opts.id;
}
};
/**
* Prepare a statement
*
* @param {string} sql - SQL statement to prepare
* @return {Promise.<Statement, Error>} - A promise to a statement object or an
* Error if rejected.
*/
Statement.prototype.prepare = function ( sql ) {
var self = this;
return self.$.conn.acquire( self.context() )
.then( function ( conn ) {
return new Promise( function ( resolve, reject ) {
if (! self.$.id ) {
self.$.id = '_' + crypto.createHash( 'sha256' ).update( sql ).digest( 'hex' );
}
self.$.ifx.prepare( conn.id(), self.$.id, sql, function ( err, stmtid ) {
if ( err ) {
return reject( err );
}
self.$.conn.release( self.context() );
resolve( self );
} );
} );
} )
.catch( function ( err ) {
self.$.conn.release( self.context() );
throw err;
} );
};
module.exports = Statement;