limber-firebird-client
Version:
Cliente JavaScript/Typescrypt para Node.js de acesso a banco de dados Firebird charset ISO8859_1 e UTF8
1,684 lines (1,405 loc) • 179 kB
JavaScript
const
net = require('net'),
os = require('os'),
path = require('path'),
Events = require('events'),
Stream = require('stream'),
messages = require('./messages.js'),
crypt = require('./unix-crypt.js'),
serialize = require('./serialize.js'),
errors = require('./errors.js'),
XdrReader = serialize.XdrReader,
BlrReader = serialize.BlrReader,
XdrWriter = serialize.XdrWriter,
BlrWriter = serialize.BlrWriter,
BitSet = serialize.BitSet,
GDSError = errors.GDSError;
/**
* Parse date from string
* @return {Date}
*/
if (String.prototype.parseDate === undefined) {
String.prototype.parseDate = function () {
var self = this.trim();
var arr = self.indexOf(' ') === -1 ? self.split('T') : self.split(' ');
var index = arr[0].indexOf(':');
var length = arr[0].length;
if (index !== -1) {
var tmp = arr[1];
arr[1] = arr[0];
arr[0] = tmp;
}
if (arr[0] === undefined) {
arr[0] = '';
}
var noTime = arr[1] === undefined ? true : arr[1].length === 0;
for (var i = 0; i < length; i++) {
var c = arr[0].charCodeAt(i);
if (c > 47 && c < 58) {
continue;
}
if (c === 45 || c === 46) {
continue;
}
if (noTime) {
return new Date(self);
}
}
if (arr[1] === undefined) {
arr[1] = '00:00:00';
}
var firstDay = arr[0].indexOf('-') === -1;
var date = (arr[0] || '').split(firstDay ? '.' : '-');
var time = (arr[1] || '').split(':');
var parsed = [];
if (date.length < 4 && time.length < 2) {
return new Date(self);
}
index = (time[2] || '').indexOf('.');
// milliseconds
if (index !== -1) {
time[3] = time[2].substring(index + 1);
time[2] = time[2].substring(0, index);
} else {
time[3] = '0';
}
parsed.push(parseInt(date[firstDay ? 2 : 0], 10)); // year
parsed.push(parseInt(date[1], 10)); // month
parsed.push(parseInt(date[firstDay ? 0 : 2], 10)); // day
parsed.push(parseInt(time[0], 10)); // hours
parsed.push(parseInt(time[1], 10)); // minutes
parsed.push(parseInt(time[2], 10)); // seconds
parsed.push(parseInt(time[3], 10)); // miliseconds
var def = new Date();
for (i = 0, length = parsed.length; i < length; i++) {
if (isNaN(parsed[i])) {
parsed[i] = 0;
}
var value = parsed[i];
if (value !== 0) {
continue;
}
switch (i) {
case 0:
if (value <= 0) {
parsed[i] = def.getFullYear();
}
break;
case 1:
if (value <= 0) {
parsed[i] = def.getMonth() + 1;
}
break;
case 2:
if (value <= 0) {
parsed[i] = def.getDate();
}
break;
}
}
return new Date(parsed[0], parsed[1] - 1, parsed[2], parsed[3], parsed[4], parsed[5]);
};
}
function noop() {
}
const
MAX_BUFFER_SIZE = 8192;
const
op_void = 0, // Packet has been voided
op_connect = 1, // Connect to remote server
op_exit = 2, // Remote end has exitted
op_accept = 3, // Server accepts connection
op_reject = 4, // Server rejects connection
op_disconnect = 6, // Connect is going away
op_response = 9, // Generic response block
// Full context server operations
op_attach = 19, // Attach database
op_create = 20, // Create database
op_detach = 21, // Detach database
op_compile = 22, // Request based operations
op_start = 23,
op_start_and_send = 24,
op_send = 25,
op_receive = 26,
op_unwind = 27, // apparently unused, see protocol.cpp's case op_unwind
op_release = 28,
op_transaction = 29, // Transaction operations
op_commit = 30,
op_rollback = 31,
op_prepare = 32,
op_reconnect = 33,
op_create_blob = 34, // Blob operations
op_open_blob = 35,
op_get_segment = 36,
op_put_segment = 37,
op_cancel_blob = 38,
op_close_blob = 39,
op_info_database = 40, // Information services
op_info_request = 41,
op_info_transaction = 42,
op_info_blob = 43,
op_batch_segments = 44, // Put a bunch of blob segments
op_que_events = 48, // Que event notification request
op_cancel_events = 49, // Cancel event notification request
op_commit_retaining = 50, // Commit retaining (what else)
op_prepare2 = 51, // Message form of prepare
op_event = 52, // Completed event request (asynchronous)
op_connect_request = 53, // Request to establish connection
op_aux_connect = 54, // Establish auxiliary connection
op_ddl = 55, // DDL call
op_open_blob2 = 56,
op_create_blob2 = 57,
op_get_slice = 58,
op_put_slice = 59,
op_slice = 60, // Successful response to op_get_slice
op_seek_blob = 61, // Blob seek operation
// DSQL operations
op_allocate_statement = 62, // allocate a statment handle
op_execute = 63, // execute a prepared statement
op_exec_immediate = 64, // execute a statement
op_fetch = 65, // fetch a record
op_fetch_response = 66, // response for record fetch
op_free_statement = 67, // free a statement
op_prepare_statement = 68, // prepare a statement
op_set_cursor = 69, // set a cursor name
op_info_sql = 70,
op_dummy = 71, // dummy packet to detect loss of client
op_response_piggyback = 72, // response block for piggybacked messages
op_start_and_receive = 73,
op_start_send_and_receive = 74,
op_exec_immediate2 = 75, // execute an immediate statement with msgs
op_execute2 = 76, // execute a statement with msgs
op_insert = 77,
op_sql_response = 78, // response from execute, exec immed, insert
op_transact = 79,
op_transact_response = 80,
op_drop_database = 81,
op_service_attach = 82,
op_service_detach = 83,
op_service_info = 84,
op_service_start = 85,
op_rollback_retaining = 86,
op_partial = 89, // packet is not complete - delay processing
op_trusted_auth = 90,
op_cancel = 91,
op_cont_auth = 92,
op_ping = 93,
op_accept_data = 94, // Server accepts connection and returns some data to client
op_abort_aux_connection = 95, // Async operation - stop waiting for async connection to arrive
op_crypt = 96,
op_crypt_key_callback = 97,
op_cond_accept = 98; // Server accepts connection, returns some data to client
// and asks client to continue authentication before attach call
const
CONNECT_VERSION2 = 2,
CONNECT_VERSION3 = 3,
ARCHITECTURE_GENERIC = 1;
const
// Protocol 10 includes support for warnings and removes the requirement for
// encoding and decoding status codes
PROTOCOL_VERSION10 = 10,
// Since protocol 11 we must be separated from Borland Interbase.
// Therefore always set highmost bit in protocol version to 1.
// For unsigned protocol version this does not break version's compare.
FB_PROTOCOL_FLAG = 0x8000,
FB_PROTOCOL_MASK = ~FB_PROTOCOL_FLAG & 0xFFFF,
// Protocol 11 has support for user authentication related
// operations (op_update_account_info, op_authenticate_user and
// op_trusted_auth). When specific operation is not supported,
// we say "sorry".
PROTOCOL_VERSION11 = (FB_PROTOCOL_FLAG | 11),
// Protocol 12 has support for asynchronous call op_cancel.
// Currently implemented asynchronously only for TCP/IP.
PROTOCOL_VERSION12 = (FB_PROTOCOL_FLAG | 12),
// Protocol 13 has support for authentication plugins (op_cont_auth).
PROTOCOL_VERSION13 = (FB_PROTOCOL_FLAG | 13),
PROTOCOL_VERSION15 = (FB_PROTOCOL_FLAG | 15),
PROTOCOL_VERSION16 = (FB_PROTOCOL_FLAG | 16);
const
CNCT_user = 1, // User name
CNCT_passwd = 2,
// CNCT_ppo = 3, // Apollo person, project, organization. OBSOLETE.
CNCT_host = 4,
CNCT_group = 5, // Effective Unix group id
CNCT_user_verification = 6, // Attach/create using this connection will use user verification
CNCT_specific_data = 7, // Some data, needed for user verification on server
CNCT_plugin_name = 8, // Name of plugin, which generated that data
CNCT_login = 9, // Same data as isc_dpb_user_name
CNCT_plugin_list = 10, // List of plugins, available on client
CNCT_client_crypt = 11, // Client encyption level (DISABLED/ENABLED/REQUIRED)
WIRE_CRYPT_DISABLED = 0,
WIRE_CRYPT_ENABLED = 1,
WIRE_CRYPT_REQUIRED = 2;
const
DSQL_close = 1,
DSQL_drop = 2,
DSQL_unprepare = 4; // >= 2.5
// Protocols types (accept_type)
const
ptype_rpc = 2, // Simple remote procedure call
ptype_batch_send = 3, // Batch sends, no asynchrony
ptype_out_of_band = 4, // Batch sends w/ out of band notification
ptype_lazy_send = 5, // Deferred packets delivery;
ptype_mask = 0xFF, // Mask - up to 255 types of protocol
pflag_compress = 0x100; // Turn on compression if possible
const SUPPORTED_PROTOCOL = [
// [PROTOCOL_VERSION10, ARCHITECTURE_GENERIC, ptype_rpc, ptype_batch_send, 1],
// [PROTOCOL_VERSION11, ARCHITECTURE_GENERIC, ptype_lazy_send, ptype_lazy_send, 2],
[PROTOCOL_VERSION12, ARCHITECTURE_GENERIC, ptype_batch_send, ptype_batch_send, 3],
[PROTOCOL_VERSION13, ARCHITECTURE_GENERIC, ptype_batch_send, ptype_batch_send, 4],
[PROTOCOL_VERSION15, ARCHITECTURE_GENERIC, ptype_batch_send, ptype_batch_send, 5],
[PROTOCOL_VERSION16, ARCHITECTURE_GENERIC, ptype_batch_send, ptype_batch_send, 6],
];
const
SQL_TEXT = 452, // Array of char
SQL_VARYING = 448,
SQL_SHORT = 500,
SQL_LONG = 496,
SQL_FLOAT = 482,
SQL_DOUBLE = 480,
SQL_D_FLOAT = 530,
SQL_TIMESTAMP = 510,
SQL_BLOB = 520,
SQL_ARRAY = 540,
SQL_QUAD = 550,
SQL_TYPE_TIME = 560,
SQL_TYPE_DATE = 570,
SQL_INT64 = 580,
SQL_BOOLEAN = 32764, // >= 3.0
SQL_NULL = 32766, // >= 2.5
SQL_TIMESTAMP_TZ = 32754, // 4.0
SQL_TIME_TZ = 32756; // 4.0
/***********************/
/* ISC Services */
/***********************/
const
isc_action_svc_backup = 1, /* Starts database backup process on the server */
isc_action_svc_restore = 2, /* Starts database restore process on the server */
isc_action_svc_repair = 3, /* Starts database repair process on the server */
isc_action_svc_add_user = 4, /* Adds a new user to the security database */
isc_action_svc_delete_user = 5, /* Deletes a user record from the security database */
isc_action_svc_modify_user = 6, /* Modifies a user record in the security database */
isc_action_svc_display_user = 7, /* Displays a user record from the security database */
isc_action_svc_properties = 8, /* Sets database properties */
isc_action_svc_add_license = 9, /* Adds a license to the license file */
isc_action_svc_remove_license = 10, /* Removes a license from the license file */
isc_action_svc_db_stats = 11, /* Retrieves database statistics */
isc_action_svc_get_ib_log = 12, /* Retrieves the InterBase log file from the server */
isc_action_svc_get_fb_log = isc_action_svc_get_ib_log, /* Retrieves the Firebird log file from the server */
isc_action_svc_nbak = 20, /* start nbackup */
isc_action_svc_nrest = 21, /* start nrestore */
isc_action_svc_trace_start = 22,
isc_action_svc_trace_stop = 23,
isc_action_svc_trace_suspend = 24,
isc_action_svc_trace_resume = 25,
isc_action_svc_trace_list = 26;
const
isc_info_svc_svr_db_info = 50, /* Retrieves the number of attachments and databases */
isc_info_svc_get_license = 51, /* Retrieves all license keys and IDs from the license file */
isc_info_svc_get_license_mask = 52, /* Retrieves a bitmask representing licensed options on the server */
isc_info_svc_get_config = 53, /* Retrieves the parameters and values for IB_CONFIG */
isc_info_svc_version = 54, /* Retrieves the version of the services manager */
isc_info_svc_server_version = 55, /* Retrieves the version of the InterBase server */
isc_info_svc_implementation = 56, /* Retrieves the implementation of the InterBase server */
isc_info_svc_capabilities = 57, /* Retrieves a bitmask representing the server's capabilities */
isc_info_svc_user_dbpath = 58, /* Retrieves the path to the security database in use by the server */
isc_info_svc_get_env = 59, /* Retrieves the setting of $INTERBASE */
isc_info_svc_get_env_lock = 60, /* Retrieves the setting of $INTERBASE_LCK */
isc_info_svc_get_env_msg = 61, /* Retrieves the setting of $INTERBASE_MSG */
isc_info_svc_line = 62, /* Retrieves 1 line of service output per call */
isc_info_svc_to_eof = 63, /* Retrieves as much of the server output as will fit in the supplied buffer */
isc_info_svc_timeout = 64, /* Sets / signifies a timeout value for reading service information */
isc_info_svc_get_licensed_users = 65, /* Retrieves the number of users licensed for accessing the server */
isc_info_svc_limbo_trans = 66, /* Retrieve the limbo transactions */
isc_info_svc_running = 67, /* Checks to see if a service is running on an attachment */
isc_info_svc_get_users = 68, /* Returns the user information from isc_action_svc_display_users */
isc_info_svc_stdin = 78;
/* Services Properties */
const
isc_spb_prp_page_buffers = 5,
isc_spb_prp_sweep_interval = 6,
isc_spb_prp_shutdown_db = 7,
isc_spb_prp_deny_new_attachments = 9,
isc_spb_prp_deny_new_transactions = 10,
isc_spb_prp_reserve_space = 11,
isc_spb_prp_write_mode = 12,
isc_spb_prp_access_mode = 13,
isc_spb_prp_set_sql_dialect = 14,
isc_spb_num_att = 5,
isc_spb_num_db = 6,
// SHUTDOWN OPTION FOR 2.0
isc_spb_prp_force_shutdown = 41,
isc_spb_prp_attachments_shutdown = 42,
isc_spb_prp_transactions_shutdown = 43,
isc_spb_prp_shutdown_mode = 44,
isc_spb_prp_online_mode = 45,
isc_spb_prp_sm_normal = 0,
isc_spb_prp_sm_multi = 1,
isc_spb_prp_sm_single = 2,
isc_spb_prp_sm_full = 3,
// WRITE_MODE_PARAMETERS
isc_spb_prp_wm_async = 37,
isc_spb_prp_wm_sync = 38,
// ACCESS_MODE_PARAMETERS
isc_spb_prp_am_readonly = 39,
isc_spb_prp_am_readwrite = 40,
// RESERVE_SPACE_PARAMETERS
isc_spb_prp_res_use_full = 35,
isc_spb_prp_res = 36,
// Option Flags
isc_spb_prp_activate = 0x0100,
isc_spb_prp_db_online = 0x0200;
// SHUTDOWN MODE
/* · Backup Service ·*/
const
isc_spb_bkp_file = 5,
isc_spb_bkp_factor = 6,
isc_spb_bkp_length = 7,
isc_spb_bkp_ignore_checksums = 0x01,
isc_spb_bkp_ignore_limbo = 0x02,
isc_spb_bkp_metadata_only = 0x04,
isc_spb_bkp_no_garbage_collect = 0x08,
isc_spb_bkp_old_descriptions = 0x10,
isc_spb_bkp_non_transportable = 0x20,
isc_spb_bkp_convert = 0x40,
isc_spb_bkp_expand = 0x80,
isc_spb_bkp_no_triggers = 0x8000,
// nbackup
isc_spb_nbk_level = 5,
isc_spb_nbk_file = 6,
isc_spb_nbk_direct = 7,
isc_spb_nbk_no_triggers = 0x01;
/* Restore Service ·*/
const
isc_spb_res_buffers = 9,
isc_spb_res_page_size = 10,
isc_spb_res_length = 11,
isc_spb_res_access_mode = 12,
isc_spb_res_fix_fss_data = 13,
isc_spb_res_fix_fss_metadata = 14,
isc_spb_res_am_readonly = isc_spb_prp_am_readonly,
isc_spb_res_am_readwrite = isc_spb_prp_am_readwrite,
isc_spb_res_deactivate_idx = 0x0100,
isc_spb_res_no_shadow = 0x0200,
isc_spb_res_no_validity = 0x0400,
isc_spb_res_one_at_a_time = 0x0800,
isc_spb_res_replace = 0x1000,
isc_spb_res_create = 0x2000,
isc_spb_res_use_all_space = 0x4000;
/* · Repair Service ·*/
const
isc_spb_rpr_commit_trans = 15,
isc_spb_rpr_rollback_trans = 34,
isc_spb_rpr_recover_two_phase = 17,
isc_spb_tra_id = 18,
isc_spb_single_tra_id = 19,
isc_spb_multi_tra_id = 20,
isc_spb_tra_state = 21,
isc_spb_tra_state_limbo = 22,
isc_spb_tra_state_commit = 23,
isc_spb_tra_state_rollback = 24,
isc_spb_tra_state_unknown = 25,
isc_spb_tra_host_site = 26,
isc_spb_tra_remote_site = 27,
isc_spb_tra_db_path = 28,
isc_spb_tra_advise = 29,
isc_spb_tra_advise_commit = 30,
isc_spb_tra_advise_rollback = 31,
isc_spb_tra_advise_unknown = 33,
isc_spb_rpr_validate_db = 0x01,
isc_spb_rpr_sweep_db = 0x02,
isc_spb_rpr_mend_db = 0x04,
isc_spb_rpr_list_limbo_trans = 0x08,
isc_spb_rpr_check_db = 0x10,
isc_spb_rpr_ignore_checksum = 0x20,
isc_spb_rpr_kill_shadows = 0x40,
isc_spb_rpr_full = 0x80,
isc_spb_rpr_icu = 0x0800;
/* · Security Service ·*/
const
isc_spb_sec_userid = 5,
isc_spb_sec_groupid = 6,
isc_spb_sec_username = 7,
isc_spb_sec_password = 8,
isc_spb_sec_groupname = 9,
isc_spb_sec_firstname = 10,
isc_spb_sec_middlename = 11,
isc_spb_sec_lastname = 12,
isc_spb_sec_admin = 13;
/* License Service */
const
isc_spb_lic_key = 5,
isc_spb_lic_id = 6,
isc_spb_lic_desc = 7;
/* Statistics Service */
const
isc_spb_sts_data_pages = 0x01,
isc_spb_sts_db_log = 0x02,
isc_spb_sts_hdr_pages = 0x04,
isc_spb_sts_idx_pages = 0x08,
isc_spb_sts_sys_relations = 0x10,
isc_spb_sts_record_versions = 0x20,
isc_spb_sts_table = 0x40,
isc_spb_sts_nocreation = 0x80;
/* Trace Service */
const
isc_spb_trc_id = 1,
isc_spb_trc_name = 2,
isc_spb_trc_cfg = 3;
/***********************/
/* ISC Error Codes */
/***********************/
const
isc_arg_end = 0, // end of argument list
isc_arg_gds = 1, // generic DSRI status value
isc_arg_string = 2, // string argument
isc_arg_cstring = 3, // count & string argument
isc_arg_number = 4, // numeric argument (long)
isc_arg_interpreted = 5, // interpreted status code (string)
isc_arg_unix = 7, // UNIX error code
isc_arg_next_mach = 15, // NeXT/Mach error code
isc_arg_win32 = 17, // Win32 error code
isc_arg_warning = 18, // warning argument
isc_arg_sql_state = 19; // SQLSTATE
const
isc_sqlerr = 335544436;
/**********************************/
/* Database parameter block stuff */
/**********************************/
const
isc_dpb_version1 = 1,
isc_dpb_version2 = 2, // >= FB30
isc_dpb_cdd_pathname = 1,
isc_dpb_allocation = 2,
isc_dpb_journal = 3,
isc_dpb_page_size = 4,
isc_dpb_num_buffers = 5,
isc_dpb_buffer_length = 6,
isc_dpb_debug = 7,
isc_dpb_garbage_collect = 8,
isc_dpb_verify = 9,
isc_dpb_sweep = 10,
isc_dpb_enable_journal = 11,
isc_dpb_disable_journal = 12,
isc_dpb_dbkey_scope = 13,
isc_dpb_number_of_users = 14,
isc_dpb_trace = 15,
isc_dpb_no_garbage_collect = 16,
isc_dpb_damaged = 17,
isc_dpb_license = 18,
isc_dpb_sys_user_name = 19,
isc_dpb_encrypt_key = 20,
isc_dpb_activate_shadow = 21,
isc_dpb_sweep_interval = 22,
isc_dpb_delete_shadow = 23,
isc_dpb_force_write = 24,
isc_dpb_begin_log = 25,
isc_dpb_quit_log = 26,
isc_dpb_no_reserve = 27,
isc_dpb_user_name = 28,
isc_dpb_password = 29,
isc_dpb_password_enc = 30,
isc_dpb_sys_user_name_enc = 31,
isc_dpb_interp = 32,
isc_dpb_online_dump = 33,
isc_dpb_old_file_size = 34,
isc_dpb_old_num_files = 35,
isc_dpb_old_file = 36,
isc_dpb_old_start_page = 37,
isc_dpb_old_start_seqno = 38,
isc_dpb_old_start_file = 39,
isc_dpb_old_dump_id = 41,
isc_dpb_lc_messages = 47,
isc_dpb_lc_ctype = 48,
isc_dpb_cache_manager = 49,
isc_dpb_shutdown = 50,
isc_dpb_online = 51,
isc_dpb_shutdown_delay = 52,
isc_dpb_reserved = 53,
isc_dpb_overwrite = 54,
isc_dpb_sec_attach = 55,
isc_dpb_connect_timeout = 57,
isc_dpb_dummy_packet_interval = 58,
isc_dpb_gbak_attach = 59,
isc_dpb_sql_role_name = 60,
isc_dpb_set_page_buffers = 61,
isc_dpb_working_directory = 62,
isc_dpb_sql_dialect = 63,
isc_dpb_set_db_readonly = 64,
isc_dpb_set_db_sql_dialect = 65,
isc_dpb_gfix_attach = 66,
isc_dpb_gstat_attach = 67,
isc_dpb_set_db_charset = 68,
isc_dpb_gsec_attach = 69,
isc_dpb_address_path = 70,
isc_dpb_process_id = 71,
isc_dpb_no_db_triggers = 72,
isc_dpb_trusted_auth = 73,
isc_dpb_process_name = 74,
isc_dpb_trusted_role = 75,
isc_dpb_org_filename = 76,
isc_dpb_utf8_filename = 77,
isc_dpb_ext_call_depth = 78,
// Firebird 3.0 constants
isc_dpb_auth_block = 79,
isc_dpb_client_version = 80,
isc_dpb_remote_protocol = 81,
isc_dpb_host_name = 82,
isc_dpb_os_user = 83,
isc_dpb_specific_auth_data = 84,
isc_dpb_auth_plugin_list = 85,
isc_dpb_auth_plugin_name = 86,
isc_dpb_config = 87,
isc_dpb_nolinger = 88,
isc_dpb_reset_icu = 89,
isc_dpb_map_attach = 90,
// Firebird 4 constants
isc_dpb_session_time_zone = 91,
isc_dpb_set_db_replica = 92,
isc_dpb_set_bind = 93,
isc_dpb_decfloat_round = 94,
isc_dpb_decfloat_traps = 95;
/*************************************/
/* Services parameter block stuff */
/*************************************/
const
isc_spb_version1 = 1,
isc_spb_current_version = 2,
isc_spb_version = isc_spb_current_version,
isc_spb_user_name = isc_dpb_user_name,
isc_spb_sys_user_name = isc_dpb_sys_user_name,
isc_spb_sys_user_name_enc = isc_dpb_sys_user_name_enc,
isc_spb_password = isc_dpb_password,
isc_spb_password_enc = isc_dpb_password_enc,
isc_spb_command_line = 105,
isc_spb_dbname = 106,
isc_spb_verbose = 107,
isc_spb_options = 108,
isc_spb_address_path = 109,
isc_spb_process_id = 110,
isc_spb_trusted_auth = 111,
// This will not be used in protocol 13, therefore may be reused
isc_spb_specific_auth_data = isc_spb_trusted_auth,
isc_spb_process_name = 112,
isc_spb_trusted_role = 113,
isc_spb_verbint = 114,
isc_spb_auth_block = 115,
isc_spb_auth_plugin_name = 116,
isc_spb_auth_plugin_list = 117,
isc_spb_utf8_filename = 118,
isc_spb_client_version = 119,
isc_spb_remote_protocol = 120,
isc_spb_host_name = 121,
isc_spb_os_user = 122,
isc_spb_config = 123,
isc_spb_expected_db = 124;
/*************************************/
/* Transaction parameter block stuff */
/*************************************/
const
isc_tpb_version1 = 1,
isc_tpb_version3 = 3,
isc_tpb_consistency = 1,
isc_tpb_concurrency = 2,
isc_tpb_shared = 3, // < FB21
isc_tpb_protected = 4, // < FB21
isc_tpb_exclusive = 5, // < FB21
isc_tpb_wait = 6,
isc_tpb_nowait = 7,
isc_tpb_read = 8,
isc_tpb_write = 9,
isc_tpb_lock_read = 10,
isc_tpb_lock_write = 11,
isc_tpb_verb_time = 12,
isc_tpb_commit_time = 13,
isc_tpb_ignore_limbo = 14,
isc_tpb_read_committed = 15,
isc_tpb_autocommit = 16,
isc_tpb_rec_version = 17,
isc_tpb_no_rec_version = 18,
isc_tpb_restart_requests = 19,
isc_tpb_no_auto_undo = 20,
isc_tpb_lock_timeout = 21; // >= FB20
/****************************/
/* Common, structural codes */
/****************************/
const
isc_info_end = 1,
isc_info_truncated = 2,
isc_info_error = 3,
isc_info_data_not_ready = 4,
isc_info_length = 126,
isc_info_flag_end = 127;
/*************************/
/* SQL information items */
/*************************/
const
isc_info_sql_select = 4,
isc_info_sql_bind = 5,
isc_info_sql_num_variables = 6,
isc_info_sql_describe_vars = 7,
isc_info_sql_describe_end = 8,
isc_info_sql_sqlda_seq = 9,
isc_info_sql_message_seq = 10,
isc_info_sql_type = 11,
isc_info_sql_sub_type = 12,
isc_info_sql_scale = 13,
isc_info_sql_length = 14,
isc_info_sql_null_ind = 15,
isc_info_sql_field = 16,
isc_info_sql_relation = 17,
isc_info_sql_owner = 18,
isc_info_sql_alias = 19,
isc_info_sql_sqlda_start = 20,
isc_info_sql_stmt_type = 21,
isc_info_sql_get_plan = 22,
isc_info_sql_records = 23,
isc_info_sql_batch_fetch = 24,
isc_info_sql_relation_alias = 25, // >= 2.0
isc_info_sql_explain_plan = 26; // >= 3.0
/*******************/
/* Blr definitions */
/*******************/
const
blr_text = 14,
blr_text2 = 15,
blr_short = 7,
blr_long = 8,
blr_quad = 9,
blr_float = 10,
blr_double = 27,
blr_d_float = 11,
blr_timestamp = 35,
blr_varying = 37,
blr_varying2 = 38,
blr_blob = 261,
blr_cstring = 40,
blr_cstring2 = 41,
blr_blob_id = 45,
blr_sql_date = 12,
blr_sql_time = 13,
blr_int64 = 16,
blr_blob2 = 17, // >= 2.0
blr_domain_name = 18, // >= 2.1
blr_domain_name2 = 19, // >= 2.1
blr_not_nullable = 20, // >= 2.1
blr_column_name = 21, // >= 2.5
blr_column_name2 = 22, // >= 2.5
blr_bool = 23, // >= 3.0
blr_version4 = 4,
blr_version5 = 5, // dialect 3
blr_eoc = 76,
blr_end = 255,
blr_assignment = 1,
blr_begin = 2,
blr_dcl_variable = 3,
blr_message = 4;
const
isc_info_sql_stmt_select = 1,
isc_info_sql_stmt_insert = 2,
isc_info_sql_stmt_update = 3,
isc_info_sql_stmt_delete = 4,
isc_info_sql_stmt_ddl = 5,
isc_info_sql_stmt_get_segment = 6,
isc_info_sql_stmt_put_segment = 7,
isc_info_sql_stmt_exec_procedure = 8,
isc_info_sql_stmt_start_trans = 9,
isc_info_sql_stmt_commit = 10,
isc_info_sql_stmt_rollback = 11,
isc_info_sql_stmt_select_for_upd = 12,
isc_info_sql_stmt_set_generator = 13,
isc_info_sql_stmt_savepoint = 14;
const
isc_blob_text = 1;
const DESCRIBE = [
isc_info_sql_stmt_type,
isc_info_sql_select,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
isc_info_sql_relation,
//isc_info_sql_owner,
isc_info_sql_alias,
isc_info_sql_describe_end,
isc_info_sql_bind,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_describe_end
];
const
ISOLATION_READ_UNCOMMITTED = [isc_tpb_version3, isc_tpb_write, isc_tpb_wait, isc_tpb_read_committed, isc_tpb_no_rec_version],
ISOLATION_READ_COMMITED_NO_WAIT = [isc_tpb_version3, isc_tpb_write, isc_tpb_nowait, isc_tpb_read_committed, isc_tpb_rec_version],
ISOLATION_READ_COMMITED = [isc_tpb_version3, isc_tpb_write, isc_tpb_wait, isc_tpb_read_committed, isc_tpb_rec_version],
ISOLATION_REPEATABLE_READ = [isc_tpb_version3, isc_tpb_write, isc_tpb_wait, isc_tpb_concurrency],
ISOLATION_SERIALIZABLE = [isc_tpb_version3, isc_tpb_write, isc_tpb_wait, isc_tpb_consistency],
ISOLATION_READ_COMMITED_READ_ONLY = [isc_tpb_version3, isc_tpb_read, isc_tpb_wait, isc_tpb_read_committed, isc_tpb_no_rec_version];
const
DEFAULT_HOST = '127.0.0.1',
DEFAULT_PORT = 3050,
DEFAULT_USER = 'SYSDBA',
DEFAULT_PASSWORD = 'masterkey',
DEFAULT_LOWERCASE_KEYS = false,
DEFAULT_PAGE_SIZE = 4096,
DEFAULT_SVC_NAME = 'service_mgr';
const AUTH_PLUGIN_LEGACY = 'Legacy_Auth';
const
AUTH_PLUGIN_LIST = [AUTH_PLUGIN_LEGACY],
LEGACY_AUTH_SALT = '9z';
exports.ISOLATION_READ_UNCOMMITTED = ISOLATION_READ_UNCOMMITTED;
exports.ISOLATION_READ_COMMITED_NO_WAIT = ISOLATION_READ_COMMITED_NO_WAIT;
exports.ISOLATION_READ_COMMITED = ISOLATION_READ_COMMITED;
exports.ISOLATION_REPEATABLE_READ = ISOLATION_REPEATABLE_READ;
exports.ISOLATION_SERIALIZABLE = ISOLATION_SERIALIZABLE;
exports.ISOLATION_READ_COMMITED_READ_ONLY = ISOLATION_READ_COMMITED_READ_ONLY;
/**
* Escape value
* @param {Object} value
* @return {String}
*/
exports.escape = function (value) {
if (value === null || value === undefined) {
return 'NULL';
}
switch (typeof (value)) {
case 'boolean':
return value ? '1' : '0';
case 'number':
return value.toString();
case 'string':
return "'" + value.replace(/'/g, "''").replace(/\\/g, '\\\\') + "'";
}
if (value instanceof Date) {
return "'" + value.getFullYear() + '-' + (value.getMonth() + 1).toString().padStart(2, '0') + '-' + value.getDate().toString().padStart(2, '0') + ' ' + value.getHours().toString().padStart(2, '0') + ':' + value.getMinutes().toString().padStart(2, '0') + ':' + value.getSeconds().toString().padStart(2, '0') + '.' + value.getMilliseconds().toString().padStart(3, '0') + "'";
}
throw new Error('Escape supports only primitive values.');
};
const
DEFAULT_FETCHSIZE = 600,
DEFAULT_FETCHSIZE_BLOB = 60;
const
BLOB_MAX = 16384;
const
MAX_INT = Math.pow(2, 31) - 1,
MIN_INT = -Math.pow(2, 31);
/***************************************
*
* SQLVar
*
***************************************/
const
ScaleDivisor = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000];
const
DateOffset = 40587,
TimeCoeff = 86400000,
MsPerMinute = 60000;
//------------------------------------------------------
function SQLVarText() {
}
SQLVarText.prototype.decode = function (data, lowerV13, encoding) {
let ret;
if (this.subType > 1) {
ret = data.readText(this.length, encoding);
} else {
ret = data.readBuffer(this.length);
}
if (!lowerV13 || !data.readInt()) {
if (Buffer.isBuffer(ret)) {
return ret.toString(encoding).trim();
} else if (ret) {
return ret.trim();
} else {
return ret;
}
}
return null;
};
SQLVarText.prototype.calcBlr = function (blr) {
blr.addByte(blr_text);
blr.addWord(this.length);
};
//------------------------------------------------------
function SQLVarNull() {
}
SQLVarNull.prototype = new SQLVarText();
SQLVarNull.prototype.constructor = SQLVarNull;
//------------------------------------------------------
function SQLVarString() {
}
SQLVarString.prototype.decode = function (data, lowerV13, encoding) {
let ret;
if (this.subType > 1) {
ret = data.readString(encoding);
} else {
ret = data.readBuffer();
}
if (!lowerV13 || !data.readInt()) {
if (Buffer.isBuffer(ret)) {
return ret.toString(encoding).trim();
} else if (ret) {
return ret.trim();
} else {
return ret;
}
}
return null;
};
SQLVarString.prototype.calcBlr = function (blr) {
blr.addByte(blr_varying);
blr.addWord(this.length);
};
//------------------------------------------------------
function SQLVarQuad() {
}
SQLVarQuad.prototype.decode = function (data, lowerV13) {
var ret = data.readQuad();
if (!lowerV13 || !data.readInt()) {
return ret;
}
return null;
};
SQLVarQuad.prototype.calcBlr = function (blr) {
blr.addByte(blr_quad);
blr.addShort(this.scale);
};
//------------------------------------------------------
function SQLVarBlob() {
}
SQLVarBlob.prototype = new SQLVarQuad();
SQLVarBlob.prototype.constructor = SQLVarBlob;
SQLVarBlob.prototype.calcBlr = function (blr) {
blr.addByte(blr_quad);
blr.addShort(0);
};
//------------------------------------------------------
function SQLVarArray() {
}
SQLVarArray.prototype = new SQLVarQuad();
SQLVarArray.prototype.constructor = SQLVarArray;
SQLVarArray.prototype.calcBlr = function (blr) {
blr.addByte(blr_quad);
blr.addShort(0);
};
//------------------------------------------------------
function SQLVarInt() {
}
SQLVarInt.prototype.decode = function (data, lowerV13) {
var ret = data.readInt();
if (this.scale) {
ret = ret / ScaleDivisor[Math.abs(this.scale)];
}
if (!lowerV13 || !data.readInt()) {
return ret;
}
return null;
};
SQLVarInt.prototype.calcBlr = function (blr) {
blr.addByte(blr_long);
blr.addShort(this.scale);
};
//------------------------------------------------------
function SQLVarShort() {
}
SQLVarShort.prototype = new SQLVarInt();
SQLVarShort.prototype.constructor = SQLVarShort;
SQLVarShort.prototype.calcBlr = function (blr) {
blr.addByte(blr_short);
blr.addShort(this.scale);
};
//------------------------------------------------------
function SQLVarInt64() {
}
SQLVarInt64.prototype.decode = function (data, lowerV13) {
var ret = data.readInt64();
if (this.scale) {
ret = ret / ScaleDivisor[Math.abs(this.scale)];
}
if (!lowerV13 || !data.readInt()) {
return ret;
}
return null;
};
SQLVarInt64.prototype.calcBlr = function (blr) {
blr.addByte(blr_int64);
blr.addShort(this.scale);
};
//------------------------------------------------------
function SQLVarFloat() {
}
SQLVarFloat.prototype.decode = function (data, lowerV13) {
var ret = data.readFloat();
if (!lowerV13 || !data.readInt()) {
return ret;
}
return null;
};
SQLVarFloat.prototype.calcBlr = function (blr) {
blr.addByte(blr_float);
};
//------------------------------------------------------
function SQLVarDouble() {
}
SQLVarDouble.prototype.decode = function (data, lowerV13) {
var ret = data.readDouble();
if (!lowerV13 || !data.readInt()) {
return ret;
}
return null;
};
SQLVarDouble.prototype.calcBlr = function (blr) {
blr.addByte(blr_double);
};
//------------------------------------------------------
function SQLVarDate() {
}
SQLVarDate.prototype.decode = function (data, lowerV13) {
var ret = data.readInt();
if (!lowerV13 || !data.readInt()) {
var d = new Date(0);
d.setMilliseconds((ret - DateOffset) * TimeCoeff + d.getTimezoneOffset() * MsPerMinute);
return d;
}
return null;
};
SQLVarDate.prototype.calcBlr = function (blr) {
blr.addByte(blr_sql_date);
};
//------------------------------------------------------
function SQLVarTime() {
}
SQLVarTime.prototype.decode = function (data, lowerV13) {
var ret = data.readUInt();
if (!lowerV13 || !data.readInt()) {
var d = new Date(0);
d.setMilliseconds(Math.floor(ret / 10) + d.getTimezoneOffset() * MsPerMinute);
return d;
}
return null;
};
SQLVarTime.prototype.calcBlr = function (blr) {
blr.addByte(blr_sql_time);
};
//------------------------------------------------------
function SQLVarTimeStamp() {
}
SQLVarTimeStamp.prototype.decode = function (data, lowerV13) {
var date = data.readInt();
var time = data.readUInt();
if (!lowerV13 || !data.readInt()) {
var d = new Date(0);
d.setMilliseconds((date - DateOffset) * TimeCoeff + Math.floor(time / 10) + d.getTimezoneOffset() * MsPerMinute);
return d;
}
return null;
};
SQLVarTimeStamp.prototype.calcBlr = function (blr) {
blr.addByte(blr_timestamp);
};
//------------------------------------------------------
function SQLVarBoolean() {
}
SQLVarBoolean.prototype.decode = function (data, lowerV13) {
var ret = data.readInt();
if (!lowerV13 || !data.readInt()) {
return Boolean(ret);
}
return null;
};
SQLVarBoolean.prototype.calcBlr = function (blr) {
blr.addByte(blr_bool);
};
//------------------------------------------------------
function SQLParamInt(value) {
this.value = value;
}
SQLParamInt.prototype.calcBlr = function (blr) {
blr.addByte(blr_long);
blr.addShort(0);
};
SQLParamInt.prototype.encode = function (data) {
if (this.value != null) {
data.addInt(this.value);
} else {
data.addInt(0);
data.addInt(1);
}
};
//------------------------------------------------------
function SQLParamInt64(value) {
this.value = value;
}
SQLParamInt64.prototype.calcBlr = function (blr) {
blr.addByte(blr_int64);
blr.addShort(0);
};
SQLParamInt64.prototype.encode = function (data) {
if (this.value != null) {
data.addInt64(this.value);
} else {
data.addInt64(0);
data.addInt(1);
}
};
//------------------------------------------------------
function SQLParamDouble(value) {
this.value = value;
}
SQLParamDouble.prototype.encode = function (data) {
if (this.value != null) {
data.addDouble(this.value);
} else {
data.addDouble(0);
data.addInt(1);
}
};
SQLParamDouble.prototype.calcBlr = function (blr) {
blr.addByte(blr_double);
};
//------------------------------------------------------
function SQLParamString(value) {
this.value = value;
}
SQLParamString.prototype.encode = function (data, encoding) {
if (this.value != null) {
data.addText(this.value, encoding);
} else {
data.addInt(1);
}
};
SQLParamString.prototype.calcBlr = function (blr, encoding) {
blr.addByte(blr_text);
var len = this.value ? Buffer.byteLength(this.value, encoding) : 0;
blr.addWord(len);
};
//------------------------------------------------------
function SQLParamQuad(value) {
this.value = value;
}
SQLParamQuad.prototype.encode = function (data) {
if (this.value != null) {
data.addInt(this.value.high);
data.addInt(this.value.low);
} else {
data.addInt(0);
data.addInt(0);
data.addInt(1);
}
};
SQLParamQuad.prototype.calcBlr = function (blr) {
blr.addByte(blr_quad);
blr.addShort(0);
};
//------------------------------------------------------
function SQLParamDate(value) {
this.value = value;
}
SQLParamDate.prototype.encode = function (data) {
if (this.value != null) {
var value = this.value.getTime() - this.value.getTimezoneOffset() * MsPerMinute;
var time = value % TimeCoeff;
var date = (value - time) / TimeCoeff + DateOffset;
time *= 10;
// check overflow
if (time < 0) {
date--;
time = TimeCoeff * 10 + time;
}
data.addInt(date);
data.addUInt(time);
} else {
data.addInt(0);
data.addUInt(0);
data.addInt(1);
}
};
SQLParamDate.prototype.calcBlr = function (blr) {
blr.addByte(blr_timestamp);
};
//------------------------------------------------------
function SQLParamBool(value) {
this.value = value;
}
SQLParamBool.prototype.encode = function (data) {
if (this.value != null) {
data.addInt(this.value ? 1 : 0);
} else {
data.addInt(0);
data.addInt(1);
}
};
SQLParamBool.prototype.calcBlr = function (blr) {
blr.addByte(blr_short);
blr.addShort(0);
};
/***************************************
*
* Error handling
*
***************************************/
function isError(obj) {
return (obj instanceof Object && obj.status);
}
function doCallback(obj, callback) {
if (!callback) {
return;
}
if (obj instanceof Error) {
doError(obj, callback);
return;
}
if (isError(obj)) {
callback(new GDSError(obj));
return;
}
callback(undefined, obj);
}
function doError(obj, callback) {
if (callback) {
if (obj && obj.message) {
let errTemp = obj.message + '';
if (errTemp && (errTemp.includes('At procedure') || errTemp.includes('At trigger') || errTemp.includes('GENERICA, '))) {
errTemp = errTemp.replace(/Error: exception [0-9]{2}, /, '');
errTemp = errTemp.replace(/Error: validation error for column /g, '');
errTemp = errTemp.replace(/^[A-Z]+(?:_[A-Z]+)+, /, '');
errTemp = errTemp.replace(/GENERICA, /g, '');
errTemp = errTemp.replace(/C!/g, 'á');
errTemp = errTemp.replace(/C'/g, 'ç');
errTemp = errTemp.replace(/C:/g, 'ú');
errTemp = errTemp.replace(/C3/g, 'ó');
errTemp = errTemp.replace(/C#/g, 'ã');
errTemp = errTemp.replace(/C-/g, 'í');
obj.message = errTemp;
}
}
callback(obj);
}
}
/***************************************
*
* Statement
*
***************************************/
function Statement(connection) {
this.connection = connection;
this.close = function (callback) {
this.connection.closeStatement(this, callback);
};
this.drop = function (callback) {
this.connection.dropStatement(this, callback);
};
this.release = function (callback) {
var cache_query = this.connection.getCachedQuery(this.query);
if (cache_query) {
this.connection.closeStatement(this, callback);
} else {
this.connection.dropStatement(this, callback);
}
};
this.execute = function (transaction, params, callback, custom) {
if (params instanceof Function) {
custom = callback;
callback = params;
params = undefined;
}
this.custom = custom;
this.connection.executeStatement(transaction, this, params, callback);
};
this.fetch = function (transaction, count, callback) {
this.connection.fetch(this, transaction, count, callback);
};
this.fetchAll = function (transaction, callback) {
this.connection.fetchAll(this, transaction, callback);
};
}
/***************************************
*
* Transaction
*
***************************************/
function Transaction(connection) {
this.connection = connection;
this.db = connection.db;
this.newStatement = function (query, callback) {
var cnx = this.connection;
var self = this;
var query_cache = cnx.getCachedQuery(query);
if (query_cache) {
callback(null, query_cache);
} else {
cnx.prepare(self, query, false, callback);
}
};
this.executeAux = function (query, params, callback, custom) {
if (params instanceof Function) {
custom = callback;
callback = params;
params = undefined;
}
var self = this;
this.newStatement(query, function (err, statement) {
if (err) {
doError(err, callback);
return;
}
function dropError(err) {
statement.release();
doCallback(err, callback);
}
statement.execute(self, params, function (err, ret) {
if (err) {
dropError(err);
return;
}
switch (statement.type) {
case isc_info_sql_stmt_select:
statement.fetchAll(self, function (err, r) {
if (err) {
dropError(err);
return;
}
statement.release();
if (callback) {
callback(undefined, r, statement.output, true);
}
});
break;
case isc_info_sql_stmt_exec_procedure:
if (ret && ret.data && ret.data.length > 0) {
statement.release();
if (callback) {
callback(undefined, ret.data[0], statement.output, true);
}
break;
} else if (statement.output.length) {
statement.fetch(self, 1, function (err, ret) {
if (err) {
dropError(err);
return;
}
statement.release();
if (callback) {
callback(undefined, ret.data[0], statement.output, false);
}
});
break;
}
// Fall through is normal
default:
statement.release();
if (callback) {
callback();
}
break;
}
}, custom);
});
};
this.sequentially = function (query, params, on, callback, asArray) {
if (params instanceof Function) {
asArray = callback;
callback = on;
on = params;
params = undefined;
}
if (callback instanceof Boolean) {
asArray = callback;
callback = undefined;
}
let self = this;
let promise = new Promise((resolve, reject) => {
if (on === undefined) {
reject(new Error('Expected "on" delegate.'));
} else {
self.executeAux(query, params, (err) => {
if (err) {
return reject(err);
} else {
return resolve();
}
}, {asObject: !asArray, asStream: true, on: on});
}
return self;
});
if (callback) {
return promise.then(_ => {
return callback(undefined);
}).catch(e => {
return callback(e);
});
}
return promise;
};
this.execute = function (query, params, queryLimit, callback) {
if (params instanceof Function) {
callback = params;
params = undefined;
}
if (queryLimit instanceof Function) {
callback = queryLimit;
queryLimit = undefined;
}
let self = this;
let promise = new Promise((resolve, reject) => {
self.executeAux(query, params, (err, result) => {
if (err) {
return reject(err);
} else {
return resolve(result);
}
}, {queryLimit: queryLimit});
return self;
});
if (callback) {
return promise.then(d => {
return callback(undefined, d);
}).catch(e => {
return callback(e);
});
}
return promise;
};
this.executeOne = function (query, params, callback) {
if (params instanceof Function) {
callback = params;
params = undefined;
}
let self = this;
let promise = new Promise((resolve, reject) => {
self.executeAux(query, params, (err, result) => {
if (err) {
return reject(err);
} else if (result && result.length > 0) {
return resolve(result[0]);
} else {
return resolve(null);
}
}, undefined);
return self;
});
if (callback) {
return promise.then(d => {
return callback(undefined, d);
}).catch(e => {
return callback(e);
});
}
return promise;
};
this.query = function (query, params, queryLimit, callback) {
if (params instanceof Function) {
callback = params;
params = undefined;
}
if (queryLimit instanceof Function) {
callback = queryLimit;
queryLimit = undefined;
}
let self = this;
let promise =