def parse_xsqlda(buf, connection, stmt_handle): xsqlda = [] stmt_type = None i = 0 while i < len(buf): if buf[i:i+3] == bytes([isc_info_sql_stmt_type,0x04,0x00]): stmt_type = bytes_to_int(buf[i+3:i+7]) i += 7 elif buf[i:i+2] == bytes([isc_info_sql_select, isc_info_sql_describe_vars]): i += 2 l = bytes_to_int(buf[i:i+2]) i += 2 col_len = bytes_to_int(buf[i:i+l]) xsqlda = [None] * col_len next_index = parse_select_items(buf[i+l:], xsqlda, connection) while next_index > 0: # more describe vars connection._op_info_sql(stmt_handle, bytes([isc_info_sql_sqlda_start, 2]) + int_to_bytes(next_index, 2) + INFO_SQL_SELECT_DESCRIBE_VARS) (h, oid, buf) = connection._op_response() assert buf[:2] == bytes([0x04,0x07]) l = bytes_to_int(buf[2:4]) assert bytes_to_int(buf[4:4+l]) == col_len next_index = parse_select_items(buf[4+l:], xsqlda, connection) else: break return stmt_type, xsqlda
def __init__(self, cur, sql, explain_plan=False): self.cur = cur self.sql = sql transaction = self.cur.transaction connection = transaction.connection connection._op_allocate_statement() (h, oid, buf) = connection._op_response() self.stmt_handle = h if explain_plan: connection._op_prepare_statement( self.stmt_handle, transaction.trans_handle, sql, option_items=bytes([isc_info_sql_get_plan])) else: connection._op_prepare_statement( self.stmt_handle, transaction.trans_handle, sql) self.plan = None (h, oid, buf) = connection._op_response() i = 0 if byte_to_int(buf[i]) == isc_info_sql_get_plan: l = bytes_to_int(buf[i+1:i+3]) self.plan = connection.bytes_to_str(buf[i+3:i+3+l]) i += 3 + l assert buf[i:i+3] == bytes([0x15,0x04,0x00]) # isc_info_sql_stmt_type (4 bytes) self.statement_type = bytes_to_int(buf[i+3:i+7]) self._xsqlda = parse_xsqlda(buf[i:], connection, self.stmt_handle)
def _db_info(self, info_requests): if info_requests[-1] == isc_info_end: self._op_info_database(bytes(info_requests)) else: self._op_info_database( bytes(info_requests + type(info_requests)([isc_info_end]))) (h, oid, buf) = self._op_response() i = 0 i_request = 0 r = [] while i < len(buf): req = byte_to_int(buf[i]) if req == isc_info_end: break assert req == info_requests[i_request] or req == isc_info_error if req == isc_info_user_names: user_names = [] while req == isc_info_user_names: l = bytes_to_int(buf[i + 1:i + 3]) user_names.append(buf[i + 3:i + 3 + l]) i = i + 3 + l req = byte_to_int(buf[i]) r.append((req, user_names)) else: l = bytes_to_int(buf[i + 1:i + 3]) r.append((req, buf[i + 3:i + 3 + l])) i = i + 3 + l i_request += 1 return r
def parse_xsqlda(buf, connection, stmt_handle): xsqlda = [] stmt_type = None i = 0 while i < len(buf): if buf[i:i + 3] == bytes([isc_info_sql_stmt_type, 0x04, 0x00]): stmt_type = bytes_to_int(buf[i + 3:i + 7]) i += 7 elif buf[i:i + 2] == bytes( [isc_info_sql_select, isc_info_sql_describe_vars]): i += 2 l = bytes_to_int(buf[i:i + 2]) i += 2 col_len = bytes_to_int(buf[i:i + l]) xsqlda = [None] * col_len next_index = parse_select_items(buf[i + l:], xsqlda, connection) while next_index > 0: # more describe vars connection._op_info_sql( stmt_handle, bytes([isc_info_sql_sqlda_start, 2]) + int_to_bytes(next_index, 2) + INFO_SQL_SELECT_DESCRIBE_VARS) (h, oid, buf) = connection._op_response() assert buf[:2] == bytes([0x04, 0x07]) l = bytes_to_int(buf[2:4]) assert bytes_to_int(buf[4:4 + l]) == col_len next_index = parse_select_items(buf[4 + l:], xsqlda, connection) else: break return stmt_type, xsqlda
def rowcount(self): self.transaction.connection._op_info_sql( self.stmt_handle, bytes([isc_info_sql_stmt_type])) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15, 0x04, 0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self.transaction.connection._op_info_sql(self.stmt_handle, bytes([isc_info_sql_records])) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x17, 0x1d, 0x00]) # isc_info_sql_records if stmt_type == isc_info_sql_stmt_select: # rowcount for select stmt changes based on num rows fetched count = -1 elif stmt_type == isc_info_sql_stmt_insert: assert buf[24:27] == bytes([0x0e, 0x04, 0x00]) # isc_info_req_insert_count count = bytes_to_int(buf[27:31]) elif stmt_type == isc_info_sql_stmt_update: assert buf[3:6] == bytes([0x0f, 0x04, 0x00]) # isc_info_req_update_count count = bytes_to_int(buf[6:10]) elif stmt_type == isc_info_sql_stmt_delete: assert buf[10:13] == bytes([0x10, 0x04, 0x00]) # isc_info_req_delete_count count = bytes_to_int(buf[13:17]) return count
def rowcount(self): self.transaction.connection._op_info_sql(self.stmt_handle, bytes([isc_info_sql_stmt_type])) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15,0x04,0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self.transaction.connection._op_info_sql(self.stmt_handle, bytes([isc_info_sql_records])) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x17,0x1d,0x00]) # isc_info_sql_records if stmt_type == isc_info_sql_stmt_select: # rowcount for select stmt changes based on num rows fetched count = -1 elif stmt_type == isc_info_sql_stmt_insert: assert buf[24:27] == bytes([0x0e,0x04,0x00]) # isc_info_req_insert_count count = bytes_to_int(buf[27:31]) elif stmt_type == isc_info_sql_stmt_update: assert buf[3:6] == bytes([0x0f,0x04,0x00]) # isc_info_req_update_count count = bytes_to_int(buf[6:10]) elif stmt_type == isc_info_sql_stmt_delete: assert buf[10:13] == bytes([0x10,0x04,0x00]) # isc_info_req_delete_count count = bytes_to_int(buf[13:17]) return count
def _db_info(self, info_requests): if info_requests[-1] == isc_info_end: self._op_info_database(bytes(info_requests)) else: self._op_info_database( bytes(info_requests+type(info_requests)([isc_info_end]))) (h, oid, buf) = self._op_response() i = 0 i_request = 0 r = [] while i < len(buf): req = byte_to_int(buf[i]) if req == isc_info_end: break assert req == info_requests[i_request] if req == isc_info_user_names: user_names = [] while req == isc_info_user_names: l = bytes_to_int(buf[i+1:i+3]) user_names.append(buf[i+3:i+3+l]) i = i + 3 + l req = byte_to_int(buf[i]) r.append(user_names) else: l = bytes_to_int(buf[i+1:i+3]) r.append(buf[i+3:i+3+l]) i = i + 3 + l i_request += 1 return r
def __init__(self, cur, sql, explain_plan=False): self.cur = cur self.sql = sql transaction = self.cur.transaction connection = transaction.connection connection._op_allocate_statement() (h, oid, buf) = connection._op_response() self.stmt_handle = h if explain_plan: connection._op_prepare_statement(self.stmt_handle, transaction.trans_handle, sql, option_items=bytes( [isc_info_sql_get_plan])) else: connection._op_prepare_statement(self.stmt_handle, transaction.trans_handle, sql) self.plan = None (h, oid, buf) = connection._op_response() i = 0 if byte_to_int(buf[i]) == isc_info_sql_get_plan: l = bytes_to_int(buf[i + 1:i + 3]) self.plan = connection.bytes_to_str(buf[i + 3:i + 3 + l]) i += 3 + l assert buf[i:i + 3] == bytes([0x15, 0x04, 0x00 ]) # isc_info_sql_stmt_type (4 bytes) self.statement_type = bytes_to_int(buf[i + 3:i + 7]) self._xsqlda = parse_xsqlda(buf[i:], connection, self.stmt_handle)
def _fetch_generator(self, stmt_handle): connection = self.transaction.connection more_data = True while more_data: connection._op_fetch(stmt_handle, calc_blr(self._xsqlda)) (rows, more_data) = connection._op_fetch_response( stmt_handle, self._xsqlda) for r in rows: # Convert BLOB handle to data for i in range(len(self._xsqlda)): x = self._xsqlda[i] if x.sqltype == SQL_TYPE_BLOB: if not r[i]: continue connection._op_open_blob(r[i], self.transaction.trans_handle) (h, oid, buf) = connection._op_response() v = bytes([]) n = 1 # 1:mora data 2:no more data while n == 1: connection._op_get_segment(h) (n, oid, buf) = connection._op_response() while buf: ln = bytes_to_int(buf[:2]) v += buf[2:ln + 2] buf = buf[ln + 2:] connection._op_close_blob(h) (h, oid, buf) = connection._op_response() r[i] = v if x.sqlsubtype == 1: # TEXT r[i] = connection.bytes_to_str(r[i]) yield r raise StopIteration()
def _execute(self, query, params): cooked_params = self._convert_params(params) if isinstance(query, PreparedStatement): stmt_handle = query.stmt_handle stmt_type = query.statement_type self._xsqlda = query._xsqlda else: stmt_handle = self.stmt_handle self.transaction.connection._op_prepare_statement( stmt_handle, self.transaction.trans_handle, query) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15, 0x04, 0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self._xsqlda = parse_xsqlda(buf, self.transaction.connection, stmt_handle) self.transaction.connection._op_execute(stmt_handle, self.transaction.trans_handle, cooked_params) try: (h, oid, buf) = self.transaction.connection._op_response() except OperationalError: e = sys.exc_info()[1] if 335544665 in e.gds_codes: raise IntegrityError(e.message, e.gds_codes, e.sql_code) return stmt_type, stmt_handle
def _fetch_generator(self, stmt_handle): connection = self.transaction.connection more_data = True while more_data: connection._op_fetch(stmt_handle, calc_blr(self._xsqlda)) (rows, more_data) = connection._op_fetch_response( stmt_handle, self._xsqlda) for r in rows: # Convert BLOB handle to data for i in range(len(self._xsqlda)): x = self._xsqlda[i] if x.sqltype == SQL_TYPE_BLOB: if not r[i]: continue connection._op_open_blob(r[i], self.transaction.trans_handle) (h, oid, buf) = connection._op_response() v = bytes([]) n = 1 # 1:mora data 2:no more data while n == 1: connection._op_get_segment(h) (n, oid, buf) = connection._op_response() while buf: ln = bytes_to_int(buf[:2]) v += buf[2:ln+2] buf = buf[ln+2:] connection._op_close_blob(h) (h, oid, buf) = connection._op_response() r[i] = v if x.sqlsubtype == 1: # TEXT r[i] = connection.bytes_to_str(r[i]) yield r raise StopIteration()
def _execute(self, query, params): cooked_params = self._convert_params(params) if isinstance(query, PreparedStatement): stmt_handle = query.stmt_handle stmt_type = query.statement_type self._xsqlda = query._xsqlda else: stmt_handle = self.stmt_handle self.transaction.connection._op_prepare_statement(stmt_handle, self.transaction.trans_handle, query) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15,0x04,0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self._xsqlda = parse_xsqlda(buf, self.transaction.connection, stmt_handle) self.transaction.connection._op_execute(stmt_handle, self.transaction.trans_handle, cooked_params) try: (h, oid, buf) = self.transaction.connection._op_response() except OperationalError: e = sys.exc_info()[1] if 335544665 in e.gds_codes: raise IntegrityError(e.message, e.gds_codes, e.sql_code) return stmt_type, stmt_handle
def parse_xsqlda(buf, connection, stmt_handle): assert buf[:3] == bytes([0x15, 0x04, 0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) if stmt_type != isc_info_sql_stmt_select: return [] assert buf[7:9] == bytes([0x04, 0x07]) l = bytes_to_int(buf[9:11]) col_len = bytes_to_int(buf[11 : 11 + l]) xsqlda = [None] * col_len next_index = parse_select_items(buf[11 + l :], xsqlda, connection) while next_index > 0: # more describe vars connection._op_info_sql( stmt_handle, bytes([isc_info_sql_sqlda_start, 2]) + int_to_bytes(next_index, 2) + INFO_SQL_SELECT_DESCRIBE_VARS, ) (h, oid, buf) = connection._op_response() assert buf[:2] == bytes([0x04, 0x07]) l = bytes_to_int(buf[2:4]) assert bytes_to_int(buf[4 : 4 + l]) == col_len next_index = parse_select_items(buf[4 + l :], xsqlda, connection) return xsqlda
def trans_info(self, info_requests): if type(info_requests) == int: # singleton r = self._trans_info([info_requests]) return {info_requests: r[0]} else: results = {} rs = self._trans_info(info_requests) for i in range(len(info_requests)): if info_requests[i] == isc_info_tra_isolation: v = (byte_to_int(rs[i][0]), byte_to_int(rs[i][1])) else: v = bytes_to_int(rs[i]) results[info_requests[i]] = v return results
def parse_xsqlda(buf, connection, stmt_handle): assert buf[:3] == bytes([0x15, 0x04, 0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) if (stmt_type != isc_info_sql_stmt_select and stmt_type != isc_info_sql_stmt_exec_procedure): return [] assert buf[7:9] == bytes([0x04, 0x07]) l = bytes_to_int(buf[9:11]) col_len = bytes_to_int(buf[11:11 + l]) xsqlda = [None] * col_len next_index = parse_select_items(buf[11 + l:], xsqlda, connection) while next_index > 0: # more describe vars connection._op_info_sql( stmt_handle, bytes([isc_info_sql_sqlda_start, 2]) + int_to_bytes(next_index, 2) + INFO_SQL_SELECT_DESCRIBE_VARS) (h, oid, buf) = connection._op_response() assert buf[:2] == bytes([0x04, 0x07]) l = bytes_to_int(buf[2:4]) assert bytes_to_int(buf[4:4 + l]) == col_len next_index = parse_select_items(buf[4 + l:], xsqlda, connection) return xsqlda
def _callproc(self, query, params): cooked_params = self._convert_params(params) stmt_handle = self.stmt_handle self.transaction.connection._op_prepare_statement(stmt_handle, self.transaction.trans_handle, query) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15,0x04,0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self._xsqlda = parse_xsqlda(buf, self.transaction.connection, stmt_handle) self.transaction.connection._op_execute2(stmt_handle, self.transaction.trans_handle, cooked_params, calc_blr(self._xsqlda)) return self.transaction.connection._op_sql_response(self._xsqlda)
def trans_info(self, info_requests): if type(info_requests) == int: # singleton r = self._trans_info([info_requests]) return {info_requests: r[1][0]} else: results = {} rs = self._trans_info(info_requests) for i in range(len(info_requests)): if rs[i][0] == isc_info_tra_isolation: v = (byte_to_int(rs[i][1][0]), byte_to_int(rs[i][1][1])) elif rs[i][0] == isc_info_error: v = None else: v = bytes_to_int(rs[i][1]) results[info_requests[i]] = v return results
def _callproc(self, query, params): cooked_params = self._convert_params(params) stmt_handle = self.stmt_handle self.transaction.connection._op_prepare_statement( stmt_handle, self.transaction.trans_handle, query) (h, oid, buf) = self.transaction.connection._op_response() assert buf[:3] == bytes([0x15, 0x04, 0x00]) # isc_info_sql_stmt_type stmt_type = bytes_to_int(buf[3:7]) self._xsqlda = parse_xsqlda(buf, self.transaction.connection, stmt_handle) self.transaction.connection._op_execute2(stmt_handle, self.transaction.trans_handle, cooked_params, calc_blr(self._xsqlda)) return self.transaction.connection._op_sql_response(self._xsqlda)
def _trans_info(self, info_requests): if info_requests[-1] == isc_info_end: self.connection._op_info_transaction(self.trans_handle, bytes(info_requests)) else: self.connection._op_info_transaction(self.trans_handle, bytes(info_requests+type(info_requests)([isc_info_end]))) (h, oid, buf) = self.connection._op_response() i = 0 i_request = 0 r = [] while i < len(buf): req = byte_to_int(buf[i]) if req == isc_info_end: break assert req == info_requests[i_request] l = bytes_to_int(buf[i+1:i+3]) r.append(buf[i+3:i+3+l]) i = i + 3 + l i_request += 1 return r
def _trans_info(self, info_requests): if info_requests[-1] == isc_info_end: self.connection._op_info_transaction(self.trans_handle, bytes(info_requests)) else: self.connection._op_info_transaction( self.trans_handle, bytes(info_requests + type(info_requests)([isc_info_end]))) (h, oid, buf) = self.connection._op_response() i = 0 i_request = 0 r = [] while i < len(buf): req = byte_to_int(buf[i]) if req == isc_info_end: break assert req == info_requests[i_request] or req == isc_info_error l = bytes_to_int(buf[i + 1:i + 3]) r.append((req, buf[i + 3:i + 3 + l])) i = i + 3 + l i_request += 1 return r
def _db_info_convert_type(self, info_request, v): REQ_INT = set([ isc_info_allocation, isc_info_no_reserve, isc_info_db_sql_dialect, isc_info_ods_minor_version, isc_info_ods_version, isc_info_page_size, isc_info_current_memory, isc_info_forced_writes, isc_info_max_memory, isc_info_num_buffers, isc_info_sweep_interval, isc_info_limbo, isc_info_attachment_id, isc_info_fetches, isc_info_marks, isc_info_reads, isc_info_writes, isc_info_set_page_buffers, isc_info_db_read_only, isc_info_db_size_in_pages, isc_info_page_errors, isc_info_record_errors, isc_info_bpage_errors, isc_info_dpage_errors, isc_info_ipage_errors, isc_info_ppage_errors, isc_info_tpage_errors, # may not be available in some versions of Firebird isc_info_oldest_transaction, isc_info_oldest_active, isc_info_oldest_snapshot, isc_info_next_transaction, isc_info_active_tran_count ]) REQ_COUNT = set([ isc_info_backout_count, isc_info_delete_count, isc_info_expunge_count, isc_info_insert_count, isc_info_purge_count, isc_info_read_idx_count, isc_info_read_seq_count, isc_info_update_count ]) if info_request in (isc_info_base_level, ): # IB6 API guide p52 return byte_to_int(v[1]) elif info_request in (isc_info_db_id, ): # IB6 API guide p52 conn_code = byte_to_int(v[0]) len1 = byte_to_int(v[1]) filename = self.bytes_to_str(v[2:2+len1]) len2 = byte_to_int(v[2+len1]) sitename = self.bytes_to_str(v[3+len1:3+len1+len2]) return (conn_code, filename, sitename) elif info_request in (isc_info_implementation, ): return (byte_to_int(v[1]), byte_to_int(v[2])) elif info_request in (isc_info_version, isc_info_firebird_version): # IB6 API guide p53 return self.bytes_to_str(v[2:2+byte_to_int(v[1])]) elif info_request in (isc_info_user_names, ): # IB6 API guide p54 user_names = [] for u in v: user_names.append(self.bytes_to_str(u[1:])) return user_names elif info_request in REQ_INT: return bytes_to_int(v) elif info_request in REQ_COUNT: counts = {} i = 0 while i < len(v): counts[bytes_to_int(v[i:i+2])] = bytes_to_int(v[i+2:i+6]) i += 6 return counts elif info_request in (isc_info_creation_date,): nday = bytes_to_int(v[:4]) + 2400001 - 1721119 century = (4 * nday - 1) // 146097 nday = 4 * nday - 1 - 146097 * century dd = nday // 4 nday = (4 * dd + 3) // 1461 dd = 4 * dd + 3 - 1461 * nday dd = (dd + 4) // 4 mm = (5 * dd - 3) // 153 dd = 5 * dd - 3 - 153 * mm dd = (dd + 5) // 5 yyyy = 100 * century + nday; if mm < 10: mm += 3 else: mm -= 9 yyyy += 1 ntime = bytes_to_int(v[4:]) h = ntime // (3600 * ISC_TIME_SECONDS_PRECISION) ntime %= 3600 * ISC_TIME_SECONDS_PRECISION m = ntime // (60 * ISC_TIME_SECONDS_PRECISION) ntime %= 60 * ISC_TIME_SECONDS_PRECISION s = ntime // ISC_TIME_SECONDS_PRECISION ms = ntime % ISC_TIME_SECONDS_PRECISION * 100 return datetime.datetime(yyyy, mm, dd, h, m, s, ms) else: return v
def parse_select_items(buf, xsqlda, connection): index = 0 i = 0 item = byte_to_int(buf[i]) while item != isc_info_end: if item == isc_info_sql_sqlda_seq: l = bytes_to_int(buf[i+1:i+3]) index = bytes_to_int(buf[i+3:i+3+l]) xsqlda[index-1] = XSQLVAR(connection.bytes_to_str) i = i + 3 + l elif item == isc_info_sql_type: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].sqltype = bytes_to_int(buf[i+3:i+3+l]) & ~ 1 i = i + 3 + l elif item == isc_info_sql_sub_type: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].sqlsubtype = bytes_to_int(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_scale: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].sqlscale = bytes_to_int(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_length: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].sqllen = bytes_to_int(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_null_ind: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].null_ok = bytes_to_int(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_field: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].fieldname = connection.bytes_to_str(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_relation: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].relname = connection.bytes_to_str(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_owner: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].ownname = connection.bytes_to_str(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_sql_alias: l = bytes_to_int(buf[i+1:i+3]) xsqlda[index-1].aliasname = connection.bytes_to_str(buf[i+3:i+3+l]) i = i + 3 + l elif item == isc_info_truncated: return index # return next index elif item == isc_info_sql_describe_end: i = i + 1 else: print('\t', item, 'Invalid item [%02x] ! i=%d' % (buf[i], i)) i = i + 1 item = byte_to_int(buf[i]) return -1 # no more info
def _db_info_convert_type(self, info_request, v): REQ_INT = set([ isc_info_allocation, isc_info_no_reserve, isc_info_db_sql_dialect, isc_info_ods_minor_version, isc_info_ods_version, isc_info_page_size, isc_info_current_memory, isc_info_forced_writes, isc_info_max_memory, isc_info_num_buffers, isc_info_sweep_interval, isc_info_limbo, isc_info_attachment_id, isc_info_fetches, isc_info_marks, isc_info_reads, isc_info_writes, isc_info_set_page_buffers, isc_info_db_read_only, isc_info_db_size_in_pages, isc_info_page_errors, isc_info_record_errors, isc_info_bpage_errors, isc_info_dpage_errors, isc_info_ipage_errors, isc_info_ppage_errors, isc_info_tpage_errors, # may not be available in some versions of Firebird isc_info_oldest_transaction, isc_info_oldest_active, isc_info_oldest_snapshot, isc_info_next_transaction, isc_info_active_tran_count ]) REQ_COUNT = set([ isc_info_backout_count, isc_info_delete_count, isc_info_expunge_count, isc_info_insert_count, isc_info_purge_count, isc_info_read_idx_count, isc_info_read_seq_count, isc_info_update_count ]) if info_request in (isc_info_base_level, ): # IB6 API guide p52 return byte_to_int(v[1]) elif info_request in (isc_info_db_id, ): # IB6 API guide p52 conn_code = byte_to_int(v[0]) len1 = byte_to_int(v[1]) filename = self.bytes_to_str(v[2:2 + len1]) len2 = byte_to_int(v[2 + len1]) sitename = self.bytes_to_str(v[3 + len1:3 + len1 + len2]) return (conn_code, filename, sitename) elif info_request in (isc_info_implementation, ): return (byte_to_int(v[1]), byte_to_int(v[2])) elif info_request in (isc_info_version, isc_info_firebird_version): # IB6 API guide p53 return self.bytes_to_str(v[2:2 + byte_to_int(v[1])]) elif info_request in (isc_info_user_names, ): # IB6 API guide p54 user_names = [] for u in v: user_names.append(self.bytes_to_str(u[1:])) return user_names elif info_request in REQ_INT: return bytes_to_int(v) elif info_request in REQ_COUNT: counts = {} i = 0 while i < len(v): counts[bytes_to_int(v[i:i + 2])] = bytes_to_int(v[i + 2:i + 6]) i += 6 return counts elif info_request in (isc_info_creation_date, ): nday = bytes_to_int(v[:4]) + 2400001 - 1721119 century = (4 * nday - 1) // 146097 nday = 4 * nday - 1 - 146097 * century dd = nday // 4 nday = (4 * dd + 3) // 1461 dd = 4 * dd + 3 - 1461 * nday dd = (dd + 4) // 4 mm = (5 * dd - 3) // 153 dd = 5 * dd - 3 - 153 * mm dd = (dd + 5) // 5 yyyy = 100 * century + nday if mm < 10: mm += 3 else: mm -= 9 yyyy += 1 ntime = bytes_to_int(v[4:]) h = ntime // (3600 * ISC_TIME_SECONDS_PRECISION) ntime %= 3600 * ISC_TIME_SECONDS_PRECISION m = ntime // (60 * ISC_TIME_SECONDS_PRECISION) ntime %= 60 * ISC_TIME_SECONDS_PRECISION s = ntime // ISC_TIME_SECONDS_PRECISION ms = ntime % ISC_TIME_SECONDS_PRECISION * 100 return datetime.datetime(yyyy, mm, dd, h, m, s, ms) else: return v
def parse_select_items(buf, xsqlda, connection): index = 0 i = 0 item = byte_to_int(buf[i]) while item != isc_info_end: if item == isc_info_sql_sqlda_seq: l = bytes_to_int(buf[i + 1:i + 3]) index = bytes_to_int(buf[i + 3:i + 3 + l]) xsqlda[index - 1] = XSQLVAR(connection.bytes_to_str) i = i + 3 + l elif item == isc_info_sql_type: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].sqltype = bytes_to_int(buf[i + 3:i + 3 + l]) & ~1 i = i + 3 + l elif item == isc_info_sql_sub_type: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].sqlsubtype = bytes_to_int(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_scale: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].sqlscale = bytes_to_int(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_length: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].sqllen = bytes_to_int(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_null_ind: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].null_ok = bytes_to_int(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_field: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].fieldname = connection.bytes_to_str(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_relation: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].relname = connection.bytes_to_str(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_owner: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].ownname = connection.bytes_to_str(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_sql_alias: l = bytes_to_int(buf[i + 1:i + 3]) xsqlda[index - 1].aliasname = connection.bytes_to_str(buf[i + 3:i + 3 + l]) i = i + 3 + l elif item == isc_info_truncated: return index # return next index elif item == isc_info_sql_describe_end: i = i + 1 else: print('\t', item, 'Invalid item [%02x] ! i=%d' % (buf[i], i)) i = i + 1 item = byte_to_int(buf[i]) return -1 # no more info