Пример #1
0
    def handle(self):
        self.debug("connected")
        self.engine = SqlEngine()
        self._pgbuf = PgBuffer(self.rfile)
        self.wbuf = PgBuffer(self.wfile)

        try:
            # Handshake
            self.read_ssl_request()
            self.send_notice()
            self.read_startup_message()

            # Auth
            self.send_authentication_request()
            self.read_authentication()
            self.send_authentication_ok()

            while True:
                self.send_ready_for_query()

                # Read Message
                type_code = self._pgbuf.read_byte()
                print PSQL_FE_MESSAGES.get(type_code)

                if type_code == "Q":
                    msglen = self._pgbuf.read_int32()
                    sql = self._pgbuf.read_string(msglen - 4)
                    self.query(sql)
                elif type_code == "X":
                    break
        except Exception as e:
            self.error(e.message)
        self.debug("disconnected")
Пример #2
0
class PsqlHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        self.debug("connected")
        self.engine = SqlEngine()
        self._pgbuf = PgBuffer(self.rfile)
        self.wbuf = PgBuffer(self.wfile)

        try:
            # Handshake
            self.read_ssl_request()
            self.send_notice()
            self.read_startup_message()

            # Auth
            self.send_authentication_request()
            self.read_authentication()
            self.send_authentication_ok()

            while True:
                self.send_ready_for_query()

                # Read Message
                type_code = self._pgbuf.read_byte()
                print PSQL_FE_MESSAGES.get(type_code)

                if type_code == "Q":
                    msglen = self._pgbuf.read_int32()
                    sql = self._pgbuf.read_string(msglen - 4)
                    self.query(sql)
                elif type_code == "X":
                    break
        except Exception as e:
            self.error(e.message)
        self.debug("disconnected")

    def read_ssl_request(self):
        msglen = self._pgbuf.read_int32()
        sslcode = self._pgbuf.read_int32()
        if msglen != 8 and sslcode != 80877103:
            raise Exception("Unsupported SSL request")

    def read_startup_message(self):
        msglen = self._pgbuf.read_int32()
        version = self._pgbuf.read_int32()
        v_maj = version >> 16
        v_min = version & 0xFFFF
        info = self._pgbuf.read_parameters(msglen - 8)
        self.debug("PSQL %d.%d" % (v_maj, v_min), str(info))

    def read_authentication(self):
        type_code = self._pgbuf.read_byte()
        if type_code != "p":
            self.send_error("FATAL", "28000", "authentication failure")
            raise Exception("Only 'Password' auth is supported, got %r" % type_code)

        msglen = self._pgbuf.read_int32()
        password = self._pgbuf.read_bytes(msglen - 4)
        print password

    def send_notice(self):
        self.wfile.write("N")

    def send_authentication_request(self):
        self.wfile.write(struct.pack("!cii", "R", 8, 3))

    def send_authentication_ok(self):
        self.wfile.write(struct.pack("!cii", "R", 8, 0))

    def send_ready_for_query(self):
        self.wfile.write(struct.pack("!cic", "Z", 5, "I"))

    def send_command_complete(self, tag):
        self.wfile.write(struct.pack("!ci", "C", 4 + len(tag)))
        self.wfile.write(tag)

    def send_error(self, severity, code, message):
        buf = PgBuffer(StringIO())
        buf.write_byte("S")
        buf.write_string(severity)
        buf.write_byte("C")
        buf.write_string(code)
        buf.write_byte("M")
        buf.write_string(message)
        buf = buf.buffer.getvalue()

        self.wbuf.write_byte("E")
        self.wbuf.write_int32(4 + len(buf) + 1)
        self.wbuf.write_string(buf)

    def send_row_description(self, fields):
        buf = PgBuffer(StringIO())
        for field in fields:
            buf.write_string(field)
            buf.write_int32(0)  # Table ID
            buf.write_int16(0)  # Column ID
            buf.write_int32(0)  # object ID of the field's data type
            buf.write_int16(-1)  # data type size
            buf.write_int32(-1)  # type modifier
            buf.write_int16(0)  # text format code
        buf = buf.buffer.getvalue()

        self.wbuf.write_byte("T")
        self.wbuf.write_int32(6 + len(buf))
        self.wbuf.write_int16(len(fields))
        self.wbuf.write_bytes(buf)

    def send_row_data(self, rows):
        for row in rows:
            buf = PgBuffer(StringIO())
            for field in row:
                v = "%r" % field
                buf.write_int32(len(v))
                buf.write_bytes(v)
            buf = buf.buffer.getvalue()

            self.wbuf.write_byte("D")
            self.wbuf.write_int32(6 + len(buf))
            self.wbuf.write_int16(len(row))
            self.wbuf.write_bytes(buf)

    def execute_select(self, stmt):
        results = self.engine.execute_statement(stmt)
        # fields = [IntField('a'), IntField('b')]
        # rows = [[1, 2], [3, 4], [5, 6]]

        self.send_row_description(results.columns)
        self.send_row_data(results.rows)

    def execute_statement(self, stmt):
        self.engine.execute_statement(stmt)

    def query(self, sql):
        self.debug("query", repr(sql))

        try:
            queries = self.engine.parse(sql)
        except Exception as e:
            self.error("query parsing", e.message)
            self.send_error("ERROR", "26000", "query parse failure: %s" % e.message)
            return

        for stmt in queries:
            try:
                st = time()
                if isinstance(stmt, SqlSelectStatement):
                    self.execute_select(stmt)
                else:
                    self.execute_statement(stmt)
                et = time()
                self.send_command_complete("%s %.3fsec\x00" % (stmt.COMMAND, et - st))
                self.debug("query time", "%s completed in %.3fsec" % (stmt.COMMAND, et - st))
            except Exception as e:
                print e
                self.error("query processing", e.message)
                self.send_error("ERROR", "XX000", "query processing failure: %s" % e.message)

    def debug(self, *messages):
        logger.debug("%s - %s" % (str(self.client_address), " - ".join(messages)))

    def error(self, *messages):
        logger.error("%s - %s" % (str(self.client_address), " - ".join(messages)))