Beispiel #1
0
    def test_request_message_init_with_multiple_segments_as_tuple(self):
        connection = Connection("localhost", 30015, "Fuu", "Bar")

        request_seg_1 = RequestSegment(0)
        request_seg_2 = RequestSegment(1)
        msg = RequestMessage.new(connection, (request_seg_1, request_seg_2))
        assert msg.segments == (request_seg_1, request_seg_2)
Beispiel #2
0
    def prepare(self, statement):
        """Prepare SQL statement in HANA and cache it
        :param statement; a valid SQL statement
        :returns: statement_id (of prepared and cached statement)
        """
        self._check_closed()
        self._column_types = None
        statement_id = params_metadata = result_metadata_part = None

        request = RequestMessage.new(
            self.connection,
            RequestSegment(message_types.PREPARE, Command(statement)))
        response = self.connection.send_request(request)

        for part in response.segments[0].parts:
            if part.kind == part_kinds.STATEMENTID:
                statement_id = part.statement_id
            elif part.kind == part_kinds.PARAMETERMETADATA:
                params_metadata = part.values
            elif part.kind == part_kinds.RESULTSETMETADATA:
                result_metadata_part = part

        # Check that both variables have been set in previous loop, we need them:
        assert statement_id is not None
        assert params_metadata is not None
        # cache statement:
        self._prepared_statements[statement_id] = PreparedStatement(
            self.connection, statement_id, params_metadata,
            result_metadata_part)
        return statement_id
Beispiel #3
0
    def _execute_direct(self, operation):
        """Execute statements which are not going through 'prepare_statement' (aka 'direct execution').
        Either their have no parameters, or Python's string expansion has been applied to the SQL statement.
        :param operation:
        """
        request = RequestMessage.new(
            self.connection,
            RequestSegment(message_types.EXECUTEDIRECT, Command(operation)))
        reply = self.connection.send_request(request)

        parts = reply.segments[0].parts
        function_code = reply.segments[0].function_code
        if function_code == function_codes.SELECT:
            self._handle_select(parts)
        elif function_code in function_codes.DML:
            self._handle_upsert(parts)
        elif function_code == function_codes.DDL:
            # No additional handling is required
            pass
        elif function_code in (function_codes.DBPROCEDURECALL,
                               function_codes.DBPROCEDURECALLWITHRESULT):
            self._handle_dbproc_call(parts, None)
        else:
            raise InterfaceError(
                "Invalid or unsupported function code received: %d" %
                function_code)
Beispiel #4
0
    def connect(self):
        with self._socket_lock:
            if self._socket is not None:
                # Socket already established
                return

            self._open_socket_and_init_protocoll()

            # Perform the authenication handshake and get the part
            # with the agreed authentication data
            agreed_auth_part = self._auth_manager.perform_handshake()

            request = RequestMessage.new(
                self,
                RequestSegment(
                    message_types.CONNECT,
                    (
                        agreed_auth_part,
                        ClientId(
                            "pyhdb-%s@%s" % (os.getpid(), socket.getfqdn())
                        ),
                        ConnectOptions(DEFAULT_CONNECTION_OPTIONS)
                    )
                )
            )
            reply = self.send_request(request, no_reconnect=True)

            for segment in reply.segments:
                for part in segment.parts:
                    if part.kind == part_kinds.CONNECTOPTIONS:
                        self.connect_options = part.options
Beispiel #5
0
    def rollback(self):
        self._check_closed()

        request = RequestMessage.new(
            self,
            RequestSegment(message_types.ROLLBACK)
        )
        self.send_request(request)
Beispiel #6
0
    def commit(self):
        self._check_closed()

        request = RequestMessage.new(
            self,
            RequestSegment(message_types.COMMIT)
        )
        self.send_request(request)
Beispiel #7
0
 def _perform_lob_write_requests(self, unwritten_lobs):
     """After sending incomplete LOB data during an INSERT or UPDATE this method will be called.
     It sends missing LOB data possibly in multiple LOBWRITE requests for all LOBs.
     :param unwritten_lobs: A deque list of LobBuffer instances containing LOB data.
            Those buffers have been assembled in the parts.Parameter.pack_lob_data() method.
     """
     while unwritten_lobs:
         request = RequestMessage.new(
             self.connection,
             RequestSegment(message_types.WRITELOB,
                            WriteLobRequest(unwritten_lobs)))
         self.connection.send_request(request)
Beispiel #8
0
def close_result(connection, _resultset_id):

    request = RequestMessage.new(
        connection,
        RequestSegment(message_types.CLOSERESULTSET,
                       (ResultSetId(_resultset_id))))

    response = connection.send_request(request)

    # no exception...
    # no result check...
    # never failed... (what if connection issue...)
    return
Beispiel #9
0
    def close(self):
        with self._socket_lock:
            if self._socket is None:
                raise Error("Connection already closed")

            try:
                request = RequestMessage.new(
                    self, RequestSegment(message_types.DISCONNECT))
                reply = self.send_request(request)
                if reply.segments[0].function_code != \
                   function_codes.DISCONNECT:
                    raise Error("Connection wasn't closed correctly")
            finally:
                self._socket.close()
                self._socket = None
