Example #1
0
 def __init__(self,objectname=None,path=None, config = {}):
     self.objectname=objectname
     if not self.objectname:
         if path:
             self.objectname=self.get_objectname_by_path(path)
         elif config:
             self.obj = config
         else:
             raise ObjectInitError('parameter objectname | path | config  is required!')
     if not config:
         self._get_config()
     try:
         self._check_config()
     except Exception as e:
         raise ObjectConfigError('object `'+str(self.objectname)+'` configuration error:   '+str(e))
     self._auto_gen_config()
     self.Data = Data(self.objectname, self.DB, self.FIELDS_ALIAS, self.METADB)
Example #2
0
class DataModel(object):
    def __init__(self,objectname=None,path=None, config = {}):
        self.objectname=objectname
        if not self.objectname:
            if path:
                self.objectname=self.get_objectname_by_path(path)
            elif config:
                self.obj = config
            else:
                raise ObjectInitError('parameter objectname | path | config  is required!')
        if not config:
            self._get_config()
        try:
            self._check_config()
        except Exception as e:
            raise ObjectConfigError('object `'+str(self.objectname)+'` configuration error:   '+str(e))
        self._auto_gen_config()
        self.Data = Data(self.objectname, self.DB, self.FIELDS_ALIAS, self.METADB)


    def check_new_config(self):
        testtable = 'jdata_config_test_table'

        try:
            self.Data.createtable(testtable)
            self.Data.droptable(testtable)
            #self.Data.query('drop table '+testtable,iscache=False, tablename = testtable)
        except Exception as e:
            raise ObjectConfigTestError('object `%s` configuration test : Create Table Error ! %s' %(self.objectname, str(e)))
        try:
            self.Data.createtable(testtable)
            self.Data.query('select * from '+testtable, iscache=False, tablename = testtable)
            self.Data.droptable(testtable)
            #self.Data.query('drop table '+testtable, iscache=False, tablename = testtable)
        except:
            raise ObjectConfigTestError('object `'+self.objectname+'` configuration test  error: Replication Lag ? ')
        
            
    def _get_config(self):
        #os.chdir(project_dir)
        try:_o = ObjectConfig.objects.get(key = self.objectname)
        except:raise ObjectNotFound('object `'+self.objectname+'` not found.')
        self.obj = simplejson.loads(_o.value)
    
    def _check_config(self):
        self.objectname = self.obj['KEY']
        self.FIELDS_DISPNAME = {}
        self.DB = self.obj['DB']
        _s = self.DB['mysql']['table_split_idx']
        self.DB['mysql']['table_split_idx'] = int(_s)
        #mysqlconfig = self.DB['mysql']['writerurl']
        _METADB = self.obj['METADB']
        self.METADB = []
        for i in _METADB:
            self.METADB.append((i['name'],i['lambda'],i['alias']))
            self.FIELDS_DISPNAME[i['name']] = i['alias']
        _FIELDS_ALIAS = self.obj['FIELDS_ALIAS']
        self.FIELDS_ALIAS={}
        for i in _FIELDS_ALIAS:
            self.FIELDS_ALIAS[i['name']] = (i['lambda'],i['alias'])
            self.FIELDS_DISPNAME[i['name']] = i['alias']
        self.NAME = self.obj['NAME']
        

    def _auto_gen_config(self):
        #self.URL_ALIAS = self.obj.get('URL_ALIAS',{'s':'starttime','e':'endtime'})
        self.SHOW_IN_QUERY = self.obj.get('SHOW_IN_QUERY',False)
        _ALLOWIPS = self.obj.get('ALLOWIPS',[])
        self.ALLOWIPS = [i['ip'] for i in _ALLOWIPS]

        #generel METADB_CHART
        str_fields =  [ i[0] for i in  list(self.METADB) if 'char' in i[1]]
        str_fields.remove(self.FIELDS_ALIAS['timeline'][0])
        int_fields = self.FIELDS_ALIAS.keys() + [ i[0] for i in  list(self.METADB) if ('int' in i[1] or 'float' in i[1])]
        int_fields.remove('timeline') 
        self.METADB_CHART = {}
        for i in str_fields:
            self.METADB_CHART[i] = {'p':i,'name':(self.FIELDS_DISPNAME.get(i) or i),'pageby':True,'filter':True,'fields':False}
        for i in int_fields:
            self.METADB_CHART[i] = {'p':i,'name':(self.FIELDS_DISPNAME.get(i) or i),'pageby':False,'filter':False,'fields':True}
        
        
        
    def get_objectname_by_path(self,path):
        url_q = QueryDict(path)
        if url_q.has_key('_o'):
            return url_q['_o']
        if url_q.has_key('_sql'):
            return self.get_query_dict_by_sql(url_q['_sql'])['_o']
        raise URLParameterError('parameter  `_o` is required.') 

  
    def get_query_dict_by_sql(self, base64_sql):
        src_sql = base64.b64decode(base64_sql)
        sql = src_sql.lower().strip().replace('\n', ' ').replace('\t', ' ')
        while True:
            if sql.find('  ')>0:
                sql = sql.replace('  ',' ')
            else:
                break
        if not sql.startswith('select'):
            raise URLParameterError('You have an error in your SQL syntax: [%s]' %src_sql)

        # 去掉select关键字
        sql = sql[6:]
        
        try:
            (sql_1, sql_2) = sql.split(' from ')
        except ValueError:
            raise URLParameterError('You have an error in your SQL syntax: no `from` found. [%s]' %src_sql)
        
        # 拿到查询的字段 _fields  sql_1=' _tstep:5 _refresh field1,field2 '
        fields = [i.strip() for i in sql_1.split(',') if i.strip()]
        _fields = [fields[0].split()[-1],] + fields[1:]
                
        # 获取其他jdata参数 
        jdata_paras  = fields[0].split()[:-1]
        

        # 获取表名:_o   
        # where后面的过滤条件: sql_w --> _filters
        # group by后面的分组条件: sql_g --> _pageby

        try:
            (sql_o_w, sql_g) = sql_2.split(' group by ')
            
        except ValueError:
            sql_o_w = sql_2
            sql_g = ''
        
        try:
            _o, sql_w = sql_o_w.split(' where ')
        except ValueError:
            _o = sql_o_w
            sql_w = ''

        #  _filters
        _filters = []
        _s = ''
        _e = ''
        for i in  sql_w.split(' and '):
            i = i.strip()
            if not i:
                continue
            if i.startswith('ptime'):
                if i.find('>=')>0:
                    _s = i.split('>=')[1]
                elif i.find('>')>0:
                    _s = i.split('>')[1]
                elif i.find('<=')>0:
                    _e = i.split('<=')[1]
                elif i.find('<')>0:
                    _e = i.split('<')[1]
                elif i.find('=')>0:
                    _s = i.split('=')[1]
                    _e = i.split('=')[1]
                else:
                    raise URLParameterError('You have an error in your SQL syntax: `%s` [%s]' %(i,src_sql))
            else:
                _filters.append(i)
        _s = _s.strip()
        _e = _e.strip()

        # _pageby 
        _pageby = [i for i in sql_g.split(',') if i ]

        query_dict =  {'_o':_o,
                '_fields':_fields,
                '_filters':_filters,
                '_pageby':_pageby,
                }

        # _s & _e
        if _s:
            query_dict['_s'] = _s
        if _e:
            query_dict['_e'] = _e
    
        # set jdata_paras
        for i in jdata_paras:
            if i.find(':')>0:
                (k, v) = i.split(':')
                query_dict[k] = v
            else:
                query_dict[i] = ''
        
        return query_dict

 
    def get_query_dict(self,path):
        path = urllib2.unquote(path)
        items=QueryDict(path).items()
        query_dict={}
        query_dict['_pageby']=[]
        query_dict['_fields']=[]
        query_dict['_filters']=[]
        for i in items:
            if i[0] == '_o' :
                query_dict['_o']=i[1]
        for i in items:
            k = i[0][i[0].find('?')+1:]
            if k =='_pageby':
                if len(i[1])>0:
                    for f in i[1].split(','):
                        query_dict['_pageby'].append(f)
            elif k =='_fields':
                for f in i[1].split(','):
                    query_dict['_fields'].append(f)
            elif k.find('_') == 0:
                query_dict[k] = i[1]
            elif k == '':
                continue
            else:
                if i[1]=='':
                    query_dict['_filters'].append(k)
                elif i[1].find('%')>=0:
                    query_dict['_filters'].append(k+' like "'+i[1]+'"')
                else:
                    query_dict['_filters'].append(k+'="'+i[1]+'"')
        if query_dict.has_key('_sql'):
            query_dict =  self.get_query_dict_by_sql(query_dict['_sql'])
                
        if query_dict.has_key('_nocheck') or query_dict.has_key('_nourlcheck'):
            return query_dict
        if not query_dict.has_key('_o'):
            raise URLParameterError('parameter  `_o` is required.')
        if len(query_dict['_fields'])==0:
            raise URLParameterError('parameter  `_fields` is required.')
        self._check_query_dict(query_dict)
        return query_dict



    def _check_query_dict(self, query_dict):
        for i in query_dict['_fields']:
            keys = self.FIELDS_ALIAS.keys() + self.Data.cols
            if i not in keys:
                raise URLParameterError('Unknown field `'+i+'`  , expecting one of: "'+', '.join(keys)+'"')
        for i in query_dict['_filters'] + query_dict['_pageby']:
            i = i.split()[0].split('=')[0]
            if not (i in self.Data.cols):
                raise URLParameterError('Unknown field `'+i+'` , expecting one of: "'+', '.join(self.Data.cols)+'"')

        # tstep有效性检查
        # 默认5分钟,必须填整数,单位分钟
        # 如果长度超过了分表粒度,则报错
        tstep = query_dict.get('_tstep',5)
        try:
            tstep = int(tstep)
        except ValueError:
            raise URLParameterError('The value of parameter `_tstep` must integer')

        split_idx = self.DB['mysql']['table_split_idx']
        if split_idx <= 8:  # 分表粒度为day month year的,最大tstep是1 day
            max_tstep = 60*24
        elif split_idx == 10:  # 分表粒度为 Hour 的,最大tstep是1 hour
            max_tstep = 60
        elif split_idx == 12: #分表粒度为 minute的,最大tstep是1 minute
            max_tstep = 1;
        if int(tstep) > max_tstep:
            raise URLParameterError('`_tstep` must less than %s minute ,default is 5(min), current value is %s' %(max_tstep, tstep))