text: #!/usr/bin/env python
  # -*- coding: utf-8 -*-
  
  import os
  import json
  import logging
  import requests
  from requests.auth import HTTPBasicAuth
  
  from redash.query_runner import *
  from redash.utils import JSONEncoder
  
  logger = logging.getLogger(__name__)
  
  types_map = {
      'tinyint': TYPE_INTEGER,
      'smallint': TYPE_INTEGER,
      'integer': TYPE_INTEGER,
      'bigint': TYPE_INTEGER,
      'int4': TYPE_INTEGER,
      'long8': TYPE_INTEGER,
      'int': TYPE_INTEGER,
      'short': TYPE_INTEGER,
      'long': TYPE_INTEGER,
      'byte': TYPE_INTEGER,
      'hllc10': TYPE_INTEGER,
      'hllc12': TYPE_INTEGER,
      'hllc14': TYPE_INTEGER,
      'hllc15': TYPE_INTEGER,
      'hllc16': TYPE_INTEGER,
      'hllc(10)': TYPE_INTEGER,
      'hllc(12)': TYPE_INTEGER,
      'hllc(14)': TYPE_INTEGER,
      'hllc(15)': TYPE_INTEGER,
      'hllc(16)': TYPE_INTEGER,
      'float': TYPE_FLOAT,
      'double': TYPE_FLOAT,
      'decimal': TYPE_FLOAT,
      'real': TYPE_FLOAT,
      'numeric': TYPE_FLOAT,
      'boolean': TYPE_BOOLEAN,
      'bool': TYPE_BOOLEAN,
      'date': TYPE_DATE,
      'datetime': TYPE_DATETIME,
      'timestamp': TYPE_DATETIME,
      'time': TYPE_DATETIME,
      'varchar': TYPE_STRING,
      'char': TYPE_STRING,
      'string': TYPE_STRING,
  }
  
  class KylinAPI(BaseQueryRunner):
      @classmethod
      def configuration_schema(cls):
          return {
              "type": "object",
              "properties": {
                  "user": {
                      "type": "string",
                      "title": "Kylin Username",
                  },
                  "password": {
                      "type": "string",
                      "title": "Kylin Password",
                  },
                  "url": {
                      "type": "string",
                      "title": "Kylin API URL",
                      "default": "http://kylin.example.com/kylin/",
                  },
                  "project": {
                      "type": "string",
                      "title": "Kylin Project",
                  },
              },
              "order": ['url', 'project', 'user', 'password'],
              "required": ["url", "project", "user", "password"],
              "secret": ["password"]
          }
  
      def run_query(self, query, user):
          url = self.configuration['url']
          kylinuser = self.configuration['user']
          kylinpass = self.configuration['password']
          kylinproject = self.configuration['project']
  
          resp = requests.post(
              os.path.join(url, "api/query"), 
              auth=HTTPBasicAuth(kylinuser, kylinpass),
              json={
                  "sql": query,
                  "offset": 0,
                  "limit": 50000,
                  "acceptPartial": False,
                  "project": kylinproject
              }
          )
  
          if not resp.ok:
              return {}, resp.text or str(resp.reason)
  
          data = resp.json()
          columns = self.get_columns(data['columnMetas'])
          rows = self.get_rows(columns, data['results'])
  
          return json.dumps({'columns': columns, 'rows': rows}), None
  
      def get_schema(self, get_stats=False):
          url = self.configuration['url']
          kylinuser = self.configuration['user']
          kylinpass = self.configuration['password']
          kylinproject = self.configuration['project']
  
          resp = requests.get(
              os.path.join(url, "api/tables_and_columns"), 
              params={"project": kylinproject},
              auth=HTTPBasicAuth(kylinuser, kylinpass),
          )
  
          resp.raise_for_status()
  
          data = resp.json()
          return [self.get_table_schema(table) for table in data]
  
      def test_connection(self):
          url = self.configuration['url']
          requests.get(url).raise_for_status()
  
      def get_columns(self, colmetas):
          return self.fetch_columns([
              (meta['name'], types_map.get(meta['columnTypeName'].lower(), TYPE_STRING))
              for meta in colmetas
          ])
  
      def get_rows(self, columns, results):
          return [
              dict(zip((c['name'] for c in columns), row))
              for row in results
          ]
  
      def get_table_schema(self, table):
          name = table['table_NAME']
          columns = [col['column_NAME'].lower() for col in table['columns']]
          return {"name": name, "columns": columns}
  
  register(KylinAPI)
  