Beispiel #10
0
    def _make_read_lob_request(self, readoffset, readlength):
        """Make low level request to HANA database (READLOBREQUEST).
        Compose request message with proper parameters and read lob data from second part object of reply.
        """
        self._connection._check_closed()

        request = RequestMessage.new(
            self._connection,
            RequestSegment(message_types.READLOB, (ReadLobRequest(
                self._lob_header.locator_id, readoffset, readlength), )))
        response = self._connection.send_request(request)

        # The segment of the message contains two parts.
        # 1) StatementContext -> ignored for now
        # 2) ReadLobReply -> contains some header information and actual LOB data
        data_part = response.segments[0].parts[1]
        # return actual lob container (BytesIO/TextIO):
        return data_part.data
Beispiel #11
0
    def perform_handshake(self):
        request = RequestMessage.new(
            self.connection,
            RequestSegment(
                message_types.AUTHENTICATE,
                Authentication(self.user, {self.method: self.client_key})))
        response = self.connection.send_request(request, no_reconnect=True)

        auth_part = response.segments[0].parts[0]
        if self.method not in auth_part.methods:
            raise Exception(
                "Only unknown authentication methods available: %s" %
                b",".join(auth_part.methods.keys()))

        salt, server_key = Fields.unpack_data(
            BytesIO(auth_part.methods[self.method]))

        self.client_proof = self.calculate_client_proof([salt], server_key)
        return Authentication(self.user, {'SCRAMSHA256': self.client_proof})
Beispiel #12
0
def drop_statement(connection, statement_id):

    log('psid to drop --> %s' % (hextostr(statement_id)), 4)

    if statement_id is None or connection is None:
        return

    t0 = time.time()

    request = RequestMessage.new(
        connection,
        RequestSegment(message_types.DROPSTATEMENTID,
                       StatementId(statement_id)))

    response = connection.send_request(request)

    t1 = time.time()

    log('psid drop took %s' % (str(round(t1 - t0, 3))), 4)
Beispiel #13
0
    def fetchmany(self, size=None):
        """Fetch many rows from select result set.
        :param size: Number of rows to return.
        :returns: list of row records (tuples)
        """
        self._check_closed()
        if not self._executed:
            raise ProgrammingError("Require execute() first")
        if size is None:
            size = self.arraysize

        column_names = [column[0] for column in self.description
                        ] if self.description else []

        result = []
        cnt = 0
        while cnt != size:
            try:
                result.append(ResultRow(column_names, next(self._buffer)))
                cnt += 1
            except StopIteration:
                break

        if cnt == size or self._received_last_resultset_part:
            # No rows are missing or there are no additional rows
            return result

        request = RequestMessage.new(
            self.connection,
            RequestSegment(
                message_types.FETCHNEXT,
                (ResultSetId(self._resultset_id), FetchSize(size - cnt))))
        response = self.connection.send_request(request)

        resultset_part = response.segments[0].parts[1]
        if resultset_part.attribute & 1:
            self._received_last_resultset_part = True
        result_parts = resultset_part.unpack_rows(self._column_types,
                                                  self.connection)
        for result_part in result_parts:
            result.append(ResultRow(column_names, result_part))
        return result
Beispiel #14
0
def test_tracing_output():
    msg_header = MessageHeader(session_id=5,
                               packet_count=3,
                               payload_length=500,
                               varpartsize=500,
                               num_segments=1,
                               packet_options=0)
    request = RequestMessage(session_id=msg_header.session_id,
                             packet_count=msg_header.packet_count,
                             segments=RequestSegment(
                                 message_types.EXECUTE,
                                 Command('select * from dummy')),
                             header=msg_header)

    pyhdb.tracing = True
    try:
        trace_msg = trace(request)
    finally:
        pyhdb.tracing = False

    assert trace_msg == TRACE_MSG
Beispiel #15
0
    def execute_prepared(self, prepared_statement, multi_row_parameters):
        """
        :param prepared_statement: A PreparedStatement instance
        :param multi_row_parameters: A list/tuple containing list/tuples of parameters (for multiple rows)
        """
        self._check_closed()

        # Convert parameters into a generator producing lists with parameters as named tuples (incl. some meta data):
        parameters = prepared_statement.prepare_parameters(
            multi_row_parameters)

        while parameters:
            request = RequestMessage.new(
                self.connection,
                RequestSegment(message_types.EXECUTE, (StatementId(
                    prepared_statement.statement_id), Parameters(parameters))))
            reply = self.connection.send_request(request)

            parts = reply.segments[0].parts
            function_code = reply.segments[0].function_code
            if function_code == function_codes.SELECT:
                self._handle_select(parts,
                                    prepared_statement.result_metadata_part)
            elif function_code in function_codes.DML:
                self._handle_upsert(
                    parts, request.segments[0].parts[1].unwritten_lobs)
            elif function_code == function_codes.DDL:
                # No additional handling is required
                pass
            elif function_code in (function_codes.DBPROCEDURECALL,
                                   function_codes.DBPROCEDURECALLWITHRESULT):
                self._handle_dbproc_call(parts,
                                         prepared_statement._params_metadata
                                         )  # resultset metadata set in prepare
            else:
                raise InterfaceError(
                    "Invalid or unsupported function code received: %d" %
                    function_code)
Beispiel #16
0
    def test_request_message_init_with_single_segment(self):
        connection = Connection("localhost", 30015, "Fuu", "Bar")

        request_seg = RequestSegment(0)
        msg = RequestMessage.new(connection, request_seg)
        assert msg.segments == (request_seg, )
Beispiel #17
0
def test_invalid_request(connection):
    request = RequestMessage.new(connection, RequestSegment(2))

    with pytest.raises(DatabaseError):
        connection.send_request(request)