code: def _prepare(self, query):
          
          self._logger.info(u'Prepare a statement: [{}]'.format(query))
  
          # Send Parse message to server
          # We don't need to tell the server the parameter types yet
          self.connection.write(messages.Parse(self.prepared_name, query, param_types=()))
          # Send Describe message to server
          self.connection.write(messages.Describe('prepared_statement', self.prepared_name))
          self.connection.write(messages.Flush())
  
          # Read expected message: ParseComplete
          self._message = self.connection.read_expected_message(messages.ParseComplete, self._error_handler)
  
          # Read expected message: ParameterDescription
          self._message = self.connection.read_expected_message(messages.ParameterDescription, self._error_handler)
          self._param_metadata = self._message.parameters
  
          # Read expected message: RowDescription or NoData
          self._message = self.connection.read_expected_message(
                          (messages.RowDescription, messages.NoData), self._error_handler)
          if isinstance(self._message, messages.NoData):
              self.description = None # response was NoData for a DDL/transaction PreparedStatement
          else:
              self.description = [Column(fd, self.unicode_error) for fd in self._message.fields]
  
          # Read expected message: CommandDescription
          self._message = self.connection.read_expected_message(messages.CommandDescription, self._error_handler)
          if len(self._message.command_tag) == 0:
              msg = 'The statement being prepared is empty'
              self._logger.error(msg)
              self.connection.write(messages.Sync())
              raise errors.EmptyQueryError(msg)
  
          self._logger.info('Finish preparing the statement')
docs: Send the query to be prepared to the server. The server will parse the
          query and return some metadata.