0:
127 | dsl_body['aggs'] = metrics
128 | dsl_body['size'] = 0
129 | return dsl_body
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/elsh/Command.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import sys
3 | from pygments.token import (Keyword,
4 | Comment,
5 | Operator,
6 | Number,
7 | Literal,
8 | String,
9 | Error)
10 | from prompt_toolkit import AbortAction, prompt
11 | from prompt_toolkit.contrib.completers import WordCompleter
12 | from prompt_toolkit.history import InMemoryHistory
13 | from pygments.style import Style
14 | from pygments.styles.default import DefaultStyle
15 | from pygments.token import Token
16 | import os
17 | import urllib3
18 | from tabulate import tabulate
19 | import json
20 | from pygments.lexers.sql import SqlLexer
21 |
22 |
23 | sql_completer = WordCompleter(['create', 'select', 'insert', 'drop',
24 | 'delete', 'from', 'where', 'table',
25 | 'bulk','update','limit','group','by',
26 | 'index.number_of_shards','index.number_of_replicas',
27 | 'index.flush_inteval','moving_avg','date_range','date_histogram'], ignore_case=True)
28 |
29 |
30 | def do_esql(database,statement):
31 | url = database.host.rstrip() + database.url
32 | http = urllib3.PoolManager()
33 | try:
34 | res = http.request('POST', url, fields = {"sql":statement})
35 | except Exception as e:
36 | print(str(e))
37 | return
38 | if res.status != 200:
39 | print(res.data.decode('utf-8'))
40 | else:
41 | gb = json.loads(res.data.decode('utf-8'))
42 | table = gb['rows']
43 | headers = gb['cols']
44 | print(tabulate(table, headers, tablefmt="grid",disable_numparse=True))
45 | if 'total' not in gb:
46 | gb['total'] = 0
47 | if 'took' not in gb:
48 | gb['took'] = 0
49 | print('%d rows affected (%.3f seconds) '%(gb['total'],gb['took']/1000))
50 |
51 |
52 | class DocumentStyle(Style):
53 | styles = {
54 | Token.Menu.Completions.Completion.Current: 'bg:#00aaaa #000000',
55 | Token.Menu.Completions.Completion: 'bg:#008888 #ffffff',
56 | Token.Menu.Completions.ProgressButton: 'bg:#003333',
57 | Token.Menu.Completions.ProgressBar: 'bg:#00aaaa',
58 | Keyword: 'bold #4b95a3',
59 | Comment: '#757265',
60 | Operator: '#e83131',
61 | Number: '#be61ff',
62 | Literal: '#ae81ff',
63 | String: '#f4a33d',
64 | Error: '#ff3300',
65 | }
66 | styles.update(DefaultStyle.styles)
67 |
68 |
69 | class Database():
70 |
71 | __slots__ = ('host','url','user','passwd')
72 | def __init__(self,host):
73 | self.url = '/esql'
74 | self.host = host
75 | self.user = ''
76 | self.passwd = ''
77 |
78 | def set_host(self,host):
79 | self.url = host
80 |
81 | def set_urer(self,user,passwd):
82 | self.user = user
83 | self.passwd = passwd
84 |
85 |
86 | def do_config(args,database):
87 | config = args.split(' ')
88 | if config[0] == 'connect':
89 | database.host = config[1]
90 |
91 | def main(database):
92 | history = InMemoryHistory()
93 | input_line = ''
94 | newline=True
95 | while True:
96 | try:
97 | if newline:
98 | text = prompt('esql> ',lexer = SqlLexer, completer=sql_completer,
99 | style=DocumentStyle, history=history,
100 | on_abort=AbortAction.RETRY)
101 | else:
102 | text = prompt('...> ', lexer = SqlLexer,completer=sql_completer,
103 | style=DocumentStyle, history=history,
104 | on_abort=AbortAction.RETRY)
105 |
106 | input_line += os.linesep + text.rstrip()
107 | if input_line.endswith(';'):
108 | if input_line[1] == '\\':
109 | do_config(input_line[2:len(input_line)-1],database)
110 | else:
111 | do_esql(database,input_line[:len(input_line)-1])
112 | newline = True
113 | input_line = ''
114 | else:
115 | newline = False
116 |
117 | except EOFError:
118 | break # Control-D pressed.
119 | print('GoodBye!')
120 |
121 | if __name__ == '__main__':
122 | if len(sys.argv) < 2:
123 | db = 'http://127.0.0.1:5000'
124 | else:
125 | db = sys.argv[1]
126 |
127 | print('Ctrl + D Quit Esql shell')
128 | main(Database(db))
129 |
130 |
131 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # esql5
2 | elsh is an interactive esql5 command line interface (CLI) SQL shell with autocompletion. support elasticserch5.x,2.x,1.x
3 | 
4 |
5 | explain
6 | 
7 |
8 | 特性介绍
9 | ----------------
10 | #接近标准SQL语法
11 |
12 | create table my_index.my_table (
13 | id keyword,
14 | name text,
15 | age long,
16 | birthday date
17 | );
18 |
19 | select * from my_index.my_type;
20 |
21 | select count(*) from my_index.my_table group by age;
22 |
23 |
24 | #Create table
25 |
26 | 字段参数,ES中分词规则、索引类型、字段格式等高级参数的支持
27 |
28 | create table my_table (
29 | name text (analyzer = ik_max_word),
30 | dd text (index=no),
31 | age long (include_in_all=false)
32 | );
33 |
34 |
35 | 对象、嵌套字段支持 as
36 |
37 | create table my_index (
38 | id long,
39 | name text,
40 | obj object as (
41 | first_name text,
42 | second_name text (analyzer=pinyin)
43 | )
44 | );
45 |
46 |
47 | create table my_index (
48 | id long,
49 | name text,
50 | obj nested as (
51 | first_name text,
52 | second_name text (analyzer=pinyin)
53 | )
54 | );
55 |
56 |
57 | ES索引高级参数支持 with option
58 |
59 | create table my_index (
60 | id long,
61 | name text
62 | ) with option (
63 | index.number_of_shards=10,
64 | index.number_of_replicas = 1
65 | );
66 |
67 |
68 | #Insert/Bulk
69 |
70 | 单条数据插入
71 | insert into my_index.index (name,age) values ('zhangsan',24);
72 |
73 | 多条插入
74 | bulk into my_index.index (name,age) values ('zhangsan',24),('lisi',24);
75 |
76 |
77 | 对象数据插入,[]list,{}Map
78 |
79 | insert into my_index.index (ds) values (['zhejiang','hangzhou']);
80 |
81 | insert into my_index.index (dd) values ({address='zhejiang',postCode='330010'});
82 |
83 |
84 | #select/Aggregations
85 |
86 | select * from my_table.my_index where name like 'john *' and age between 20 and 30 and (hotel = 'hanting' or flight = 'MH4510');
87 |
88 | 查询指定路由
89 | select * from my_table@'00001' where name = 'jack';
90 |
91 | 地理位置中心点查询
92 | select * from hz_point where geo_distance({distance='1km',location='30.306378,120.247427'});
93 |
94 | 地理坐标区域查询
95 | select * from hz_point where geo_bounding_box({location={top_left='31.306378,119.247427',bottom_right='29.285797,122.172329'}});
96 |
97 | pipeline统计 move_avg
98 | select count(*) as total, moving_avg({buckets_path=total}) from my_index group by date_histogram({field=timestamp,interval='1h'});
99 |
100 |
101 | #explain
102 |
103 |
104 |
105 | esql> explain select max(KSSJ) from my_test group by date_histogram({field=ts,interval='1h'});
106 |
107 | {
108 | "_source": [],
109 | "aggs": {
110 | "ts": {
111 | "aggs": {
112 | "_0_max": {
113 | "max": {
114 | "field": "KSSJ"
115 | }
116 | }
117 | },
118 | "date_histogram": {
119 | "field": "ts",
120 | "interval": "1h"
121 | }
122 | }
123 | },
124 | "query": {
125 | "match_all": {}
126 | },
127 | "size": 0
128 | }
129 |
130 |
131 |
132 | Getting Started
133 | ----------------
134 | 环境要求python >= 2.7
135 |
136 | export PYTHONHOME=(%python_path)
137 | export PATH=$PYTHONHOME/bin:$PATH
138 |
139 |
140 | 安装第三方依赖包
141 | pip install -r esql5.egg-info/requires.txt
142 | 或python setup.py install
143 |
144 | 修改配置文件esql5/conf
145 |
146 | elastic: {
147 | hosts: [
148 | {
149 | host: 127.0.0.1
150 | port: 9200
151 | }
152 | ]
153 | }
154 |
155 | 运行esql5服务
156 | (standalone):
157 | cd esql5
158 | python -m App.app
159 |
160 | (with uwsgi)
161 | cd esql5/bin
162 | ./service start
163 |
164 |
165 | shell终端:
166 | cd esql5/bin
167 | ./elsh
168 |
169 | JDBC驱动:
170 | https://github.com/unimassystem/elasticsearch-jdbc
171 |
172 | String sql = "select SRC_IP,SRC_PORT from my_test* where SRC_PORT between 10 and 100 limit 1000";
173 | String url = "jdbc:elasticsearch://127.0.0.1:5000";
174 | Connection connection = DriverManager.getConnection(url, "test", null);
175 | Statement statement = connection.createStatement();
176 | ResultSet rs = statement.executeQuery(sql);
177 | ResultSetMetaData meta = rs.getMetaData();
178 | String columns = "|";
179 | for (int i = 0; i < meta.getColumnCount(); i++) {
180 | columns += meta.getColumnLabel(i) + " | ";
181 | }
182 | System.out.println(columns);
183 | while (rs.next()) {
184 | String row = "|";
185 | for (int i = 0; i < meta.getColumnCount(); i++) {
186 | row += rs.getString(i) + " | ";
187 | }
188 | System.out.println(row);
189 | }
190 |
191 |
192 |
--------------------------------------------------------------------------------
/ql/dsl/QueryBody.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Jan 13, 2017
3 |
4 | @author: qs
5 | '''
6 |
7 | from ql.dsl import parse_left_values,parse_right_values,parse_value,parse_object
8 | from ql.parse.ASTNode import Node
9 | from ql.parse.parser import TK
10 |
11 | def query_string_query(left_val,right_val,operator='AND'):
12 | return {
13 | 'query_string':{
14 | 'default_operator': operator,
15 | 'query': right_val,
16 | 'fields': left_val
17 | }
18 | }
19 |
20 |
21 | def range_query(compare,left_val,right_val):
22 | if compare == '>':
23 | compare = 'gt'
24 | elif compare == '<':
25 | compare = 'lt'
26 | elif compare == '>=':
27 | compare = 'gte'
28 | elif compare == '<=':
29 | compare = 'lte'
30 | return {
31 | 'range': {
32 | left_val[0]:{
33 | compare:right_val
34 | }
35 | }
36 | }
37 |
38 |
39 | def wildcard_query(left_val,right_val):
40 | return {'wildcard': {left_val[0]:right_val}}
41 |
42 |
43 |
44 |
45 | def between_query(fun_parms):
46 | parms = parse_right_values(fun_parms)
47 | return {
48 | 'range': {
49 | parms[0]:{
50 | 'gte':parms[1],
51 | 'lte':parms[2],
52 | }
53 | }
54 | }
55 |
56 |
57 | def query_missing(fun_parms):
58 | parms = parse_right_values(fun_parms)
59 | return {
60 | 'constant_score': {
61 | 'filter': {
62 | 'missing': {
63 | 'field': parms[0]
64 | }
65 | }
66 | }
67 | }
68 |
69 | def other_functions(name,parms):
70 | retval={name:{}}
71 | for e in parms:
72 | if e.get_type() == TK.TOK_DICT:
73 | retval[name].update(parse_object(e))
74 | return retval
75 |
76 |
77 |
78 |
79 | def function_expression_dsl(name, parms):
80 | if name.lower() == 'between':
81 | return between_query(parms)
82 | if name.lower() == 'isnull':
83 | return query_missing(parms)
84 | else:
85 | return other_functions(name,parms)
86 |
87 |
88 |
89 | def compare_expression_dsl(compare,left_val,right_val):
90 | if compare == '=':
91 | return query_string_query(left_val,right_val)
92 | elif compare in ['>','>=','<','<=']:
93 | return range_query(compare,left_val,right_val)
94 | elif compare.lower() == 'like':
95 | return wildcard_query(left_val,right_val)
96 |
97 |
98 | def in_expression_dsl(left_val,right_val):
99 | return query_string_query(left_val,' '.join(right_val),'OR')
100 |
101 |
102 | class FunctionExpression(object):
103 | __slots__ = ('function_name','function_parms')
104 | def __init__(self,tree: Node):
105 | self.function_name = tree.get_value()
106 | self.function_parms = tree.get_children()
107 | def dsl(self):
108 | return function_expression_dsl(self.function_name,self.function_parms)
109 |
110 |
111 | class INExpression(object):
112 | __slots__ = ('left_values','right_value')
113 | def __init__(self,tree: Node):
114 | self.left_values = parse_left_values(tree.get_child(0).get_children())
115 | self.right_value = parse_right_values(tree.get_child(1).get_children())
116 | def dsl(self):
117 | return in_expression_dsl(self.left_values,self.right_value)
118 |
119 |
120 | def query_expression(tree: Node):
121 | if tree.get_type() == TK.TOK_COMPARE:
122 | return CompareExpression(tree)
123 | if tree.get_type() == TK.TOK_FUNCTION:
124 | return FunctionExpression(tree)
125 | if tree.get_type() == TK.TOK_IN:
126 | return INExpression(tree)
127 |
128 |
129 | class CompareExpression(object):
130 |
131 | __slots__ = ('compare','left_values','right_value')
132 |
133 | def __init__(self,tree: Node):
134 | self.compare = tree.get_value().lower()
135 | if tree.get_child(0).get_type() == TK.TOK_EXPRESSION_LEFT:
136 | self.left_values = parse_left_values(tree.get_child(0).get_children())
137 | if tree.get_child(1).get_type() == TK.TOK_EXPRESSION_RIGHT:
138 | if len(parse_right_values(tree.get_child(1).get_children())) > 0:
139 | self.right_value = parse_right_values(tree.get_child(1).get_children())[0]
140 | else:
141 | self.right_value = None
142 | def dsl(self):
143 | return compare_expression_dsl(self.compare,self.left_values,self.right_value)
144 |
145 |
146 |
147 | class QueryBody(object):
148 |
149 | __slots__ = ('combine','root','reversed','lchild','rchild')
150 |
151 | def __init__(self,tree: Node,root=True):
152 |
153 | if tree.get_type() == TK.TOK_REVERSED:
154 | tree = tree.get_child(0)
155 | self.reversed = True
156 |
157 | self.root = root;
158 | self.combine = 'must'
159 | if tree.get_type() == TK.TOK_COMPOUND:
160 | self.combine = tree.get_value()
161 | self.lchild = QueryBody(tree.get_child(0),False)
162 | self.rchild = QueryBody(tree.get_child(1),False)
163 | else:
164 | self.lchild = query_expression(tree)
165 |
166 |
167 | def dsl(self):
168 | ret = {}
169 | if self.combine == 'and':
170 | self.combine = 'must'
171 | if self.combine == 'or':
172 | self.combine = 'should'
173 | if self.root:
174 | ret = {'bool': {}}
175 | ret['bool'][self.combine] = [self.lchild.dsl()]
176 | if hasattr(self, 'rchild'):
177 | ret['bool'][self.combine].append(self.rchild.dsl())
178 | else:
179 | if hasattr(self, 'rchild'):
180 | ret = {'bool': {}}
181 | ret['bool'][self.combine] = [self.lchild.dsl()] + [self.rchild.dsl()]
182 | else:
183 | ret = self.lchild.dsl()
184 | if hasattr(self, 'reversed') and self.reversed == True:
185 | rev = {'bool': {}}
186 | rev['bool']['must_not'] = [ret]
187 | ret = rev
188 | return ret
189 |
190 |
191 |
192 |
193 |
--------------------------------------------------------------------------------
/head/lang/zh_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs": "加载聚合查询...",
4 | "General.Searching": "搜索中...",
5 | "General.Search": "搜索",
6 | "General.Help": "帮助",
7 | "General.HelpGlyph": "?",
8 | "General.CloseGlyph": "X",
9 | "General.RefreshResults": "刷新",
10 | "General.ManualRefresh": "手动刷新",
11 | "General.RefreshQuickly": "快速刷新",
12 | "General.Refresh5seconds": "每5秒刷新",
13 | "General.Refresh1minute": "每1分钟刷新",
14 | "AliasForm.AliasName": "别名",
15 | "AliasForm.NewAliasForIndex": "为 {0} 创建新别名",
16 | "AliasForm.DeleteAliasMessage": "输入 ''{0}'' 删除 {1}. 此操作无法恢复",
17 | "AnyRequest.DisplayOptions" : "显示选项",
18 | "AnyRequest.AsGraph" : "图形视图",
19 | "AnyRequest.AsJson" : "原始 JSON",
20 | "AnyRequest.AsTable" : "表格视图",
21 | "AnyRequest.History" : "历史记录",
22 | "AnyRequest.RepeatRequest" : "重复请求",
23 | "AnyRequest.RepeatRequestSelect" : "重复周期 ",
24 | "AnyRequest.Transformer" : "结果转换器",
25 | "AnyRequest.Pretty": "易读",
26 | "AnyRequest.Query" : "查询",
27 | "AnyRequest.Request": "提交请求",
28 | "AnyRequest.Requesting": "请求中...",
29 | "AnyRequest.ValidateJSON": "验证 JSON",
30 | "Browser.Title": "数据浏览",
31 | "Browser.ResultSourcePanelTitle": "原始数据",
32 | "Command.DELETE": "删除",
33 | "Command.SHUTDOWN": "关闭",
34 | "Command.DeleteAliasMessage": "删除别名?",
35 | "ClusterOverView.IndexName": "索引名称",
36 | "ClusterOverview.NumShards": "分片数",
37 | "ClusterOverview.NumReplicas": "副本数",
38 | "ClusterOverview.NewIndex": "新建索引",
39 | "IndexActionsMenu.Title": "动作",
40 | "IndexActionsMenu.NewAlias": "新建别名...",
41 | "IndexActionsMenu.Refresh": "刷新",
42 | "IndexActionsMenu.Flush": "Flush刷新",
43 | "IndexActionsMenu.Optimize": "优化...",
44 | "IndexActionsMenu.Snapshot": "网关快照",
45 | "IndexActionsMenu.Analyser": "测试分析器",
46 | "IndexActionsMenu.Open": "开启",
47 | "IndexActionsMenu.Close": "关闭",
48 | "IndexActionsMenu.Delete": "删除...",
49 | "IndexInfoMenu.Title": "信息",
50 | "IndexInfoMenu.Status": "索引状态",
51 | "IndexInfoMenu.Metadata": "索引信息",
52 | "IndexCommand.TextToAnalyze": "文本分析",
53 | "IndexCommand.ShutdownMessage": "输入 ''{0}'' 以关闭 {1} 节点. 关闭的节点无法从此界面重新启动",
54 | "IndexOverview.PageTitle": "索引概览",
55 | "IndexSelector.NameWithDocs": "{0} ({1} 个文档)",
56 | "IndexSelector.SearchIndexForDocs": "搜索 {0} 的文档, 查询条件:",
57 | "FilterBrowser.OutputType": "返回格式: {0}",
58 | "FilterBrowser.OutputSize": "显示数量: {0}",
59 | "Header.ClusterHealth": "集群健康值: {0} ({1} of {2})",
60 | "Header.ClusterNotConnected": "集群健康值: 未连接",
61 | "Header.Connect": "连接",
62 | "Nav.AnyRequest": "复合查询",
63 | "Nav.Browser": "数据浏览",
64 | "Nav.ClusterHealth": "集群健康值",
65 | "Nav.ClusterState": "群集状态",
66 | "Nav.ClusterNodes": "集群节点",
67 | "Nav.Info": "信息",
68 | "Nav.NodeStats": "节点状态",
69 | "Nav.Overview": "概览",
70 | "Nav.Indices": "索引",
71 | "Nav.Plugins": "插件",
72 | "Nav.Status": "状态",
73 | "Nav.Templates": "模板",
74 | "Nav.StructuredQuery": "基本查询",
75 | "NodeActionsMenu.Title": "动作",
76 | "NodeActionsMenu.Shutdown": "关停...",
77 | "NodeInfoMenu.Title": "信息",
78 | "NodeInfoMenu.ClusterNodeInfo": "集群节点信息",
79 | "NodeInfoMenu.NodeStats": "节点状态",
80 | "NodeType.Client": "节点客户端",
81 | "NodeType.Coord": "协调器",
82 | "NodeType.Master": "主节点",
83 | "NodeType.Tribe": "分支结点",
84 | "NodeType.Worker": "工作节点",
85 | "NodeType.Unassigned": "未分配",
86 | "OptimizeForm.OptimizeIndex": "优化 {0}",
87 | "OptimizeForm.MaxSegments": "最大索引段数",
88 | "OptimizeForm.ExpungeDeletes": "只删除被标记为删除的",
89 | "OptimizeForm.FlushAfter": "优化后刷新",
90 | "OptimizeForm.WaitForMerge": "等待合并",
91 | "Overview.PageTitle" : "集群概览",
92 | "Output.JSON": "JSON",
93 | "Output.Table": "Table",
94 | "Output.CSV": "CSV",
95 | "Output.ShowSource": "显示查询语句",
96 | "Preference.SortCluster": "集群排序",
97 | "Sort.ByName": "按名称",
98 | "Sort.ByAddress": "按地址",
99 | "Sort.ByType": "按类型",
100 | "TableResults.Summary": "查询 {1} 个分片中用的 {0} 个. {2} 命中. 耗时 {3} 秒",
101 | "QueryFilter.AllIndices": "所有索引",
102 | "QueryFilter.AnyValue": "任意",
103 | "QueryFilter-Header-Indices": "索引",
104 | "QueryFilter-Header-Types": "类型",
105 | "QueryFilter-Header-Fields": "字段",
106 | "QueryFilter.DateRangeHint.from": "从 : {0}",
107 | "QueryFilter.DateRangeHint.to": " 到 : {0}",
108 | "Query.FailAndUndo": "查询失败. 撤消最近的更改",
109 | "StructuredQuery.ShowRawJson": "显示原始 JSON"
110 | });
111 |
112 | i18n.setKeys({
113 | "AnyRequest.TransformerHelp" : "\
114 | 结果转换器用于返回结果原始JSON的后续处理, 将结果转换为更有用的格式.
\
115 | 转换器应当包含javascript函数体. 函数的返回值将传递给json分析器
\
116 | Example:
\
117 | return root.hits.hits[0];
\
118 | 遍历结果并只显示第一个元素
\
119 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0);
\
120 | 将返回整个集群使用的总内存
\
121 | 以下函数可以方便的处理数组与对象
\
122 |
\
123 | - Object.keys(object) := array
\
124 | - array.forEach(function(prop, index))
\
125 | - array.map(function(prop, index)) := array
\
126 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
127 |
\
128 | 当启用重复请求时, prev 参数将会传递给转换器函数. 这将用于比较并累加图形
\
129 | Example:
\
130 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la;
\
131 | 将返回第一个集群节点最近一分钟内的平均负载\
132 | 将会把结果送人图表以产生一个负载曲线图\
133 | "
134 | });
135 |
136 | i18n.setKeys({
137 | "AnyRequest.DisplayOptionsHelp" : "\
138 |
原始 Json: 将完整的查询结果转换为原始JSON格式
\
139 | 图形视图: 将查询结果图形化, 将查询结果转换为数组值的形式
\
140 | 表格视图: 如果查询是一个搜索, 可以将搜索结果以表格形式显示.
\
141 | "
142 | });
143 |
144 | i18n.setKeys({
145 | "QueryFilter.DateRangeHelp" : "\
146 | Date 字段接受日期范围的形式查询.
\
147 | 一下格式被支持:
\
148 | \
149 | - 关键词 / 关键短语
\
150 | now
today
tomorrow
yesterday
last / this / next + week / month / year
\
151 | 搜索关键字匹配的日期. last year 将搜索过去全年. \
152 | - 范围
\
153 | 1000 secs
5mins
1day
2days
80d
9 months
2yrs (空格可选, 同等于多个范围修饰词)
\
154 | 创建一个指定时间范围的搜索, 将围绕现在 并延伸至过去与未来时间段. \
155 | - DateTime 与 DateTime局部
\
156 | 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
157 | 指定一个特定的日期范围. 2011会搜索整个 2011年, 而 2011-01-18 12:32:45 将只搜索1秒范围内 \
158 | - Time 与 Time局部
\
159 | 12
12:32
12:32:45
\
160 | 这些格式只搜索当天的特定时间. 12:32 将搜索当天的那一分钟 \
161 | - 日期范围
\
162 | 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
163 | 日期范围是将两个日期格式串 (日期关键字 / DateTime / Time) 用 < 或 -> (效果相同) 分隔. 如果缺少任意一端,那么在这个方向上时间将没有限制. \
164 | - 偏移日期范围
\
165 | 2010 -> 1yr
3mins < now\
166 | 搜索包括指定方向上偏移的日期. \
167 | - 锚定范围
\
168 | 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
169 | 类似于上面的便宜日期,在两个方向上将锚定的日期延长 \
170 |
\
171 | "
172 | });
173 |
--------------------------------------------------------------------------------
/ql/dsl/Response.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Mar 10, 2017
3 |
4 | @author: qs
5 | '''
6 |
7 | def parse_hit(cols,metas,hit):
8 | row = []
9 | for meta in metas:
10 | row.append(hit[meta])
11 | if '_source' not in hit:
12 | return row
13 |
14 | for col in cols:
15 | if col in hit['_source'].keys():
16 | row.append(hit['_source'][col])
17 | else:
18 | row.append(None)
19 | return row
20 |
21 |
22 | def parse_hits_cols(hits):
23 | fields = {}
24 | for hit in hits:
25 | if '_source' in hit:
26 | for key in hit['_source'].keys():
27 | fields[key] = True
28 | return list(fields.keys())
29 |
30 |
31 | def parse_hits(cols,hits):
32 | if 'hits' not in hits:
33 | return
34 | hits = hits['hits']
35 | metas = ['_id','_index','_type']
36 | # cols = parse_hits_cols(hits)
37 | rows = []
38 | for hit in hits:
39 | rows.append(parse_hit(cols,metas,hit))
40 | retval = {}
41 | retval['cols'] = metas + cols
42 | retval['rows'] = rows
43 | return retval
44 |
45 |
46 | def parse_aggs_cols(aggs,bks):
47 | for k in aggs.keys():
48 | if type(aggs[k]) != dict:
49 | continue
50 | if 'buckets' in aggs[k].keys():
51 | bks.append(k)
52 | buckets = aggs[k]['buckets']
53 | if len(buckets) > 0:
54 | parse_aggs_cols(buckets[0],bks)
55 |
56 |
57 |
58 | def parse_aggs_rows(aggs,bks,depth,rows,bucket_vals=[]):
59 | bucket_name = None
60 | if depth < len(bks):
61 | bucket_name = bks[depth]
62 | if 'buckets' in aggs[bucket_name] :
63 | for bucket in aggs[bucket_name]['buckets']:
64 | if 'key_as_string' in bucket:
65 | bucket_vals.append(bucket['key_as_string'])
66 | elif 'key' in bucket:
67 | bucket_vals.append(bucket['key'])
68 | else:
69 | bucket_vals.append(None)
70 | parse_aggs_rows(bucket,bks,depth + 1,rows,bucket_vals)
71 | if len(bucket_vals) > 0:
72 | bucket_vals.pop(len(bucket_vals) - 1)
73 | else:
74 | row = bucket_vals[:]
75 | mts = {}
76 | for mertic in aggs.keys():
77 | if type(aggs[mertic]) == dict and 'value' in aggs[mertic].keys():
78 | if 'value_as_string' in aggs[mertic].keys():
79 | mts[mertic] = aggs[mertic]['value_as_string']
80 | else:
81 | mts[mertic] = aggs[mertic]['value']
82 | rows.append((row,mts))
83 | if len(bucket_vals) > 0:
84 | bucket_vals.pop(len(bucket_vals) - 1)
85 | pass
86 |
87 |
88 |
89 | def get_agg_rows(bks,rows):
90 |
91 | mertics = {}
92 | for (bucket,mts) in rows:
93 | for m in mts.keys():
94 | mertics[m] = True
95 | for m in mertics.keys():
96 | bks.append(m)
97 | retval = []
98 | for (bucket,mts) in rows:
99 | row = bucket
100 | for m in mertics.keys():
101 | if m in mts.keys():
102 | row.append(mts[m])
103 | else:
104 | row.append(None)
105 | retval.append(row)
106 | return retval
107 |
108 |
109 | def parse_aggregations(aggs):
110 | bks = []
111 | depth = 0
112 | rows = []
113 | retval = {}
114 | parse_aggs_cols(aggs,bks)
115 | parse_aggs_rows(aggs,bks,depth,rows)
116 | row_sets = get_agg_rows(bks,rows)
117 | retval['cols'] = bks
118 | retval['rows'] = row_sets
119 | return retval
120 |
121 |
122 | def get_type_cols(tp):
123 | if 'properties' in tp.keys():
124 | return tp['properties'].keys()
125 |
126 | def get_inx_cols(inx):
127 | cols=[]
128 | if 'mappings' in inx.keys():
129 | for tp in inx['mappings']:
130 | cols.extend(get_type_cols(inx['mappings'][tp]))
131 | return cols
132 |
133 | def get_cols(mappings):
134 | cols=[]
135 | for inx in mappings.keys():
136 | cols.extend(get_inx_cols(mappings[inx]))
137 | return list(set(cols))
138 |
139 |
140 | def response_hits(res,mappings,selecols):
141 | response = {}
142 | if len(selecols) == 1 and selecols[0] == '*':
143 | cols = get_cols(mappings)
144 | else:
145 | cols = selecols
146 | if 'aggregations' in res.keys():
147 | response = parse_aggregations(res['aggregations'])
148 | response['total'] = len(response['rows'])
149 | elif 'hits' in res.keys() and 'aggregations' not in res.keys():
150 | response = parse_hits(cols,res['hits'])
151 | response['total'] = res['hits']['total']
152 | else:
153 | response['cols'] = []
154 | response['rows'] = []
155 | response['total'] = 1
156 | if 'took' in res:
157 | response['took'] = res['took']
158 | else:
159 | response['took'] = 0
160 |
161 | return response
162 |
163 |
164 |
165 | def response_nor(res,took):
166 | response = {}
167 | response['cols'] = []
168 | response['rows'] = []
169 | response['total'] = 1
170 | response['took'] = took
171 | return response
172 |
173 |
174 | def _parse_cat_json(res,response):
175 | cols= {}
176 | for row in res:
177 | for col in row.keys():
178 | cols[col] = True
179 | response['cols'] = list(cols.keys())
180 | for row in res:
181 | record=[]
182 | for col in response['cols']:
183 | record.append(row[col])
184 | response['rows'].append(record)
185 | pass
186 |
187 |
188 | def _parse_cat_plain(res,response):
189 | lines = res.split('\n')
190 | head = ' '.join(lines[0].split())
191 | response['cols'] = head.split()
192 | for line in lines[1:]:
193 | if len(line) <= 0:
194 | continue
195 | row = ' '.join(line.split())
196 | response['rows'].append(row.split())
197 | pass
198 |
199 |
200 | def response_cat(res,took):
201 | response = {}
202 | response['cols'] = []
203 | response['rows'] = []
204 |
205 | if type(res) == str:
206 | _parse_cat_plain(res,response)
207 | else:
208 | _parse_cat_json(res,response)
209 |
210 | response['total'] = len(response['rows'])
211 | response['took'] = took
212 | return response
213 |
214 |
215 |
216 | def response_mappings(res,took):
217 |
218 | response = {}
219 | response['cols'] = ['index','doc_type','col_name','data_type','properties']
220 | response['rows'] = []
221 |
222 | for _index in res.keys():
223 | index = res[_index]
224 | if 'mappings' in index.keys():
225 | mappings = index['mappings']
226 | for _doc_type in mappings.keys():
227 | doc_type = mappings[_doc_type]
228 | if 'properties' in doc_type.keys():
229 | properties = doc_type['properties']
230 | for _field in properties.keys():
231 | _type = 'object'
232 | _properties = None
233 | field = properties[_field]
234 | if 'type' in field.keys():
235 | _type = field['type']
236 | if 'properties' in field.keys():
237 | _properties = field['properties']
238 | response['rows'].append([_index,_doc_type,_field,_type,_properties])
239 | response['total'] = len(response['rows'])
240 | response['took'] = took
241 | return response
242 |
243 |
244 | def response_bulk(res):
245 | response = {}
246 | response['cols'] = []
247 | response['rows'] = []
248 | response['total'] = 0
249 | response['took'] = 0
250 | if 'took' in res.keys():
251 | response['took'] = res['took']
252 | if 'items' in res.keys():
253 | response['total'] = len(res['items'])
254 | return response
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/ql/utest.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Dec 23, 2016
3 |
4 | @author: qs
5 | '''
6 | # -*- coding: utf-8 -*-
7 |
8 |
9 |
10 |
11 | from ql.parse import lexer
12 | from ql.parse import parser
13 | from ply.lex import lex
14 | from ply.yacc import yacc
15 | from ql.parse.parser import TK
16 |
17 | from ql.dsl.Explain import Explain
18 | from ql.dsl.Insert import Insert,Bulk
19 | from ql.dsl.Update import Update,Upsert
20 | from ql.dsl.Delete import Delete
21 | from ql.dsl.Query import Query
22 | from ql.dsl.Response import response_hits
23 | from ql.dsl.Create import Create
24 | from ql.dsl.Describe import Describe
25 | import sys
26 | import json
27 | from elasticsearch import Elasticsearch
28 |
29 |
30 |
31 | def exec_query(stmt):
32 |
33 | my_lexer=lex(module=lexer,optimize=True,debug=True)
34 |
35 | my_parser=yacc(debug=True,module=parser)
36 |
37 | val = my_parser.parse(lexer=my_lexer.clone(),debug=False,input=sql)
38 |
39 | es = Elasticsearch([{'host':"10.68.23.81","port":9200}])
40 |
41 |
42 | val.debug()
43 |
44 | if val.get_type() == TK.TOK_QUERY:
45 |
46 | query = Query(val)
47 |
48 | print(query.dsl())
49 |
50 | print(query._index,query._type)
51 |
52 | if hasattr(query, 'route'):
53 | res = es.search(index=query._index, doc_type = query._type, body=query.dsl(),routing=query.route, request_timeout=100)
54 | else:
55 | res = es.search(index=query._index, doc_type = query._type, body=query.dsl(), request_timeout=100)
56 |
57 | mappings = es.indices.get_mapping(index=query._index, doc_type = query._type)
58 |
59 | selecols = query.dsl()['_source']
60 |
61 | stmt_res = None
62 |
63 | stmt_res = response_hits(res,mappings,selecols)
64 |
65 | print(json.dumps(stmt_res,indent=4))
66 |
67 | elif val.get_type() == TK.TOK_CREATE_TABLE:
68 |
69 | stmt = Create(val)
70 |
71 | res = es.indices.create(index=stmt._index,body = stmt._options,request_timeout=100,ignore= 400)
72 |
73 | res = es.indices.put_mapping(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), request_timeout=100)
74 |
75 | print(json.dumps(res,indent=4))
76 |
77 | elif val.get_type() == TK.TOK_INSERT_INTO:
78 |
79 | # val.debug()
80 |
81 | stmt = Insert(val)
82 |
83 | parms = stmt.metas
84 |
85 | res = es.index(index = stmt._index,doc_type = stmt._type, body = stmt.dsl(),**parms)
86 |
87 | print(json.dumps(res,indent=4))
88 |
89 | elif val.get_type() == TK.TOK_BULK_INTO:
90 |
91 | # val.debug()
92 |
93 |
94 | stmt = Bulk(val)
95 |
96 | res = es.bulk(index = stmt._index,doc_type = stmt._type, body = stmt.dsl())
97 |
98 | print(json.dumps(res,indent=4))
99 |
100 |
101 | elif val.get_type() == TK.TOK_UPDATE:
102 |
103 | val.debug()
104 |
105 | stmt = Update(val)
106 |
107 | print(json.dumps(stmt.dsl(),indent=4))
108 |
109 | res = es.update(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), **stmt.conditions)
110 |
111 |
112 | print(json.dumps(res,indent=4))
113 |
114 |
115 | elif val.get_type() == TK.TOK_UPSERT_INTO:
116 |
117 | val.debug()
118 |
119 | stmt = Upsert(val)
120 |
121 | print(json.dumps(stmt.dsl(),indent=4))
122 |
123 | res = es.update(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), **stmt.conditions)
124 |
125 |
126 | print(json.dumps(res,indent=4))
127 |
128 |
129 | elif val.get_type() == TK.TOK_DELETE:
130 |
131 | val.debug()
132 |
133 | stmt = Delete(val)
134 |
135 | res = es.delete_by_query(index = stmt._index, doc_type = stmt._type, body = stmt.dsl())
136 | # res = es.delete(index = stmt._index, doc_type = stmt._type, **stmt.conditions,ignore= 404)
137 |
138 | print(json.dumps(res,indent=4))
139 |
140 |
141 | elif val.get_type() == TK.TOK_EXPLAIN:
142 | stmt = Explain(val)
143 | print(stmt.curl_str)
144 | print(json.dumps(stmt.dsl(),indent=4))
145 |
146 | elif val.get_type() == TK.TOK_DESC_TABLE:
147 |
148 | stmt = Describe(val)
149 |
150 |
151 | res = es.indices.get_mapping(index = stmt._index,doc_type=stmt._type)
152 |
153 | print(res)
154 |
155 |
156 | else:
157 | res = es.cat.indices(index = 'qs_test*', v=True)
158 | val.debug()
159 | print(res)
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | if __name__ == "__main__":
168 |
169 | if len(sys.argv) < 2:
170 | sqls = [
171 |
172 | # '''create table qs_test03.ccx (
173 | # name string (analyzer = ik),
174 | # timestamp date,
175 | # age long
176 | # ) with option (
177 | # index.number_of_shards=10,
178 | # index.number_of_replicas = 1,
179 | # index.flush_inteval='10s'
180 | # )''',
181 | # '''show tables''',
182 | # '''desc flow_i'''
183 | #
184 | # '''create table my_tb.ccx (
185 | # a string (index=no),
186 | # c object as (
187 | # raw string (index=not_analyzed,doc_values=false),
188 | # obj object as (
189 | # ddd string (index=no)
190 | # )
191 | # )
192 | # ) with meta (
193 | # _parent (type='people'),
194 | # _source (includes = [a,'*c'])
195 | # ) with option (
196 | # index.number_of_shards=10,
197 | # index.number_of_replicas = 1,
198 | # index.flush_inteval='10s'
199 | # );''',
200 |
201 | # '''select * from _all''',
202 |
203 | # '''select count(*) as c,count(*) as cc ,sum(dd) as dd,moving_avg({buckets_path=c,window=30,model=simple}), moving_avg({buckets_path=dd,window=30,model=simple})
204 | # from my_index02
205 | # group by name,date_histogram({field=ts,interval='1h'});''',
206 | #
207 | # '''select count(*) from my_index02 group by date_range({field=ts,ranges=[{to='now-10M/M',from=now},{to='now',from='now-10M/M'}]});''',
208 | #
209 | # '''insert into my_index.base (_id,_routing,name,age,address,message) values (200,200,'zhangsan',24,{address='zhejiang',postCode='330010'},['sms001','sms002'])''',
210 | # #
211 | # '''bulk into my_index_occ.base(_id,name,age,address,message) values
212 | # (1,'zhangsan',24,{address='zhejiang',postCode='330010'},['sms:001','sms:002']),
213 | # (2,'zhangsan',25,{address='zhejiang',postCode='330010'},['sms:001','sms:002'])''',
214 | #
215 | #
216 | # '''update my_index_occ.base set name = 'lisi' ,age = 30,address={address='shanghai',postCode='3300100009'} where _id = 1''',
217 | #
218 | # '''upsert my_index_occ.base set name1 = 'lisi' ,age1 = 30,address1={address='shanghai',postCode='3300100009'} where _id = 1''',
219 | #
220 | # '''delete from test_ts where 1 = 1'''
221 | #
222 | #
223 | # '''explain select count(*) as c,count(*) as cc ,sum(dd) as dd,moving_avg({buckets_path=c,window=30,model=simple}), moving_avg({buckets_path=dd,window=30,model=simple})
224 | # from my_index02
225 | # group by name,date_histogram({field=ts,interval='1h'});''',
226 | #
227 | # '''select * from "config_log-'23'".base where app_name in ("login",'policy') and app_id > 1001 and app_ii = "2001"''',
228 | '''select * from qs_001@'3301' ''',
229 |
230 | ]
231 |
232 | for sql in sqls:
233 | print(sql)
234 | exec_query(sql)
235 |
236 | else:
237 | sql = sys.argv[1]
238 | exec_query(sql)
239 |
240 |
241 |
--------------------------------------------------------------------------------
/head/lang/ja_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | // "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs": "Aggregations ロード中...",
4 | "General.Searching": "検索中...",
5 | "General.Search": "Search",
6 | "General.Help": "ヘルプ",
7 | // "General.HelpGlyph": "?",
8 | // "General.CloseGlyph": "X",
9 | "General.RefreshResults": "リフレッシュ",
10 | "General.ManualRefresh": "マニュアルモード",
11 | "General.RefreshQuickly": "クイックモード",
12 | "General.Refresh5seconds": "5秒毎にリフレッシュ",
13 | "General.Refresh1minute": "1分毎にリフレッシュ",
14 | "AliasForm.AliasName": "エイリアス名",
15 | "AliasForm.NewAliasForIndex": "{0} の新しいエイリアス",
16 | "AliasForm.DeleteAliasMessage": "インデックス ''{1}'' を削除するために ''{0}'' とタイプして下さい. この操作は undo できません.",
17 | "AnyRequest.DisplayOptions" : "表示オプション",
18 | "AnyRequest.AsGraph" : "グラフの表示",
19 | "AnyRequest.AsJson" : "生の JSON を表示",
20 | "AnyRequest.AsTable" : "テーブルの表示",
21 | "AnyRequest.History" : "履歴",
22 | "AnyRequest.RepeatRequest" : "繰り返しリクエストを投げる",
23 | "AnyRequest.RepeatRequestSelect" : "次の間隔でリクエストを繰り返す",
24 | "AnyRequest.Transformer" : "Result Transformer",
25 | // "AnyRequest.Pretty": "Pretty",
26 | "AnyRequest.Query" : "Query",
27 | "AnyRequest.Request": "Request",
28 | "AnyRequest.Requesting": "検索中...",
29 | "AnyRequest.ValidateJSON": "Validate JSON",
30 | "Browser.Title": "Browser",
31 | "Browser.ResultSourcePanelTitle": "Result Source",
32 | "Command.DELETE": "DELETE",
33 | "Command.SHUTDOWN": "SHUTDOWN",
34 | "Command.DeleteAliasMessage": "エイリアスを削除しますか?",
35 | "ClusterOverView.IndexName": "Index名",
36 | "ClusterOverview.NumShards": "Number of Shards",
37 | "ClusterOverview.NumReplicas": "Number of Replicas",
38 | "ClusterOverview.NewIndex": "インデックスの作成",
39 | // "IndexActionsMenu.Title": "Actions",
40 | "IndexActionsMenu.NewAlias": "新しいエイリアス...",
41 | "IndexActionsMenu.Refresh": "Refresh",
42 | "IndexActionsMenu.Flush": "Flush",
43 | "IndexActionsMenu.Optimize": "Optimize...",
44 | "IndexActionsMenu.Snapshot": "Gateway Snapshot",
45 | "IndexActionsMenu.Analyser": "Analyserテスト",
46 | // "IndexActionsMenu.Open": "Open",
47 | // "IndexActionsMenu.Close": "Close",
48 | // "IndexActionsMenu.Delete": "Delete...",
49 | // "IndexInfoMenu.Title": "Info",
50 | // "IndexInfoMenu.Status": "Index Status",
51 | // "IndexInfoMenu.Metadata": "Index Metadata",
52 | "IndexCommand.TextToAnalyze": "Analyse するテキストを入力",
53 | "IndexCommand.ShutdownMessage": " {1} をシャットダウンするために ''{0}'' と入力して下さい. このインターフェースからはリスタートはできません.",
54 | "IndexOverview.PageTitle": "インデックスのOverview",
55 | // "IndexSelector.NameWithDocs": "{0} ({1} docs)",
56 | "IndexSelector.SearchIndexForDocs": "Search {0} for documents where:",
57 | "FilterBrowser.OutputType": "結果の出力形式: {0} ",
58 | "FilterBrowser.OutputSize": "結果の取得サイズ: {0} ",
59 | "Header.ClusterHealth": "cluster health: {0} ({1} of {2})",
60 | "Header.ClusterNotConnected": "cluster health: not connected",
61 | "Header.Connect": "接続",
62 | "Nav.AnyRequest": "Any Request",
63 | "Nav.Browser": "Browser",
64 | "Nav.ClusterHealth": "Cluster Health",
65 | "Nav.ClusterState": "Cluster State",
66 | "Nav.ClusterNodes": "Nodes Info",
67 | // "Nav.Info": "Info",
68 | "Nav.NodeStats": "Nodes Stats",
69 | "Nav.Overview": "Overview",
70 | "Nav.Indices": "Indices",
71 | "Nav.Plugins": "Plugins",
72 | "Nav.Status": "Indices Stats",
73 | "Nav.Templates": "Templates",
74 | "Nav.StructuredQuery": "Structured Query",
75 | // "NodeActionsMenu.Title": "Actions",
76 | "NodeActionsMenu.Shutdown": "シャットダウン...",
77 | // "NodeInfoMenu.Title": "Info",
78 | "NodeInfoMenu.ClusterNodeInfo": "Cluster Node Info",
79 | // "NodeInfoMenu.NodeStats": "Node Stats",
80 | "NodeType.Client": "Client Node",
81 | "NodeType.Coord": "Coordinator",
82 | "NodeType.Master": "Master Node",
83 | "NodeType.Tribe": "Tribe Node",
84 | "NodeType.Worker": "Worker Node",
85 | "NodeType.Unassigned": "Unassigned",
86 | "OptimizeForm.OptimizeIndex": "Optimize {0}",
87 | "OptimizeForm.MaxSegments": "Maximum # Of Segments",
88 | "OptimizeForm.ExpungeDeletes": "Only Expunge Deletes",
89 | "OptimizeForm.FlushAfter": "Flush After Optimize",
90 | "OptimizeForm.WaitForMerge": "Wait For Merge",
91 | "Overview.PageTitle" : "クラスタのOverview",
92 | // "Output.JSON": "JSON",
93 | "Output.Table": "表",
94 | // "Output.CSV": "CSV",
95 | "Output.ShowSource": "Query の source を表示",
96 | "Preference.SortCluster": "ノードのソート",
97 | "Sort.ByName": "名前順",
98 | "Sort.ByAddress": "アドレス順",
99 | "Sort.ByType": "タイプ順",
100 | "Preference.SortIndices": "インデックスのソート",
101 | "SortIndices.Descending": "降順(desc)",
102 | "SortIndices.Ascending": "昇順(asc)",
103 | "Preference.ViewAliases": "エイリアスの表示方法",
104 | "ViewAliases.Grouped": "標準",
105 | "ViewAliases.List": "リスト形式",
106 | "ViewAliases.None": "表示しない",
107 | "Overview.IndexFilter": "インデックスの絞り込み",
108 | "TableResults.Summary": "検索結果: {0} / {1} シャード. {2} ヒット. {3} 秒",
109 | "QueryFilter.AllIndices": "全インデックス",
110 | "QueryFilter.AnyValue": "any",
111 | "QueryFilter-Header-Indices": "Indices",
112 | // "QueryFilter-Header-Types": "Types",
113 | "QueryFilter-Header-Fields": "Fields",
114 | "QueryFilter.DateRangeHint.from": "From : {0}",
115 | "QueryFilter.DateRangeHint.to": " To : {0}",
116 | "Query.FailAndUndo": "Query Failed. Undoing last changes",
117 | "StructuredQuery.ShowRawJson": "生の JSON を表示する"
118 | });
119 |
120 | i18n.setKeys({
121 | "AnyRequest.TransformerHelp" : "\
122 | Result Transformer は、ESから返ってきた JSON をより使いやすい形式に変換することができます.
\
123 | transformer には javascript の function の中身を記述します. 戻り値の新しい JSON が画面出力されます.
\
124 | 例:
\
125 | return root.hits.hits[0]; 検索結果の最初のドキュメントだけを表示するように JSON をトラバースする例
\
126 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0); クラスタ全体でのトータル使用メモリを返す例
\
127 | 以下の関数は、配列やオブジェクトを扱うのに便利です
\
128 |
\
129 | - Object.keys(object) := array
\
130 | - array.forEach(function(prop, index))
\
131 | - array.map(function(prop, index)) := array
\
132 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
133 |
\
134 | 繰り返しリクエストを投げた時, prev 引数に前の戻り値が入ります. 比較や、累積グラフの作成などに利用できます.
\
135 | 例:
\
136 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la; 最初のノードの load_average を配列で返します.\
137 | この配列をグラフの入力値に用いることで load_average の遷移をグラフとして視覚化することができます.\
138 | "
139 | });
140 |
141 | i18n.setKeys({
142 | "AnyRequest.DisplayOptionsHelp" : "\
143 |
生の JSON の表示: 検索結果を生の JSON で表示します
\
144 | グラフの表示: 検索結果をグラフで表示します. Result Transformer を使って、配列の値に変換する必要があります
\
145 | 表の表示: 検索クエリの場合には、結果を表形式で表示できます
\
146 | "
147 | });
148 |
149 | //i18n.setKeys({
150 | // "QueryFilter.DateRangeHelp" : "\
151 | // Date fields accept a natural language query to produce a From and To date that form a range that the results are queried over.
\
152 | // The following formats are supported:
\
153 | // \
154 | // - Keywords / Key Phrases
\
155 | // now
today
tomorrow
yesterday
last / this / next + week / month / year
\
156 | // searches for dates matching the keyword. last year would search all of last year. \
157 | // - Ranges
\
158 | // 1000 secs
5mins
1day
2days
80d
9 months
2yrs (spaces optional, many synonyms for range qualifiers)
\
159 | // Create a search range centered on now extending into the past and future by the amount specified. \
160 | // - DateTime and Partial DateTime
\
161 | // 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
162 | // these formats specify a specific date range. 2011 would search the whole of 2011, while 2011-01-18 12:32:45 would only search for results in that 1 second range \
163 | // - Time and Time Partials
\
164 | // 12
12:32
12:32:45
\
165 | // these formats search for a particular time during the current day. 12:32 would search that minute during today \
166 | // - Date Ranges
\
167 | // 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
168 | // A Date Range is created by specifying two dates in any format (Keyword / DateTime / Time) separated by < or -> (both do the same thing). If either end of the date range is missing, it is the same as having no constraint in that direction. \
169 | // - Date Range using Offset
\
170 | // 2010 -> 1yr
3mins < now\
171 | // Searches the specified date including the range in the direction specified. \
172 | // - Anchored Ranges
\
173 | // 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
174 | // Similar to above except the range is extend in both directions from the anchor date \
175 | //
\
176 | // "
177 | //});
178 |
--------------------------------------------------------------------------------
/head/lang/en_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs": "Loading Aggregations...",
4 | "General.Searching": "Searching...",
5 | "General.Search": "Search",
6 | "General.Help": "Help",
7 | "General.HelpGlyph": "?",
8 | "General.CloseGlyph": "X",
9 | "General.RefreshResults": "Refresh",
10 | "General.ManualRefresh": "Manual Refresh",
11 | "General.RefreshQuickly": "Refresh quickly",
12 | "General.Refresh5seconds": "Refresh every 5 seconds",
13 | "General.Refresh1minute": "Refresh every minute",
14 | "AliasForm.AliasName": "Alias Name",
15 | "AliasForm.NewAliasForIndex": "New Alias for {0}",
16 | "AliasForm.DeleteAliasMessage": "type ''{0}'' to delete {1}. There is no undo",
17 | "AnyRequest.DisplayOptions" : "Display Options",
18 | "AnyRequest.AsGraph" : "Graph Results",
19 | "AnyRequest.AsJson" : "Show Raw JSON",
20 | "AnyRequest.AsTable" : "Show Search Results Table",
21 | "AnyRequest.History" : "History",
22 | "AnyRequest.RepeatRequest" : "Repeat Request",
23 | "AnyRequest.RepeatRequestSelect" : "Repeat request every ",
24 | "AnyRequest.Transformer" : "Result Transformer",
25 | "AnyRequest.Pretty": "Pretty",
26 | "AnyRequest.Query" : "Query",
27 | "AnyRequest.Request": "Request",
28 | "AnyRequest.Requesting": "Requesting...",
29 | "AnyRequest.ValidateJSON": "Validate JSON",
30 | "Browser.Title": "Browser",
31 | "Browser.ResultSourcePanelTitle": "Result Source",
32 | "Command.DELETE": "DELETE",
33 | "Command.SHUTDOWN": "SHUTDOWN",
34 | "Command.DeleteAliasMessage": "Delete Alias?",
35 | "ClusterOverView.IndexName": "Index Name",
36 | "ClusterOverview.NumShards": "Number of Shards",
37 | "ClusterOverview.NumReplicas": "Number of Replicas",
38 | "ClusterOverview.NewIndex": "New Index",
39 | "IndexActionsMenu.Title": "Actions",
40 | "IndexActionsMenu.NewAlias": "New Alias...",
41 | "IndexActionsMenu.Refresh": "Refresh",
42 | "IndexActionsMenu.Flush": "Flush",
43 | "IndexActionsMenu.Optimize": "Optimize...",
44 | "IndexActionsMenu.Snapshot": "Gateway Snapshot",
45 | "IndexActionsMenu.Analyser": "Test Analyser",
46 | "IndexActionsMenu.Open": "Open",
47 | "IndexActionsMenu.Close": "Close",
48 | "IndexActionsMenu.Delete": "Delete...",
49 | "IndexInfoMenu.Title": "Info",
50 | "IndexInfoMenu.Status": "Index Status",
51 | "IndexInfoMenu.Metadata": "Index Metadata",
52 | "IndexCommand.TextToAnalyze": "Text to Analyse",
53 | "IndexCommand.ShutdownMessage": "type ''{0}'' to shutdown {1}. Node can NOT be restarted from this interface",
54 | "IndexOverview.PageTitle": "Indices Overview",
55 | "IndexSelector.NameWithDocs": "{0} ({1} docs)",
56 | "IndexSelector.SearchIndexForDocs": "Search {0} for documents where:",
57 | "FilterBrowser.OutputType": "Output Results: {0}",
58 | "FilterBrowser.OutputSize": "Number of Results: {0}",
59 | "Header.ClusterHealth": "cluster health: {0} ({1} of {2})",
60 | "Header.ClusterNotConnected": "cluster health: not connected",
61 | "Header.Connect": "Connect",
62 | "Nav.AnyRequest": "Any Request",
63 | "Nav.Browser": "Browser",
64 | "Nav.ClusterHealth": "Cluster Health",
65 | "Nav.ClusterState": "Cluster State",
66 | "Nav.ClusterNodes": "Nodes Info",
67 | "Nav.Info": "Info",
68 | "Nav.NodeStats": "Nodes Stats",
69 | "Nav.Overview": "Overview",
70 | "Nav.Indices": "Indices",
71 | "Nav.Plugins": "Plugins",
72 | "Nav.Status": "Indices Stats",
73 | "Nav.Templates": "Templates",
74 | "Nav.StructuredQuery": "Structured Query",
75 | "NodeActionsMenu.Title": "Actions",
76 | "NodeActionsMenu.Shutdown": "Shutdown...",
77 | "NodeInfoMenu.Title": "Info",
78 | "NodeInfoMenu.ClusterNodeInfo": "Cluster Node Info",
79 | "NodeInfoMenu.NodeStats": "Node Stats",
80 | "NodeType.Client": "Client Node",
81 | "NodeType.Coord": "Coordinator",
82 | "NodeType.Master": "Master Node",
83 | "NodeType.Tribe": "Tribe Node",
84 | "NodeType.Worker": "Worker Node",
85 | "NodeType.Unassigned": "Unassigned",
86 | "OptimizeForm.OptimizeIndex": "Optimize {0}",
87 | "OptimizeForm.MaxSegments": "Maximum # Of Segments",
88 | "OptimizeForm.ExpungeDeletes": "Only Expunge Deletes",
89 | "OptimizeForm.FlushAfter": "Flush After Optimize",
90 | "OptimizeForm.WaitForMerge": "Wait For Merge",
91 | "Overview.PageTitle" : "Cluster Overview",
92 | "Output.JSON": "JSON",
93 | "Output.Table": "Table",
94 | "Output.CSV": "CSV",
95 | "Output.ShowSource": "Show query source",
96 | "Preference.SortCluster": "Sort Cluster",
97 | "Sort.ByName": "By Name",
98 | "Sort.ByAddress": "By Address",
99 | "Sort.ByType": "By Type",
100 | "Preference.SortIndices": "Sort Indices",
101 | "SortIndices.Descending": "Descending",
102 | "SortIndices.Ascending": "Ascending",
103 | "Preference.ViewAliases": "View Aliases",
104 | "ViewAliases.Grouped": "Grouped",
105 | "ViewAliases.List": "List",
106 | "ViewAliases.None": "None",
107 | "Overview.IndexFilter": "Index Filter",
108 | "TableResults.Summary": "Searched {0} of {1} shards. {2} hits. {3} seconds",
109 | "QueryFilter.AllIndices": "All Indices",
110 | "QueryFilter.AnyValue": "any",
111 | "QueryFilter-Header-Indices": "Indices",
112 | "QueryFilter-Header-Types": "Types",
113 | "QueryFilter-Header-Fields": "Fields",
114 | "QueryFilter.DateRangeHint.from": "From : {0}",
115 | "QueryFilter.DateRangeHint.to": " To : {0}",
116 | "Query.FailAndUndo": "Query Failed. Undoing last changes",
117 | "StructuredQuery.ShowRawJson": "Show Raw JSON"
118 | });
119 |
120 | i18n.setKeys({
121 | "AnyRequest.TransformerHelp" : "\
122 | The Result Transformer can be used to post process the raw json results from a request into a more useful format.
\
123 | The transformer should contain the body of a javascript function. The return value from the function becomes the new value passed to the json printer
\
124 | Example:
\
125 | return root.hits.hits[0]; would traverse a result set to show just the first match
\
126 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0); would return the total memory used across an entire cluster
\
127 | The following functions are available and can be useful processing arrays and objects
\
128 |
\
129 | - Object.keys(object) := array
\
130 | - array.forEach(function(prop, index))
\
131 | - array.map(function(prop, index)) := array
\
132 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
133 |
\
134 | When Repeat Request is running, an extra parameter called prev is passed to the transformation function. This allows comparisons, and cumulative graphing
\
135 | Example:
\
136 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la; would return the load average on the first cluster node over the last minute\
137 | This could be fed into the Graph to produce a load graph for the node\
138 | "
139 | });
140 |
141 | i18n.setKeys({
142 | "AnyRequest.DisplayOptionsHelp" : "\
143 |
Raw Json: shows complete results of the query and transformation in raw JSON format
\
144 | Graph Results: To produce a graph of your results, use the result transformer to produce an array of values
\
145 | Search Results Table: If your query is a search, you can display the results of the search in a table.
\
146 | "
147 | });
148 |
149 | i18n.setKeys({
150 | "QueryFilter.DateRangeHelp" : "\
151 | Date fields accept a natural language query to produce a From and To date that form a range that the results are queried over.
\
152 | The following formats are supported:
\
153 | \
154 | - Keywords / Key Phrases
\
155 | now
today
tomorrow
yesterday
last / this / next + week / month / year
\
156 | searches for dates matching the keyword. last year would search all of last year. \
157 | - Ranges
\
158 | 1000 secs
5mins
1day
2days
80d
9 months
2yrs (spaces optional, many synonyms for range qualifiers)
\
159 | Create a search range centered on now extending into the past and future by the amount specified. \
160 | - DateTime and Partial DateTime
\
161 | 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
162 | these formats specify a specific date range. 2011 would search the whole of 2011, while 2011-01-18 12:32:45 would only search for results in that 1 second range \
163 | - Time and Time Partials
\
164 | 12
12:32
12:32:45
\
165 | these formats search for a particular time during the current day. 12:32 would search that minute during today \
166 | - Date Ranges
\
167 | 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
168 | A Date Range is created by specifying two dates in any format (Keyword / DateTime / Time) separated by < or -> (both do the same thing). If either end of the date range is missing, it is the same as having no constraint in that direction. \
169 | - Date Range using Offset
\
170 | 2010 -> 1yr
3mins < now\
171 | Searches the specified date including the range in the direction specified. \
172 | - Anchored Ranges
\
173 | 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
174 | Similar to above except the range is extend in both directions from the anchor date \
175 |
\
176 | "
177 | });
178 |
--------------------------------------------------------------------------------
/head/lang/fr_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | // "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs" : "Chargement des facettes...",
4 | "General.Searching": "Recherche en cours...",
5 | "General.Search": "Recherche",
6 | "General.Help": "Aide",
7 | // "General.HelpGlyph": "?",
8 | // "General.CloseGlyph": "X",
9 | "General.RefreshResults": "Rafraîchir",
10 | "General.ManualRefresh": "Rafraîchissement manuel",
11 | "General.RefreshQuickly": "Rafraîchissement rapide",
12 | "General.Refresh5seconds": "Rafraîchissement toutes les 5 secondes",
13 | "General.Refresh1minute": "Rafraîchissement toutes les minutes",
14 | "AliasForm.AliasName": "Alias",
15 | "AliasForm.NewAliasForIndex": "Nouvel Alias pour {0}",
16 | "AliasForm.DeleteAliasMessage": "Entrez ''{0}'' pour effacer {1}. Attention, action irréversible.",
17 | "AnyRequest.DisplayOptions" : "Options d'affichage",
18 | "AnyRequest.AsGraph" : "En graphe",
19 | "AnyRequest.AsJson" : "En JSON brut",
20 | "AnyRequest.AsTable" : "En tableau",
21 | "AnyRequest.History" : "Historique",
22 | "AnyRequest.RepeatRequest" : "Répétition automatique de la requête",
23 | "AnyRequest.RepeatRequestSelect" : "Répéter la requête toutes les ",
24 | "AnyRequest.Transformer" : "Transformation des résultats",
25 | // "AnyRequest.Pretty": "Pretty",
26 | "AnyRequest.Query" : "Recherche",
27 | "AnyRequest.Request": "Requête",
28 | "AnyRequest.Requesting": "Requête en cours...",
29 | "AnyRequest.ValidateJSON": "Valider le JSON",
30 | "Browser.Title": "Navigateur",
31 | "Browser.ResultSourcePanelTitle": "Résultat au format JSON",
32 | "Command.DELETE": "SUPPRIMER",
33 | "Command.SHUTDOWN": "ETEINDRE",
34 | "Command.DeleteAliasMessage": "Supprimer l'Alias?",
35 | "ClusterOverView.IndexName": "Index",
36 | "ClusterOverview.NumShards": "Nombre de shards",
37 | "ClusterOverview.NumReplicas": "Nombre de replica",
38 | "ClusterOverview.NewIndex": "Nouvel Index",
39 | // "IndexActionsMenu.Title": "Actions",
40 | "IndexActionsMenu.NewAlias": "Nouvel Alias...",
41 | "IndexActionsMenu.Refresh": "Rafraîchir",
42 | "IndexActionsMenu.Flush": "Flusher",
43 | "IndexActionsMenu.Optimize": "Optimiser...",
44 | "IndexActionsMenu.Snapshot": "Dupliquer l'index (Snapshot)",
45 | "IndexActionsMenu.Analyser": "Tester un analyseur",
46 | "IndexActionsMenu.Open": "Ouvrir",
47 | "IndexActionsMenu.Close": "Fermer",
48 | "IndexActionsMenu.Delete": "Effacer...",
49 | // "IndexInfoMenu.Title": "Info",
50 | "IndexInfoMenu.Status": "Etat de l'Index",
51 | "IndexInfoMenu.Metadata": "Métadonnées de l'Index",
52 | "IndexCommand.TextToAnalyze": "Texte à analyser",
53 | "IndexCommand.ShutdownMessage": "Entrez ''{0}'' pour éteindre {1}. Le noeud NE PEUT PAS être redémarré depuis cette interface.",
54 | // "IndexSelector.NameWithDocs": "{0} ({1} docs)",
55 | "IndexSelector.SearchIndexForDocs": "Chercher dans {0} les documents correspondant à",
56 | "FilterBrowser.OutputType": "Format d'affichage des résultats {0}",
57 | "FilterBrowser.OutputSize": "Nombre de Résultats: {0}",
58 | "Header.ClusterHealth": "Santé du cluster: {0} ({1} {2})",
59 | "Header.ClusterNotConnected": "Santé du cluster: non connecté",
60 | "Header.Connect": "Se connecter",
61 | "Nav.AnyRequest": "Autres requêtes",
62 | "Nav.StructuredQuery": "Requêtes structurées",
63 | "Nav.Browser": "Navigateur",
64 | "Nav.ClusterHealth": "Santé du cluster",
65 | "Nav.ClusterState": "Etat du cluster",
66 | "Nav.ClusterNodes": "Noeuds du cluster",
67 | // "Nav.Info": "Info",
68 | "Nav.NodeStats": "Statistiques sur les noeuds",
69 | "Nav.Overview": "Aperçu",
70 | "Nav.Indices": "Index",
71 | "Nav.Plugins": "Plugins",
72 | "Nav.Status": "Etat",
73 | "Nav.Templates": "Templates",
74 | "Nav.StructuredQuery": "Recherche Structurée",
75 | // "NodeActionsMenu.Title": "Actions",
76 | "NodeActionsMenu.Shutdown": "Eteindre...",
77 | // "NodeInfoMenu.Title": "Info",
78 | "NodeInfoMenu.ClusterNodeInfo": "Infos sur le noeud du cluster",
79 | "NodeInfoMenu.NodeStats": "Statistiques du noeud",
80 | "NodeType.Client": "Noeud Client",
81 | "NodeType.Coord": "Coordinateur",
82 | "NodeType.Master": "Noeud Master",
83 | "NodeType.Tribe": "Noeud Tribe",
84 | "NodeType.Worker": "Noeud Worker",
85 | "NodeType.Unassigned": "Non assigné",
86 | "OptimizeForm.OptimizeIndex": "Optimiser {0}",
87 | "OptimizeForm.MaxSegments": "Nombre maximum de segments",
88 | "OptimizeForm.ExpungeDeletes": "Seulement purger les suppressions",
89 | "OptimizeForm.FlushAfter": "Flusher après l'optimisation",
90 | "OptimizeForm.WaitForMerge": "Attendre la fin de la fusion",
91 | "Overview.PageTitle" : "Aperçu du cluster",
92 | // "Output.JSON": "JSON",
93 | "Output.Table": "Tableau",
94 | "Output.ShowSource": "Voir la requête source",
95 | "TableResults.Summary": "Recherche sur {0} des {1} shards. {2} résultats. {3} secondes",
96 | "QueryFilter.AllIndices": "Tous les index",
97 | "QueryFilter.AnyValue": "Tout",
98 | "QueryFilter-Header-Indices": "Index",
99 | // "QueryFilter-Header-Types": "Types",
100 | "QueryFilter-Header-Fields": "Champs",
101 | "QueryFilter.DateRangeHint.from": "De : {0}",
102 | "QueryFilter.DateRangeHint.to": " A : {0}",
103 | "Query.FailAndUndo": "Requête en échec. Annulation des dernières modifications.",
104 | "StructuredQuery.ShowRawJson": "Voir le JSON brut"
105 | });
106 |
107 | i18n.setKeys({
108 | "AnyRequest.TransformerHelp" : "\
109 | Le transformateur de résultats peut être utilisé pour modifier a posteriori les résultats JSON bruts dans un format plus utile.
\
110 | Le transformateur devrait contenir le corps d'une fonction javascript. La valeur de retour de la fonction devient la nouvelle valeur qui sera passée à l'afficheur des documents JSON.
\
111 | Exemple:
\
112 | return root.hits.hits[0]; ne renverra que le premier élément de l'ensemble des résultats.
\
113 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0); retournera la mémoire totale utilisée dans l'ensemble du cluster.
\
114 | Les fonctions suivantes sont disponibles et peuvent vous être utiles pour travailler sur les tableaux et les objets:
\
115 |
\
116 | - Object.keys(object) := array
\
117 | - array.forEach(function(prop, index))
\
118 | - array.map(function(prop, index)) := array
\
119 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
120 |
\
121 | Lorsque vous activez la répétition automatique de la requête, un paramètre supplémentaire nommé prev est passé à la fonction de transformation. Cela permet les comparaisons et les graphes cumulatifs.
\
122 | Exemple:
\
123 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la; retournera la charge moyenne du premier noeud du cluster pour la dernière minute écoulée.\
124 | Cela peut alimenter ensuite le graphe pour produire un graphe de charge du noeud.\
125 | "
126 | });
127 |
128 | i18n.setKeys({
129 | "AnyRequest.DisplayOptionsHelp" : "\
130 |
En JSON brut: affiche les résultats complets de la recherche éventuellement transformée au format JSON brut.
\
131 | En graphe: pour fabriquer un graphe de vos résultats, utilsez la transformation de résultats pour générer un tableau de valeurs.
\
132 | En tableau: si votre requête est une recherche, vous pouvez alors afficher les résultats dans un tableau.
\
133 | "
134 | });
135 |
136 | i18n.setKeys({
137 | "QueryFilter.DateRangeHelp" : "\
138 | Les champs Date acceptent une requête en langage naturel pour produire un écart de date (from/to) correspondant.
\
139 | Les formats suivants sont acceptés :
\
140 | \
141 | - Mots clés
\
142 | now
today
tomorrow
yesterday
last / this / next + week / month / year
\
143 | Cherchera pour des dates correspondant au mot clé. last year cherchera sur toute l'année précédente. \
144 | - Ecarts
\
145 | 1000 secs
5mins
1day
2days
80d
9 months
2yrs (les espaces sont optionnels et il existe beaucoup de synonymes pour qualifier les écarts)
\
146 | Créé un écart de date basé sur l'heure courante (maintenant) avec plus ou moins l'écart indiqué. \
147 | - Dates et Dates partielles
\
148 | 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
149 | Ces formats indiquent un écart de date spécifique. 2011 cherchera sur toute l'année 2011, alors que 2011-01-18 12:32:45 ne cherchera que pour la date précise à la seconde près. \
150 | - Heures et heures partielles
\
151 | 12
12:32
12:32:45
\
152 | Ces formats indiquent un espace de temps pour la date du jour. 12:32 cherchera les éléments d'aujourd'hui à cette minute précise. \
153 | - Ecart de Date
\
154 | 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
155 | Un écart de date est créé en spécifiant deux dates dans n'importe lequel des formats précédents (Mot clé / Dates / Heures) séparées par < ou -> (les deux produisent le même effet). Si la date de fin n'est pas indiquée, alors il n'y aura aucune contrainte de fin. \
156 | - Ecart de date avec décalage
\
157 | 2010 -> 1yr
3mins < now\
158 | Cherche en incluant un décalage de la date dans la direction indiquée. \
159 | - Ecart de date avec bornes
\
160 | 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
161 | Similaire à ci-dessus excepté que le décalage est appliqué dans les deux sens à partir de la date indiquée. \
162 |
\
163 | "
164 | });
165 |
--------------------------------------------------------------------------------
/head/lang/tr_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs": "Gruplar Yükleniyor...",
4 | "General.Searching": "Aranıyor...",
5 | "General.Search": "Ara",
6 | "General.Help": "Yardım",
7 | "General.HelpGlyph": "?",
8 | "General.CloseGlyph": "X",
9 | "General.RefreshResults": "Yenile",
10 | "General.ManualRefresh": "Manuel Yenileme",
11 | "General.RefreshQuickly": "Hızlı yenile",
12 | "General.Refresh5seconds": "5 saniyede bir yenile",
13 | "General.Refresh1minute": "Her dakika yenile",
14 | "AliasForm.AliasName": "Alternatif İsim",
15 | "AliasForm.NewAliasForIndex": "{0} için yeni alternatif isim",
16 | "AliasForm.DeleteAliasMessage": "{1} silmek için ''{0}'' . Geriye dönüş yoktur.",
17 | "AnyRequest.DisplayOptions" : "Seçenekleri Göster",
18 | "AnyRequest.AsGraph" : "Sonuçları Çizdir",
19 | "AnyRequest.AsJson" : "JSON formatında göster",
20 | "AnyRequest.AsTable" : "Arama sonuçlarını tablo halinde göster",
21 | "AnyRequest.History" : "Geçmiş",
22 | "AnyRequest.RepeatRequest" : "İsteği Tekrarla",
23 | "AnyRequest.RepeatRequestSelect" : "İsteği sürekli tekrarla ",
24 | "AnyRequest.Transformer" : "Sonuç Dönüştürücü",
25 | "AnyRequest.Pretty": "Düzenli",
26 | "AnyRequest.Query" : "Sorgu",
27 | "AnyRequest.Request": "Gönder",
28 | "AnyRequest.Requesting": "İsteniyor...",
29 | "AnyRequest.ValidateJSON": "JSON Doğrula",
30 | "Browser.Title": "Browser",
31 | "Browser.ResultSourcePanelTitle": "Sonuç Kaynağı",
32 | "Command.DELETE": "SİL",
33 | "Command.SHUTDOWN": "KAPA",
34 | "Command.DeleteAliasMessage": "Alternatif ismi sil?",
35 | "ClusterOverView.IndexName": "Indeks İsmi",
36 | "ClusterOverview.NumShards": "Sektör Sayısı",
37 | "ClusterOverview.NumReplicas": "Yedek Sayısı",
38 | "ClusterOverview.NewIndex": "Yeni Indeks",
39 | "IndexActionsMenu.Title": "İşlemler",
40 | "IndexActionsMenu.NewAlias": "Yeni Alternatif İsim...",
41 | "IndexActionsMenu.Refresh": "Yenile",
42 | "IndexActionsMenu.Flush": "Boşalt",
43 | "IndexActionsMenu.Optimize": "Optimize et...",
44 | "IndexActionsMenu.Snapshot": "Gateway Snapshot (Kopya Al)",
45 | "IndexActionsMenu.Analyser": "Analizi test et",
46 | "IndexActionsMenu.Open": "Aç",
47 | "IndexActionsMenu.Close": "Kapa",
48 | "IndexActionsMenu.Delete": "Sil...",
49 | "IndexInfoMenu.Title": "Bilgi",
50 | "IndexInfoMenu.Status": "Indeks Durumu",
51 | "IndexInfoMenu.Metadata": "Indeks Metaveri",
52 | "IndexCommand.TextToAnalyze": "Analiz edilecek metin",
53 | "IndexCommand.ShutdownMessage": "{1} kapatmak için ''{0}'' yazın . Nod bu arayüzden tekrar BAŞLATILAMAZ",
54 | "IndexOverview.PageTitle": "Indeksler Genel Bakış",
55 | "IndexSelector.NameWithDocs": "{0} ({1} döküman)",
56 | "IndexSelector.SearchIndexForDocs": "{0} indeksinde ara:",
57 | "FilterBrowser.OutputType": "Sonuç Formatı: {0}",
58 | "FilterBrowser.OutputSize": "Sonuç Sayısı: {0}",
59 | "Header.ClusterHealth": "Küme Durumu: {0} ({1} de {2})",
60 | "Header.ClusterNotConnected": "Küme Durumu: Bağlı Değil",
61 | "Header.Connect": "Bağlan",
62 | "Nav.AnyRequest": "Özel Sorgu",
63 | "Nav.Browser": "Görüntüle",
64 | "Nav.ClusterHealth": "Küme Durumu",
65 | "Nav.ClusterState": "Küme Statüsü",
66 | "Nav.ClusterNodes": "Nod Bilgileri",
67 | "Nav.Info": "Bilgi",
68 | "Nav.NodeStats": "Nod İstatistikleri",
69 | "Nav.Overview": "Genel Bakış",
70 | "Nav.Indices": "Indeksler",
71 | "Nav.Plugins": "Eklentiler",
72 | "Nav.Status": "Indeks İstatistikleri",
73 | "Nav.Templates": "Şablonlar",
74 | "Nav.StructuredQuery": "Yapılandırılmış Sorgu",
75 | "NodeActionsMenu.Title": "İşlemler",
76 | "NodeActionsMenu.Shutdown": "Kapat...",
77 | "NodeInfoMenu.Title": "Bilgi",
78 | "NodeInfoMenu.ClusterNodeInfo": "Küme Nod Bilgileri",
79 | "NodeInfoMenu.NodeStats": "Nod İstatistikleri",
80 | "NodeType.Client": "Client Nod",
81 | "NodeType.Coord": "Coordinator",
82 | "NodeType.Master": "Master Nod",
83 | "NodeType.Tribe": "Tribe Nod",
84 | "NodeType.Worker": "Worker Nod",
85 | "NodeType.Unassigned": "Sahipsiz",
86 | "OptimizeForm.OptimizeIndex": "{0} Optimize Et",
87 | "OptimizeForm.MaxSegments": "Maksimum Segment Sayısı",
88 | "OptimizeForm.ExpungeDeletes": "Silme İşlemi Artıklarını Temizle",
89 | "OptimizeForm.FlushAfter": "Optimize Ettikten Sonra Boşalt",
90 | "OptimizeForm.WaitForMerge": "Birleştirme İçin Bekle",
91 | "Overview.PageTitle" : "Kümeler Genelbakış",
92 | "Output.JSON": "JSON",
93 | "Output.Table": "Tablo",
94 | "Output.CSV": "CSV",
95 | "Output.ShowSource": "Sorgu kaynağını göster",
96 | "Preference.SortCluster": "Kümeyi Sırala",
97 | "Sort.ByName": "İsme göre",
98 | "Sort.ByAddress": "Adrese göre",
99 | "Sort.ByType": "Tipe göre",
100 | "Preference.SortIndices": "Indeksleri sırala",
101 | "SortIndices.Descending": "Azalan",
102 | "SortIndices.Ascending": "Artan",
103 | "Preference.ViewAliases": "Alternatif isimleri görüntüle",
104 | "ViewAliases.Grouped": "Gruplanmış",
105 | "ViewAliases.List": "Liste",
106 | "ViewAliases.None": "Karışık",
107 | "Overview.IndexFilter": "Indeks Filtresi",
108 | "TableResults.Summary": "{0} parçanın {1} tanesi arandı. {2} sonuç. {3} saniye",
109 | "QueryFilter.AllIndices": "Tüm Indeksler",
110 | "QueryFilter.AnyValue": "herhangi",
111 | "QueryFilter-Header-Indices": "Indeksler",
112 | "QueryFilter-Header-Types": "Tipler",
113 | "QueryFilter-Header-Fields": "Alanlar",
114 | "QueryFilter.DateRangeHint.from": "{0}'dan",
115 | "QueryFilter.DateRangeHint.to": " {0}'a",
116 | "Query.FailAndUndo": "Sorgu Başarısız. Son değişiklikler geri alınıyor.",
117 | "StructuredQuery.ShowRawJson": "Formatsız JSON göster"
118 | });
119 |
120 | i18n.setKeys({
121 | "AnyRequest.TransformerHelp" : "\
122 | Sonuç Dönüştürücü sorgudan dönen JSON sonuçlarını işleyip daha kullanışlı bir formata dönüştürmek için kullanılabilir.
\
123 | Dönüştürücü içierisinde javascript fonksiyonu tanımlanmalıdır. Bu fonksiyondan dönen yeni sonuç çıktı kısmına yazdırılır.
\
124 | Örnek:
\
125 | return root.hits.hits[0]; sonucu dolaşarak ilk eşleşmeyi göster
\
126 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0); tüm kümede kullanılan toplam belleği gösterir
\
127 | Aşağıdaki fonksiyonlar dizi ve objelerin işlenmesinde yardımcı olması için kullanılabilir
\
128 |
\
129 | - Object.keys(object) := array
\
130 | - array.forEach(function(prop, index))
\
131 | - array.map(function(prop, index)) := array
\
132 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
133 |
\
134 | Sorgu tekrarlama çalışırken, prev isimli ekstra bir parametre dönüştürücü fonksiyonuna verilir. Bu sayede karşılaştırmalar ve toplu grafik gösterimleri yapılabilir.
\
135 | Örnek:
\
136 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la; önceki dakika boyunca kümede bulunan ilk nod üzerindeki averaj yükü verir.\
137 | Bu sonuç nod için yük grafiği yaratılmasında kullanılabilir.\
138 | "
139 | });
140 |
141 | i18n.setKeys({
142 | "AnyRequest.DisplayOptionsHelp" : "\
143 |
Sade Json: Sorgunun tüm sonuçlarını ve (yapıldıysa) dönüştürüldükten sonraki halini sade JSON formatında gösterir
\
144 | Sonuçları Çizdir: Sonuçları grafiksel olarak görüntülemek için sonuç dörücüyü kullanarak değerleri dizi haline getirin.
\
145 | Arama Sonuçları Tablosu: Eğer sorgunuz bir arama ise, sonuçları bir tabloda görüntüleyebilirsiniz.
\
146 | "
147 | });
148 |
149 | i18n.setKeys({
150 | "QueryFilter.DateRangeHelp" : "\
151 | Tarih alanları ana dile yakın kelimeler kullanarak iki tarih aralığında sorgu yapılabilmesini sağlar.
\
152 | Aşağıdaki tanımlar kullanılabilir:
\
153 | \
154 | - Anahtar Kelimeler
\
155 | now
today
tomorrow
yesterday
last / this / next + week / month / year
\
156 | kelimeleri eşleşen tarihleri verir. Örneğin last year geçen yıl tarihli bütün verileri döndürür. \
157 | - Aralıklar
\
158 | 1000 secs
5mins
1day
2days
80d
9 months
2yrs (boşluklar isteğe bağlıdır, ayni kelime için farklı yazım şekilleri kullanılabilir)
\
159 | Şu anki tarihi (now) baz alarak geçmiş veya ileriki bir tarih aralığındaki kayıtları verir. \
160 | - Tarih ve Kısmi Tarihler
\
161 | 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
162 | bu formatlar spesifik bir tarihi tanımlarlar. 2011 tüm 2011 yılını ararken, 2011-01-18 12:32:45 şeklinde bir sorgu sadece o saniyedeki sonuçları verir. \
163 | - Zaman ve Kısmi Zamanlar
\
164 | 12
12:32
12:32:45
\
165 | bu formatlar gün içerisinde spesifik bir zamanı tanımlarlar. Örneğin 12:32 sadece bu saat ve dakikadaki kayıtları verir. \
166 | - Tarih Aralıkları
\
167 | 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
168 | Tarih aralıkları yukarda belirtilen herhangi bir formatı < or -> ile ayırarak yapılabilir. Eğer aralığın bir tarafı eksikse, sorgu ucu açıkmış gibi davranır. \
169 | - Ofsetli Tarih Aralığı
\
170 | 2010 -> 1yr
3mins < now\
171 | Verilen yöndeki tarih aralığına bakar. \
172 | - Çakılı Aralıklar
\
173 | 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
174 | Yukarıdakiyle ayni fakat belirtilen tarihten her iki yöne de bakılır. \
175 |
\
176 | "
177 | });
178 |
--------------------------------------------------------------------------------
/head/lang/pt_strings.js:
--------------------------------------------------------------------------------
1 | i18n.setKeys({
2 | "General.Elasticsearch": "Elasticsearch",
3 | "General.LoadingAggs": "Carregando Facetas...",
4 | "General.Searching": "Buscando...",
5 | "General.Search": "Busca",
6 | "General.Help": "Ajuda",
7 | "General.HelpGlyph": "?",
8 | "General.CloseGlyph": "X",
9 | "General.RefreshResults": "Atualizar",
10 | "General.ManualRefresh": "Atualização Manual",
11 | "General.RefreshQuickly": "Atualização rápida",
12 | "General.Refresh5seconds": "Atualização a cada 5 segundos",
13 | "General.Refresh1minute": "Atualização a cada minuto",
14 | "AliasForm.AliasName": "Apelido",
15 | "AliasForm.NewAliasForIndex": "Novo apelido para {0}",
16 | "AliasForm.DeleteAliasMessage": "digite ''{0}'' para deletar {1}. Não há como voltar atrás",
17 | "AnyRequest.DisplayOptions" : "Mostrar Opções",
18 | "AnyRequest.AsGraph" : "Mostrar como gráfico",
19 | "AnyRequest.AsJson" : "Mostrar JSON bruto",
20 | "AnyRequest.AsTable" : "Mostrar tabela de resultados da consulta",
21 | "AnyRequest.History" : "Histórico",
22 | "AnyRequest.RepeatRequest" : "Refazer requisição",
23 | "AnyRequest.RepeatRequestSelect" : "Repetir requisição a cada ",
24 | "AnyRequest.Transformer" : "Transformador de resultado",
25 | "AnyRequest.Pretty": "Amigável",
26 | "AnyRequest.Query" : "Consulta",
27 | "AnyRequest.Request": "Requisição",
28 | "AnyRequest.Requesting": "Realizando requisição...",
29 | "AnyRequest.ValidateJSON": "Validar JSON",
30 | "Browser.Title": "Navegador",
31 | "Browser.ResultSourcePanelTitle": "Resultado",
32 | "Command.DELETE": "DELETAR",
33 | "Command.SHUTDOWN": "DESLIGAR",
34 | "Command.DeleteAliasMessage": "Remover apelido?",
35 | "ClusterOverView.IndexName": "Nome do índice",
36 | "ClusterOverview.NumShards": "Número de Shards",
37 | "ClusterOverview.NumReplicas": "Número de Réplicas",
38 | "ClusterOverview.NewIndex": "Novo índice",
39 | "IndexActionsMenu.Title": "Ações",
40 | "IndexActionsMenu.NewAlias": "Novo apelido...",
41 | "IndexActionsMenu.Refresh": "Atualizar",
42 | "IndexActionsMenu.Flush": "Flush",
43 | "IndexActionsMenu.Optimize": "Otimizar...",
44 | "IndexActionsMenu.Snapshot": "Snapshot do Gateway",
45 | "IndexActionsMenu.Analyser": "Analizador de teste",
46 | "IndexActionsMenu.Open": "Abrir",
47 | "IndexActionsMenu.Close": "Fechar",
48 | "IndexActionsMenu.Delete": "Deletar...",
49 | "IndexInfoMenu.Title": "Info",
50 | "IndexInfoMenu.Status": "Status do índice",
51 | "IndexInfoMenu.Metadata": "Metadados do índice",
52 | "IndexCommand.TextToAnalyze": "Texto para analizar",
53 | "IndexCommand.ShutdownMessage": "digite ''{0}'' para desligar {1}. Nó NÃO PODE ser reiniciado à partir dessa interface",
54 | "IndexOverview.PageTitle": "Visão geral dos índices",
55 | "IndexSelector.NameWithDocs": "{0} ({1} documentoss)",
56 | "IndexSelector.SearchIndexForDocs": "Busca {0} por documentos onde:",
57 | "FilterBrowser.OutputType": "Resultados: {0}",
58 | "FilterBrowser.OutputSize": "Número de Resultados: {0}",
59 | "Header.ClusterHealth": "saúde do cluster: {0} ({1} {2})",
60 | "Header.ClusterNotConnected": "saúde do cluster: não conectado",
61 | "Header.Connect": "Conectar",
62 | "Nav.AnyRequest": "Qualquer requisição",
63 | "Nav.Browser": "Navegador",
64 | "Nav.ClusterHealth": "Saúde do Cluster",
65 | "Nav.ClusterState": "Estado do Cluster",
66 | "Nav.ClusterNodes": "Nós do Cluster",
67 | "Nav.Info": "Informações",
68 | "Nav.NodeStats": "Estatísticas do nó",
69 | "Nav.Overview": "Visão Geral",
70 | "Nav.Indices": "Índices",
71 | "Nav.Plugins": "Plugins",
72 | "Nav.Status": "Status",
73 | "Nav.Templates": "Modelos",
74 | "Nav.StructuredQuery": "Consulta Estruturada",
75 | "NodeActionsMenu.Title": "Ações",
76 | "NodeActionsMenu.Shutdown": "Desligar...",
77 | "NodeInfoMenu.Title": "Informações",
78 | "NodeInfoMenu.ClusterNodeInfo": "Informações do Nó do Cluster",
79 | "NodeInfoMenu.NodeStats": "Estatísticas do Nó",
80 | "NodeType.Client": "Nó cliente",
81 | "NodeType.Coord": "Coordenador",
82 | "NodeType.Master": "Nó mestre",
83 | "NodeType.Tribe": "Nó tribo",
84 | "NodeType.Worker": "Nó trabalhador",
85 | "NodeType.Unassigned": "Não atribuido",
86 | "OptimizeForm.OptimizeIndex": "Otimizar {0}",
87 | "OptimizeForm.MaxSegments": "# Máximo De Segmentos",
88 | "OptimizeForm.ExpungeDeletes": "Apenas Expurgar Exclusões",
89 | "OptimizeForm.FlushAfter": "Flush após Otimizar",
90 | "OptimizeForm.WaitForMerge": "Esperar Por Merge",
91 | "Overview.PageTitle": "Visão geral do Cluster",
92 | "Output.JSON": "JSON",
93 | "Output.Table": "Tabela",
94 | "Output.CSV": "CSV",
95 | "Output.ShowSource": "Mostrar consulta original",
96 | "Preference.SortCluster": "Ordenar Cluster",
97 | "Sort.ByName": "Por nome",
98 | "Sort.ByAddress": "Por endereço",
99 | "Sort.ByType": "Por tipo",
100 | "Preference.ViewAliases": "Ver Alias",
101 | "ViewAliases.Grouped": "Agrupado",
102 | "ViewAliases.List": "Lista",
103 | "ViewAliases.None": "Nenhum",
104 | "Overview.IndexFilter": "Filtar Índice",
105 | "TableResults.Summary": "Buscado {0} de {1} shards. {2} resultados. {3} segundos",
106 | "QueryFilter.AllIndices": "Todos os Índices",
107 | "QueryFilter.AnyValue": "qualquer",
108 | "QueryFilter-Header-Indices": "Índices",
109 | "QueryFilter-Header-Types": "Tipos",
110 | "QueryFilter-Header-Fields": "Campos",
111 | "QueryFilter.DateRangeHint.from": "De : {0}",
112 | "QueryFilter.DateRangeHint.to": " A : {0}",
113 | "Query.FailAndUndo": "Consulta falhou. Desfazendo últimas alterações",
114 | "StructuredQuery.ShowRawJson": "Mostrar JSON bruto"
115 | });
116 |
117 | i18n.setKeys({
118 | "AnyRequest.TransformerHelp" : "\
119 | O Transformador de Resultados pode ser usado para transformar os resultados de uma consulta de json bruto para um formato mais útil.
\
120 | O transformador deve possuir o corpo de uma função javascript. O retorno da função se torna o novo valor passado para o json printer
\
121 | Exemplo:
\
122 | return root.hits.hits[0]; irá alterar a resposta para mostrar apenas o primeiro resultado
\
123 | return Object.keys(root.nodes).reduce(function(tot, node) { return tot + root.nodes[node].os.mem.used_in_bytes; }, 0); irá retornar o total de memória utilizada pelo cluster
\
124 | As seguintes funções estão disponíveis e podem ser úteis no processamento de vetores e objetos
\
125 |
\
126 | - Object.keys(object) := array
\
127 | - array.forEach(function(prop, index))
\
128 | - array.map(function(prop, index)) := array
\
129 | - array.reduce(function(accumulator, prop, index), initial_value) := final_value
\
130 |
\
131 | Durante a execução da opção Refazer Requisição, um parâmetro extra chamado prev é passado para a função de transformação. Isso permite fazer comparações e marcações cumulativas
\
132 | Exemplo:
\
133 | var la = [ root.nodes[Object.keys(root.nodes)[0]].os.load_average[0] ]; return prev ? la.concat(prev) : la; irá retornar a carga média no primeiro nó do cluster no último minuto\
134 | Essa informação pode ser inserida no Gráfico para fazer um gráfico de carga do nó\
135 | "
136 | });
137 |
138 | i18n.setKeys({
139 | "AnyRequest.DisplayOptionsHelp" : "\
140 |
Json Bruto: Exibe o resultado completo da consulta e da transformação no formato de JSON bruto
\
141 | Gráfico de Resultados: Para gerar um gráfico com seus resultados, utilize o tranformador de resultados para produzir um vetor de valores
\
142 | Tabela de Resultados da Consulta: Se sua consulta for uma busca, você pode exibir seus resultados no formato de uma tabela.
\
143 | "
144 | });
145 |
146 | i18n.setKeys({
147 | "QueryFilter.DateRangeHelp" : "\
148 | Campos do tipo Data aceitam consultas em linguagem natural (em inglês) para produzir um From e um To de modo a formar um intervalo dentro do qual os resultados são filtrados.
\
149 | Os seguintes formatos são suportados:
\
150 | \
151 | - Palavras-chave
\
152 | now
today
tomorrow
yesterday
last / this / next + week / month / year
\
153 | buscam por datas de acordo com a palavra-chave. last year irá buscar tudo do último ano. \
154 | - Intervalos
\
155 | 1000 secs
5mins
1day
2days
80d
9 months
2yrs (espaços são opcionais, diversos sinônimos para qualificadores de intervalo)
\
156 | Cria um intervalo de busca a partir de agora (now), extendendo este intervalo no passado e no futuro de acordo com intervalo especificado. \
157 | - Data/Hora (DateTime) e Data/Hora parcial
\
158 | 2011
2011-01
2011-01-18
2011-01-18 12
2011-01-18 12:32
2011-01-18 12:32:45
\
159 | esses formatos especificam um intervalo especifico. 2011 irá buscar todo o ano de 2011, enquanto 2011-01-18 12:32:45 irá buscar apenas por resultados dentro deste intervalo de 1 segundo \
160 | - Tempo (Time) e Tempo parcial
\
161 | 12
12:32
12:32:45
\
162 | esses formatos buscam por um horário específico no dia atual. 12:32 irá buscar este minuto específico do dia \
163 | - Intervalos de Data
\
164 | 2010 -> 2011
last week -> next week
2011-05 ->
< now
\
165 | Um intervalo de data é criado especificando-se duas datas em qualquer formato (Palavras-chave, Data/Hora ou Tempo) separados por < ou -> (ambos fazem a mesma coisa). Se a data de início ou fim do intervalo não for especificada é a mesma coisa que não impor limites na busca nesta direção. \
166 | - Intervalo de Data com Deslocamento
\
167 | 2010 -> 1yr
3mins < now\
168 | Busca a data especificada incluindo o intervalo na direção determinada pelo deslocamento \
169 | - Intervalos Bidirecionais
\
170 | 2010-05-13 05:13 <> 10m
now <> 1yr
lastweek <> 1month
\
171 | Idêntico ao exemplo anterior porém o intervalo é extendido em ambas as direções a partir da data especificada \
172 |
\
173 | "
174 | });
175 |
--------------------------------------------------------------------------------
/App/esql.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Apr 19, 2017
3 |
4 | @author: qs
5 | '''
6 |
7 | from App.utils import http_response_error,http_response_succes,http_response_nor
8 | import yaml
9 | import os
10 | from elasticsearch import Elasticsearch
11 | from ql.parse import lexer
12 | from ql.parse import parser
13 | from ply.lex import lex
14 | from ply.yacc import yacc
15 | from ql.dsl.Query import Query
16 | from ql.dsl.Response import response_hits,response_nor,response_cat,response_mappings,response_bulk
17 | from elasticsearch import ElasticsearchException
18 | from ql.parse.parser import TK
19 | from ql.dsl.Create import Create
20 | from ql.dsl.Describe import Describe
21 | from ql.dsl.Insert import Insert,Bulk
22 | from ql.dsl.Update import Update,Upsert
23 | from ql.dsl.Delete import Delete
24 | from ql.dsl.Drop import Drop
25 | from ql.dsl.Explain import Explain
26 | import time
27 |
28 |
29 | ESQL_HOME = os.path.realpath(os.path.join(__file__, '..', '..'))
30 |
31 |
32 | class Esql():
33 | def __init__(self):
34 | conf_file = open(os.path.join(ESQL_HOME,'conf','esql.yml'), 'r')
35 | app_conf = yaml.load(conf_file)
36 | conf_file.close()
37 | self.es_hosts = app_conf['elastic'].get('hosts')
38 | self.es_handler = Elasticsearch(self.es_hosts)
39 | self.lexer = lex(module=lexer,optimize=True,debug=False)
40 | self.parser = yacc(debug=False,module=parser)
41 |
42 |
43 | def get_host_url(self):
44 | return "http://" + self.es_hosts[0]['host'] + ":" + str(self.es_hosts[0]['port'])
45 |
46 |
47 |
48 | def _exec_query(self,ast):
49 |
50 | try:
51 | stmt = Query(ast)
52 | except Exception:
53 | return http_response_error('Parse statement to dsl error!')
54 |
55 | try:
56 | if hasattr(stmt, 'route'):
57 | hits = self.es_handler.search(index=stmt._index, doc_type = stmt._type, body = stmt.dsl(),routing = stmt.route, request_timeout=100)
58 | else:
59 | hits = self.es_handler.search(index=stmt._index, doc_type = stmt._type, body = stmt.dsl(), request_timeout=100)
60 | except ElasticsearchException as e:
61 | return http_response_error(str(e))
62 | try:
63 | mappings = self.es_handler.indices.get_mapping(index=stmt._index, doc_type = stmt._type)
64 | except ElasticsearchException as e:
65 | return http_response_error(str(e))
66 | selecols = stmt.dsl()['_source']
67 | stmt_res = None
68 | try:
69 | stmt_res = response_hits(hits,mappings,selecols)
70 | except Exception as e:
71 | return http_response_nor(str(e))
72 | return http_response_succes(stmt_res)
73 |
74 |
75 | def _exec_create_table(self,ast):
76 |
77 | start_time = time.time()
78 | try:
79 | stmt = Create(ast)
80 | except Exception:
81 | return http_response_error('Parse statement to dsl error!')
82 | try:
83 | res = self.es_handler.indices.create(index=stmt._index,body = stmt._options,request_timeout=100,ignore= 400)
84 | if stmt._type == None:
85 | stmt._type = 'base'
86 | res = self.es_handler.indices.put_mapping(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), request_timeout=100)
87 | except ElasticsearchException as e:
88 | return http_response_nor(str(e))
89 |
90 | stmt_res = None
91 |
92 | end_time = time.time()
93 |
94 | took = int((end_time - start_time)*1000)
95 | try:
96 | stmt_res = response_nor(res,took)
97 | except Exception as e:
98 | return http_response_error(str(e))
99 | return http_response_succes(stmt_res)
100 |
101 |
102 | def _exec_show_tables(self,ast):
103 |
104 | start_time = time.time()
105 |
106 | try:
107 | res = self.es_handler.cat.indices(v=True,bytes='b',h=['index','status','pri','rep','docs.count','store.size'])
108 | except ElasticsearchException as e:
109 | return http_response_error(str(e))
110 |
111 | stmt_res = res
112 |
113 | end_time = time.time()
114 |
115 | took = int((end_time - start_time)*1000)
116 | try:
117 | stmt_res = response_cat(res,took)
118 | except Exception as e:
119 | return http_response_error(str(e))
120 | return http_response_succes(stmt_res)
121 |
122 |
123 |
124 | def _exec_desc_table(self,ast):
125 | start_time = time.time()
126 | try:
127 | stmt = Describe(ast)
128 | except Exception:
129 | return http_response_error('Parse statement to dsl error!')
130 | try:
131 | res = self.es_handler.indices.get_mapping(index = stmt._index, doc_type = stmt._type)
132 | except ElasticsearchException as e:
133 | return http_response_error(e.error)
134 |
135 | stmt_res = None
136 |
137 | end_time = time.time()
138 |
139 | took = int((end_time - start_time)*1000)
140 | try:
141 | stmt_res = response_mappings(res,took)
142 | except Exception as e:
143 | return http_response_error(str(e))
144 | return http_response_succes(stmt_res)
145 |
146 |
147 | def _exec_drop_table(self,ast):
148 | start_time = time.time()
149 | try:
150 | stmt = Drop(ast)
151 | except Exception:
152 | return http_response_error('Parse statement to dsl error!')
153 | try:
154 | res = self.es_handler.indices.delete(index = stmt._index)
155 | except ElasticsearchException as e:
156 | return http_response_error(e.error)
157 |
158 | stmt_res = None
159 |
160 | end_time = time.time()
161 |
162 | took = int((end_time - start_time)*1000)
163 | try:
164 | stmt_res = response_nor(res,took)
165 | except Exception as e:
166 | return http_response_error(str(e))
167 | return http_response_succes(stmt_res)
168 |
169 | def _exec_insert_into(self,ast):
170 | start_time = time.time()
171 | try:
172 | stmt = Insert(ast)
173 | except Exception:
174 | return http_response_error('Parse statement to dsl error!')
175 | try:
176 | parms = stmt.metas
177 | if stmt._type == None:
178 | stmt._type = 'base'
179 | res = self.es_handler.index(index = stmt._index,doc_type = stmt._type, body = stmt.dsl(),**parms)
180 |
181 | except ElasticsearchException as e:
182 | return http_response_error(str(e))
183 |
184 | stmt_res = None
185 | end_time = time.time()
186 | took = int((end_time - start_time)*1000)
187 | try:
188 | stmt_res = response_nor(res,took)
189 | except Exception as e:
190 | return http_response_error(str(e))
191 | return http_response_succes(stmt_res)
192 |
193 |
194 | def _exec_bulk_into(self,ast):
195 |
196 | try:
197 | stmt = Bulk(ast)
198 | except Exception:
199 | return http_response_error('Parse statement to dsl error!')
200 | try:
201 | if stmt._type == None:
202 | stmt._type = 'base'
203 | res = self.es_handler.bulk(index = stmt._index,doc_type = stmt._type, body = stmt.dsl())
204 |
205 | except ElasticsearchException as e:
206 | return http_response_error(str(e))
207 |
208 | stmt_res = None
209 |
210 | try:
211 | stmt_res = response_bulk(res)
212 | except Exception as e:
213 | return http_response_error(str(e))
214 | return http_response_succes(stmt_res)
215 |
216 |
217 |
218 | def _exec_update(self,ast):
219 | start_time = time.time()
220 | try:
221 | stmt = Update(ast)
222 | except Exception:
223 | return http_response_error('Parse statement to dsl error!')
224 | try:
225 | if stmt._type == None:
226 | stmt._type = 'base'
227 | res = self.es_handler.update(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), **stmt.conditions)
228 |
229 | except ElasticsearchException as e:
230 | return http_response_error(str(e))
231 |
232 | stmt_res = None
233 |
234 | end_time = time.time()
235 | took = int((end_time - start_time)*1000)
236 | try:
237 | stmt_res = response_nor(res,took)
238 | except Exception as e:
239 | return http_response_error(str(e))
240 | return http_response_succes(stmt_res)
241 |
242 |
243 | def _exec_upsert(self,ast):
244 | start_time = time.time()
245 | try:
246 | stmt = Upsert(ast)
247 | except Exception:
248 | return http_response_error('Parse statement to dsl error!')
249 | try:
250 | if stmt._type == None:
251 | stmt._type = 'base'
252 | res = self.es_handler.update(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(), **stmt.conditions)
253 |
254 | except ElasticsearchException as e:
255 | return http_response_error(str(e))
256 |
257 | stmt_res = None
258 |
259 | end_time = time.time()
260 | took = int((end_time - start_time)*1000)
261 | try:
262 | stmt_res = response_nor(res,took)
263 | except Exception as e:
264 | return http_response_error(str(e))
265 | return http_response_succes(stmt_res)
266 |
267 |
268 | def _exec_delete(self,ast):
269 | start_time = time.time()
270 | try:
271 | stmt = Delete(ast)
272 | except Exception:
273 | return http_response_error('Parse statement to dsl error!')
274 | try:
275 | res = self.es_handler.delete_by_query(index = stmt._index, doc_type = stmt._type, body = stmt.dsl(),timeout='30m')
276 | except ElasticsearchException as e:
277 | return http_response_error(str(e))
278 |
279 | stmt_res = None
280 |
281 | end_time = time.time()
282 | took = int((end_time - start_time)*1000)
283 | try:
284 | stmt_res = response_nor(res,took)
285 | except Exception as e:
286 | return http_response_error(str(e))
287 | return http_response_succes(stmt_res)
288 |
289 |
290 | def _exec_explain(self,ast):
291 | try:
292 | stmt = Explain(ast)
293 | except Exception:
294 | return http_response_error('Parse statement to dsl error!')
295 | return http_response_nor(stmt.dsl(),202)
296 |
297 |
298 | def exec_statement(self,sql):
299 | ast = None
300 | try:
301 | ast = self.parser.parse(lexer=self.lexer.clone(),debug=False,input=sql)
302 | except Exception as e:
303 | return http_response_error(str(e))
304 |
305 | if ast == None:
306 | return http_response_error('parse statement error')
307 |
308 | if ast.get_type() == TK.TOK_QUERY:
309 | return self._exec_query(ast)
310 | elif ast.get_type() == TK.TOK_CREATE_TABLE:
311 | return self._exec_create_table(ast)
312 | elif ast.get_type() == TK.TOK_SHOW_TABLES:
313 | return self._exec_show_tables(ast)
314 | elif ast.get_type() == TK.TOK_DESC_TABLE:
315 | return self._exec_desc_table(ast)
316 | elif ast.get_type() == TK.TOK_INSERT_INTO:
317 | return self._exec_insert_into(ast)
318 | elif ast.get_type() == TK.TOK_BULK_INTO:
319 | return self._exec_bulk_into(ast)
320 | elif ast.get_type() == TK.TOK_UPDATE:
321 | return self._exec_update(ast)
322 | elif ast.get_type() == TK.TOK_UPSERT_INTO:
323 | return self._exec_upsert(ast)
324 | elif ast.get_type() == TK.TOK_DELETE:
325 | return self._exec_delete(ast)
326 | elif ast.get_type() == TK.TOK_DROP_TABLE:
327 | return self._exec_drop_table(ast)
328 | elif ast.get_type() == TK.TOK_EXPLAIN:
329 | return self._exec_explain(ast)
330 | else:
331 | return http_response_error('Syntax not supported!')
332 |
333 |
334 |
335 |
--------------------------------------------------------------------------------
/head/app.css:
--------------------------------------------------------------------------------
1 | TABLE.table {
2 | border-collapse: collapse;
3 | }
4 |
5 |
6 | TABLE.table TH {
7 | font-weight: normal;
8 | text-align: left;
9 | vertical-align: middle;
10 | }
11 |
12 | TABLE.table TBODY.striped TR:nth-child(odd) {
13 | background: #eee;
14 | }
15 |
16 | TABLE.table H3 {
17 | margin: 0;
18 | font-weight: bold;
19 | font-size: 140%;
20 | }
21 |
22 | .require { color: #a00; }
23 |
24 | .uiButton {
25 | padding: 0;
26 | border: 0;
27 | margin: 3px;
28 | width: auto;
29 | overflow: visible;
30 | cursor: pointer;
31 | background: transparent;
32 | }
33 |
34 | .uiButton-content {
35 | height: 20px;
36 | border: 1px solid #668dc6;
37 | border-radius: 2px;
38 | background: #96c6eb;
39 | background: -moz-linear-gradient(top, #96c6eb, #5296c7);
40 | background: -webkit-linear-gradient(top, #96c6eb, #5296c7);
41 | color: white;
42 | font-weight: bold;
43 | }
44 |
45 | .moz .uiButton-content { margin: 0 -2px; }
46 |
47 | .uiButton-label {
48 | padding: 2px 6px;
49 | white-space: nowrap;
50 | }
51 | .uiButton:hover .uiButton-content {
52 | background: #2777ba;
53 | background: -moz-linear-gradient(top, #6aaadf, #2777ba);
54 | background: -webkit-linear-gradient(top, #6aaadf, #2777ba);
55 | }
56 | .uiButton.active .uiButton-content,
57 | .uiButton:active .uiButton-content {
58 | background: #2575b7;
59 | background: -moz-linear-gradient(top, #2576b8, #2575b7);
60 | background: -webkit-linear-gradient(top, #2576b8, #2575b7);
61 | }
62 | .uiButton.disabled .uiButton-content,
63 | .uiButton.disabled:active .uiButton-content {
64 | border-color: #c6c6c6;
65 | color: #999999;
66 | background: #ddd;
67 | background: -moz-linear-gradient(top, #ddd, #ddd);
68 | background: -webkit-linear-gradient(top, #ddd, #ddd);
69 | }
70 |
71 | .uiButton.disabled {
72 | cursor: default;
73 | }
74 |
75 | .uiMenuButton {
76 | display: inline-block;
77 | }
78 |
79 | .uiMenuButton .uiButton-label {
80 | background-image: url('data:image/gif;base64,R0lGODlhDwAPAIABAP///////yH5BAEAAAEALAAAAAAPAA8AAAITjI+py+0P4wG0gmavq1HLD4ZiAQA7');
81 | background-position: right 50%;
82 | background-repeat: no-repeat;
83 | padding-right: 17px;
84 | text-align: left;
85 | }
86 |
87 | .uiSplitButton {
88 | white-space: nowrap;
89 | }
90 |
91 | .uiSplitButton .uiButton:first-child {
92 | margin-right: 0;
93 | display: inline-block;
94 | }
95 |
96 | .uiSplitButton .uiButton:first-child .uiButton-content {
97 | border-right-width: 1;
98 | border-right-color: #5296c7;
99 | border-top-right-radius: 0;
100 | border-bottom-right-radius: 0;
101 | }
102 |
103 | .uiSplitButton .uiMenuButton {
104 | margin-left: 0;
105 | }
106 |
107 | .uiSplitButton .uiButton:last-child .uiButton-content {
108 | border-radius: 2px;
109 | border-left-width: 1;
110 | border-left-color: #96c6eb;
111 | border-top-left-radius: 0;
112 | border-bottom-left-radius: 0;
113 | height: 20px;
114 | }
115 |
116 | .uiSplitButton .uiButton:last-child .uiButton-label {
117 | padding: 2px 17px 2px 6px;
118 | margin-left: -8px;
119 | }
120 |
121 | .uiToolbar {
122 | height: 28px;
123 | background: #fdfefe;
124 | background: -moz-linear-gradient(top, #fdfefe, #eaedef);
125 | background: -webkit-linear-gradient(top, #fdfefe, #eaedef);
126 | border-bottom: 1px solid #d2d5d7;
127 | padding: 3px 10px;
128 | }
129 |
130 | .uiToolbar H2 {
131 | display: inline-block;
132 | font-size: 120%;
133 | margin: 0;
134 | padding: 5px 20px 5px 0;
135 | }
136 |
137 | .uiToolbar .uiTextField {
138 | display: inline-block;
139 | }
140 |
141 | .uiToolbar .uiTextField INPUT {
142 | padding-top: 2px;
143 | padding-bottom: 5px;
144 | }
145 | #uiModal {
146 | background: black;
147 | }
148 |
149 | .uiPanel {
150 | box-shadow: -1px 2.5px 4px -3px black, -1px -2.5px 4px -3px black, 3px 2.5px 4px -3px black, 3px -2.5px 4px -3px black;
151 | position: absolute;
152 | background: #eee;
153 | border: 1px solid #666;
154 | }
155 |
156 | .uiPanel-titleBar {
157 | text-align: center;
158 | font-weight: bold;
159 | padding: 2px 0;
160 | background: rgba(223, 223, 223, 0.75);
161 | background: -moz-linear-gradient(top, rgba(223, 223, 223, 0.75), rgba(193, 193, 193, 0.75), rgba(223, 223, 223, 0.75));
162 | background: -webkit-linear-gradient(top, rgba(223, 223, 223, 0.75), rgba(193, 193, 193, 0.75), rgba(223, 223, 223, 0.75));
163 | border-bottom: 1px solid #bbb;
164 | }
165 |
166 | .uiPanel-close {
167 | cursor: pointer;
168 | border: 1px solid #aaa;
169 | background: #fff;
170 | color: #fff;
171 | float: left;
172 | height: 10px;
173 | left: 3px;
174 | line-height: 9px;
175 | padding: 1px 0;
176 | position: relative;
177 | text-shadow: 0 0 1px #000;
178 | top: 0px;
179 | width: 12px;
180 | }
181 | .uiPanel-close:hover {
182 | background: #eee;
183 | }
184 |
185 | .uiPanel-body {
186 | overflow: auto;
187 | }
188 |
189 |
190 | .uiInfoPanel {
191 | background: rgba(0, 0, 0, 0.75);
192 | color: white;
193 | border-radius: 8px;
194 | padding: 1px;
195 | }
196 | .uiInfoPanel .uiPanel-titleBar {
197 | background: rgba(74, 74, 74, 0.75);
198 | background: -moz-linear-gradient(top, rgba(84, 84, 84, 0.75), rgba(54, 54, 54, 0.75), rgba(64, 64, 64, 0.75));
199 | background: -webkit-linear-gradient(top, rgba(84, 84, 84, 0.75), rgba(54, 54, 54, 0.75), rgba(64, 64, 64, 0.75));
200 | border-radius: 8px 8px 0 0;
201 | padding: 1px 0 2px 0;
202 | border-bottom: 0;
203 | }
204 | .uiInfoPanel .uiPanel-close {
205 | border-radius: 6px;
206 | height: 13px;
207 | width: 13px;
208 | background: #ccc;
209 | left: 3px;
210 | top: 1px;
211 | color: #333;
212 | text-shadow: #222 0 0 1px;
213 | line-height: 11px;
214 | border: 0;
215 | padding: 0;
216 | }
217 | .uiInfoPanel .uiPanel-close:hover {
218 | background: #eee;
219 | }
220 |
221 | .uiInfoPanel .uiPanel-body {
222 | background: transparent;
223 | padding: 20px;
224 | border-radius: 0 0 8px 8px;
225 | border: 1px solid #222;
226 | }
227 |
228 | .uiMenuPanel {
229 | border: 1px solid #668dc6;
230 | position: absolute;
231 | background: #96c6eb;
232 | color: white;
233 | }
234 |
235 | .uiMenuPanel LI {
236 | list-style: none;
237 | border-bottom: 1px solid #668dc6;
238 | }
239 |
240 | .uiMenuPanel LI:hover {
241 | background: #2575b7;
242 | }
243 |
244 | .uiMenuPanel LI:last-child {
245 | border-bottom: 0;
246 | }
247 |
248 | .uiMenuPanel-label {
249 | white-space: nowrap;
250 | padding: 2px 10px 2px 10px;
251 | cursor: pointer;
252 | }
253 |
254 | .disabled .uiMenuPanel-label {
255 | cursor: auto;
256 | color: #888;
257 | }
258 |
259 | .uiSelectMenuPanel .uiMenuPanel-label {
260 | margin-left: 1em;
261 | padding-left: 4px;
262 | }
263 |
264 | .uiSelectMenuPanel .uiMenuPanel-item.selected .uiMenuPanel-label:before {
265 | content: "\2713";
266 | width: 12px;
267 | margin-left: -12px;
268 | display: inline-block;
269 | }
270 |
271 | .uiTable TABLE {
272 | border-collapse: collapse;
273 | }
274 |
275 | .uiTable-body {
276 | overflow-y: scroll;
277 | overflow-x: auto;
278 | }
279 |
280 | .uiTable-headers {
281 | overflow-x: hidden;
282 | }
283 |
284 | .uiTable-body TD {
285 | white-space: nowrap;
286 | }
287 |
288 | .uiTable-body .uiTable-header-row TH,
289 | .uiTable-body .uiTable-header-row TH DIV {
290 | padding-top: 0;
291 | padding-bottom: 0;
292 | }
293 |
294 | .uiTable-body .uiTable-header-cell > DIV {
295 | height: 0;
296 | overflow: hidden;
297 | }
298 |
299 | .uiTable-headercell-menu {
300 | float: right;
301 | }
302 |
303 | .uiTable-tools {
304 | padding: 3px 4px;
305 | height: 14px;
306 | }
307 |
308 | .uiTable-header-row {
309 | background: #ddd;
310 | background: -moz-linear-gradient(top, #eee, #ccc);
311 | background: -webkit-linear-gradient(top, #eee, #ccc);
312 | }
313 |
314 | .uiTable-headercell-text {
315 | margin-right: 20px;
316 | }
317 |
318 | .uiTable-headercell-menu {
319 | display: none;
320 | }
321 |
322 | .uiTable-header-row TH {
323 | border-right: 1px solid #bbb;
324 | padding: 0;
325 | text-align: left;
326 | }
327 |
328 | .uiTable-header-row TH > DIV {
329 | padding: 3px 4px;
330 | border-right: 1px solid #eee;
331 | }
332 |
333 | .uiTable-headerEndCap > DIV {
334 | width: 19px;
335 | }
336 |
337 | .uiTable-header-row .uiTable-sort {
338 | background: #ccc;
339 | background: -moz-linear-gradient(top, #bebebe, #ccc);
340 | background: -webkit-linear-gradient(top, #bebebe, #ccc);
341 | }
342 | .uiTable-header-row TH.uiTable-sort > DIV {
343 | border-right: 1px solid #ccc;
344 | }
345 |
346 | .uiTable-sort .uiTable-headercell-menu {
347 | display: block;
348 | }
349 |
350 | .uiTable TABLE TD {
351 | border-right: 1px solid transparent;
352 | padding: 3px 4px;
353 | }
354 |
355 | .uiTable-body TABLE TR:nth-child(even) {
356 | background: #f3f3f3;
357 | }
358 |
359 | .uiTable-body TABLE TR.selected {
360 | color: white;
361 | background: #6060f1;
362 | }
363 |
364 | DIV.uiJsonPretty-object { font-size: 1.26em; font-family: monospace; }
365 | UL.uiJsonPretty-object,
366 | UL.uiJsonPretty-array { margin: 0; padding: 0 0 0 2em; list-style: none; }
367 | UL.uiJsonPretty-object LI,
368 | UL.uiJsonPretty-array LI { padding: 0; margin: 0; }
369 | .expando > SPAN.uiJsonPretty-name:before { content: "\25bc\a0"; color: #555; position: relative; top: 2px; }
370 | .expando.uiJsonPretty-minimised > SPAN.uiJsonPretty-name:before { content: "\25ba\a0"; top: 0; }
371 | .uiJsonPretty-minimised > UL SPAN.uiJsonPretty-name:before,
372 | .expando .uiJsonPretty-minimised > UL SPAN.uiJsonPretty-name:before { content: ""; }
373 | SPAN.uiJsonPretty-string,
374 | SPAN.uiJsonPretty-string A { color: green; }
375 | SPAN.uiJsonPretty-string A { text-decoration: underline;}
376 | SPAN.uiJsonPretty-number { color: blue; }
377 | SPAN.uiJsonPretty-null { color: red; }
378 | SPAN.uiJsonPretty-boolean { color: purple; }
379 | .expando > .uiJsonPretty-name { cursor: pointer; }
380 | .expando > .uiJsonPretty-name:hover { text-decoration: underline; }
381 | .uiJsonPretty-minimised { white-space: nowrap; overflow: hidden; }
382 | .uiJsonPretty-minimised > UL { opacity: 0.6; }
383 | .uiJsonPretty-minimised .uiJsonPretty-minimised > UL { opacity: 1; }
384 | .uiJsonPretty-minimised UL, .uiJsonPretty-minimised LI { display: inline; padding: 0; }
385 |
386 |
387 | .uiJsonPanel SPAN.uiJsonPretty-string { color: #6F6; }
388 | .uiJsonPanel SPAN.uiJsonPretty-number { color: #66F; }
389 | .uiJsonPanel SPAN.uiJsonPretty-null { color: #F66; }
390 | .uiJsonPanel SPAN.uiJsonPretty-boolean { color: #F6F; }
391 |
392 | .uiPanelForm-field {
393 | display: block;
394 | padding: 2px 0;
395 | clear: both;
396 | }
397 |
398 | .uiPanelForm-label {
399 | float: left;
400 | width: 200px;
401 | padding: 3px 7px;
402 | text-align: right;
403 | }
404 |
405 | .uiSidebarSection-head {
406 | background-color: #b9cfff;
407 | background-image: url('data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAcCAMAAABifa5OAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAMAUExURQUCFf///wICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkNDQ0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///2Oyy/cAAAACdFJOU/8A5bcwSgAAADxJREFUeNq8zzkOACAMA8Hd/3+agiuRcIsrRopIjArOoLK1QAMNNBCRPkhLyzkn35Bjfd7JR1Nr09NoDACnvgDl1zlzoQAAAABJRU5ErkJggg==');
408 | background-repeat: no-repeat;
409 | background-position: 2px 5px;
410 | margin-bottom: 1px;
411 | padding: 3px 3px 3px 17px;
412 | cursor: pointer;
413 | }
414 |
415 | .shown > .uiSidebarSection-head {
416 | background-position: 2px -13px;
417 | }
418 |
419 | .uiSidebarSection-body {
420 | margin-bottom: 3px;
421 | display: none;
422 | }
423 |
424 | .uiSidebarSection-help {
425 | text-shadow: #228 1px 1px 2px;
426 | color: blue;
427 | cursor: pointer;
428 | }
429 |
430 | .uiSidebarSection-help:hover {
431 | text-decoration: underline;
432 | }
433 |
434 | .uiQueryFilter {
435 | width: 350px;
436 | padding: 5px;
437 | background: #d8e7ff;
438 | background: -moz-linear-gradient(left, #d8e7ff, #e8f1ff);
439 | background: -webkit-linear-gradient(left, #d8e7ff, #e8f1ff);
440 | }
441 |
442 | .uiQueryFilter DIV.uiQueryFilter-section {
443 | margin-bottom: 5px;
444 | }
445 |
446 | .uiQueryFilter HEADER {
447 | display: block;
448 | font-variant: small-caps;
449 | font-weight: bold;
450 | margin: 5px 0;
451 | }
452 |
453 | .uiQueryFilter-aliases SELECT {
454 | width: 100%;
455 | }
456 |
457 | .uiQueryFilter-booble {
458 | cursor: pointer;
459 | background: #e8f1ff;
460 | border: 1px solid #e8f1ff;
461 | border-radius: 5px;
462 | padding: 1px 4px;
463 | margin-bottom: 1px;
464 | overflow: hidden;
465 | white-space: nowrap;
466 | }
467 |
468 | .uiQueryFilter-booble.selected {
469 | background: #dae3f0;
470 | border-top: 1px solid #c8d4e6;
471 | border-left: 1px solid #c8d4e6;
472 | border-bottom: 1px solid #ffffff;
473 | border-right: 1px solid #ffffff;
474 | }
475 |
476 | .uiQueryFilter-filterName {
477 | background-color: #cbdfff;
478 | margin-bottom: 4px;
479 | padding: 3px;
480 | cursor: pointer;
481 | }
482 |
483 | .uiQueryFilter-filters INPUT {
484 | width: 300px;
485 | }
486 |
487 | .uiQueryFilter-subMultiFields {
488 | padding-left: 10px;
489 | }
490 |
491 | .uiQueryFilter-rangeHintFrom,
492 | .uiQueryFilter-rangeHintTo {
493 | margin: 0;
494 | opacity: 0.75;
495 | }
496 | .uiBrowser-filter {
497 | float: left;
498 | }
499 |
500 | .uiBrowser-table {
501 | margin-left: 365px;
502 | }
503 |
504 | .uiAnyRequest-request {
505 | float: left;
506 | width: 350px;
507 | padding: 5px;
508 | background: #d8e7ff;
509 | background: -moz-linear-gradient(left, #d8e7ff, #e8f1ff);
510 | background: -webkit-linear-gradient(left, #d8e7ff, #e8f1ff);
511 | }
512 |
513 | .uiAnyRequest-request INPUT[type=text],
514 | .uiAnyRequest-request TEXTAREA {
515 | width: 340px;
516 | }
517 |
518 | .anyRequest INPUT[name=path] {
519 | width: 259px;
520 | }
521 |
522 | .uiAnyRequest-out {
523 | margin-left: 365px;
524 | }
525 |
526 | .uiAnyRequest-out P {
527 | margin-top: 0;
528 | }
529 |
530 | .uiAnyRequest-jsonErr {
531 | color: red;
532 | }
533 |
534 | .uiAnyRequest-history {
535 | margin: 0;
536 | padding: 0;
537 | list-style: none;
538 | max-height: 100px;
539 | overflow-x: hidden;
540 | overflow-y: auto;
541 | }
542 |
543 | .uiNodesView TH,
544 | .uiNodesView TD {
545 | vertical-align: top;
546 | padding: 2px 20px;
547 | }
548 |
549 | .uiNodesView TH.close,
550 | .uiNodesView TD.close {
551 | color: #888;
552 | background: #f2f2f2;
553 | }
554 |
555 | .uiNodesView .uiMenuButton .uiButton-content {
556 | padding-right: 3px;
557 | border-radius: 8px;
558 | height: 14px;
559 | }
560 |
561 | .uiNodesView .uiMenuButton.active .uiButton-content,
562 | .uiNodesView .uiMenuButton:active .uiButton-content {
563 | border-bottom-right-radius: 0px;
564 | border-bottom-left-radius: 0px;
565 | }
566 |
567 | .uiNodesView .uiMenuButton .uiButton-label {
568 | padding: 0px 17px 0px 7px;
569 | }
570 |
571 | .uiNodesView-hasAlias {
572 | text-align: center;
573 | }
574 | .uiNodesView-hasAlias.max {
575 | border-top-right-radius: 8px;
576 | border-bottom-right-radius: 8px;
577 | }
578 | .uiNodesView-hasAlias.min {
579 | border-top-left-radius: 8px;
580 | border-bottom-left-radius: 8px;
581 | }
582 | .uiNodesView-hasAlias-remove {
583 | float: right;
584 | font-weight: bold;
585 | cursor: pointer;
586 | }
587 |
588 | .uiNodesView TD.uiNodesView-icon {
589 | padding: 20px 0px 15px 20px;
590 | }
591 |
592 | .uiNodesView-node:nth-child(odd) {
593 | background: #eee;
594 | }
595 |
596 | .uiNodesView-routing {
597 | position: relative;
598 | min-width: 90px;
599 | }
600 |
601 | .uiNodesView-nullReplica,
602 | .uiNodesView-replica {
603 | box-sizing: border-box;
604 | cursor: pointer;
605 | float: left;
606 | height: 40px;
607 | width: 35px;
608 | margin: 4px;
609 | border: 2px solid #444;
610 | padding: 2px;
611 | font-size: 32px;
612 | line-height: 32px;
613 | text-align: center;
614 | letter-spacing: -5px;
615 | text-indent: -7px;
616 | }
617 |
618 | .uiNodesView-replica.primary {
619 | border-width: 4px;
620 | line-height: 29px;
621 | }
622 |
623 | .uiNodesView-nullReplica {
624 | border-color: transparent;
625 | }
626 |
627 | .uiNodesView-replica.state-UNASSIGNED { background: #eeeeee; color: #999; border-color: #666; float: none; display: inline-block; }
628 | .uiNodesView-replica.state-INITIALIZING { background: #dddc88; }
629 | .uiNodesView-replica.state-STARTED { background: #99dd88; }
630 | .uiNodesView-replica.state-RELOCATING { background: #dc88dd; }
631 |
632 |
633 | .uiClusterConnect-uri {
634 | width: 280px;
635 | }
636 |
637 | .uiStructuredQuery {
638 | padding: 10px;
639 | }
640 |
641 | .uiStructuredQuery-out {
642 | min-height: 30px;
643 | }
644 |
645 | .uiFilterBrowser-row * {
646 | margin-right: 0.4em;
647 | }
648 |
649 | .uiFilterBrowser-row BUTTON {
650 | height: 22px;
651 | position: relative;
652 | top: 1px;
653 | }
654 |
655 | .uiHeader {
656 | padding: 3px 10px;
657 | }
658 |
659 | .uiHeader-name, .uiHeader-status {
660 | font-size: 1.2em;
661 | font-weight: bold;
662 | padding: 0 10px;
663 | }
664 |
665 |
666 | .uiApp-header {
667 | background: #eee;
668 | position: fixed;
669 | width: 100%;
670 | z-index: 9;
671 | }
672 |
673 | .uiApp-header H1 {
674 | margin: -2px 0 -4px 0;
675 | float: left;
676 | padding-right: 25px;
677 | }
678 |
679 | .uiApp-headerMenu {
680 | border-bottom: 1px solid #bbb;
681 | padding: 0px 3px;
682 | height: 22px;
683 | }
684 |
685 | .uiApp-headerMenu .active {
686 | background: white;
687 | border-bottom-color: white;
688 | }
689 |
690 | .uiApp-headerMenuItem {
691 | border: 1px solid #bbb;
692 | padding: 4px 8px 1px ;
693 | margin: 2px 1px 0;
694 | height: 14px;
695 | cursor: pointer;
696 | }
697 |
698 | .uiApp-body {
699 | padding: 51px 0px 0px 0px;
700 | }
701 |
702 | .uiApp-headerNewMenuItem {
703 | color: blue;
704 | }
705 |
--------------------------------------------------------------------------------
/ql/parse/parser.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Dec 15, 2016
3 |
4 | @author: qs
5 | '''
6 |
7 | from ql.parse import lexer
8 | from ql.parse import ASTNode
9 | from enum import Enum
10 |
11 | class AutoNumber(Enum):
12 | def __new__(cls):
13 | value = len(cls.__members__) + 1
14 | obj = object.__new__(cls)
15 | obj._value_ = value
16 | return obj
17 |
18 |
19 |
20 | class TK(AutoNumber):
21 | TOK_IDENTIFIER = ()
22 | TOK_VALUE = ()
23 | TOK_DQ_VALUE = ()
24 | TOK_DOT = ()
25 | TOK_LIST = ()
26 | TOK_DICT = ()
27 | TOK_TUPLE = ()
28 | TOK_KEY_VALUE = ()
29 |
30 | TOK_CORE_TYPE = ()
31 | TOK_TABLE_NAME=()
32 |
33 | TOK_CREATE_TABLE = ()
34 | TOK_QUERY = ()
35 | TOK_INSERT_INTO = ()
36 | TOK_BULK_INTO = ()
37 | TOK_UPSERT_INTO = ()
38 | TOK_UPDATE = ()
39 | TOK_DELETE = ()
40 |
41 | TOK_COLUMN_DEFINE = ()
42 | TOK_COLUMN_OPTIONS = ()
43 | TOK_META_DEFINE = ()
44 | TOK_META_OPTIONS = ()
45 | TOK_TABLE_COLUMNS = ()
46 | TOK_TABLE_METAS = ()
47 | TOK_TABLE_OPTIONS = ()
48 |
49 | TOK_FUNCTION = ()
50 | TOK_EXPRESSION = ()
51 | TOK_COMPARE = ()
52 | TOK_IN = ()
53 | TOK_REVERSED = ()
54 | TOK_COMPOUND = ()
55 | TOK_EXPRESSION_LEFT = ()
56 | TOK_EXPRESSION_RIGHT = ()
57 |
58 | TOK_SELECT = ()
59 | TOK_SELEXPR = ()
60 | TOK_FROM = ()
61 | TOK_WHERE = ()
62 | TOK_LIMIT = ()
63 | TOK_ORDERBY = ()
64 | TOK_GROUPBY = ()
65 | TOK_SORT = ()
66 | TOK_SORT_MODE = ()
67 |
68 | TOK_INSERT_COLUMNS = ()
69 | TOK_INSERT_ROW = ()
70 | TOK_INSERT_ROWS = ()
71 |
72 | TOK_SET_COLUMNS_CLAUSE = ()
73 |
74 | TOK_EXPLAIN = ()
75 |
76 | TOK_DESC_TABLE = ()
77 | TOK_SHOW_TABLES = ()
78 | TOK_DROP_TABLE = ()
79 |
80 | tokens = lexer.tokens
81 |
82 | precedence = (
83 | ('left','OR'),
84 | ('left','AND'),
85 | ('left','NOT'))
86 |
87 |
88 | def token_list(plist):
89 | retval = []
90 | if len(plist) == 2:
91 | retval = [plist[1]]
92 | else:
93 | if isinstance(plist[3],list):
94 | retval = [plist[1]] + plist[3]
95 | else:
96 | retval = [plist[1],plist[3]]
97 | return retval
98 |
99 |
100 | def p_EXECUTE_STATEMENT(p):
101 | '''EXECUTE_STATEMENT : STATEMENT'''
102 | p[0] = p[1]
103 |
104 |
105 | def p_EXPLAIN_STATEMENT(p):
106 | '''STATEMENT : EXPLAIN STATEMENT'''
107 | p[0] = ASTNode.Node(TK.TOK_EXPLAIN,None,[p[2]])
108 |
109 |
110 | def p_STATEMENT(p):
111 | '''STATEMENT : TOK_CREATE_TABLE
112 | | TOK_INSERT_INTO
113 | | TOK_QUERY
114 | | TOK_BULK_INTO
115 | | TOK_UPDATE
116 | | TOK_UPSERT_INTO
117 | | TOK_DELETE
118 | | TOK_SHOW_TABLES
119 | | TOK_DESC_TABLE
120 | | TOK_DROP_TABLE'''
121 | p[0] = p[1]
122 |
123 |
124 |
125 | '''======================================base define========================================================'''
126 |
127 |
128 | def p_TOK_OPTIONS_OBJECT(p):
129 | '''TOK_OPTIONS_OBJECT : "(" KV_ELEMENTS_EXPR ")"'''
130 | p[0] = ASTNode.Node(TK.TOK_DICT,None,p[2])
131 |
132 |
133 | def p_TOK_DICT_OBJECT(p):
134 | '''TOK_DICT_OBJECT : "{" KV_ELEMENTS_EXPR "}"'''
135 | p[0] = ASTNode.Node(TK.TOK_DICT,None,p[2])
136 |
137 |
138 | def p_TOK_LIST_OBJECT(p):
139 | '''TOK_LIST_OBJECT : "[" VALUES_EXPR "]"
140 | | "[" "]"'''
141 | if len(p) == 4:
142 | p[0] = ASTNode.Node(TK.TOK_LIST,None,p[2])
143 | else:
144 | p[0] = ASTNode.Node(TK.TOK_LIST,None,None)
145 |
146 |
147 | def p_TOK_TUPLE_OBJECT(p):
148 | '''TOK_TUPLE_OBJECT : "(" VALUES_EXPR ")"
149 | | "(" ")"'''
150 | if len(p) == 4:
151 | p[0] = ASTNode.Node(TK.TOK_TUPLE,None,p[2])
152 | else:
153 | p[0] = ASTNode.Node(TK.TOK_TUPLE,None,None)
154 |
155 |
156 | def p_KV_ELEMENTS_EXPR(p):
157 | '''KV_ELEMENTS_EXPR : TOK_KEY_VALUE
158 | | TOK_KEY_VALUE COMMA TOK_KEY_VALUE
159 | | TOK_KEY_VALUE COMMA KV_ELEMENTS_EXPR'''
160 | p[0] = token_list(p)
161 |
162 |
163 | def p_VALUES_EXPR(p):
164 | '''VALUES_EXPR : VALUE_EXPR
165 | | VALUE_EXPR COMMA VALUE_EXPR
166 | | VALUE_EXPR COMMA VALUES_EXPR'''
167 | p[0] = token_list(p)
168 |
169 |
170 | def p_TOK_KEY_VALUE(p):
171 | '''TOK_KEY_VALUE : TOK_EXPRESSION'''
172 | if p[1].get_value() != '=':
173 | pass
174 | else:
175 | p[0] = p[1]
176 | p[0].set_type(TK.TOK_KEY_VALUE)
177 |
178 |
179 |
180 | def p_LEFT_RESERVED_VALUES_EXPR(p):
181 | '''LEFT_RESERVED_VALUES_EXPR : FROM
182 | | TO'''
183 | p[0] = ASTNode.Node(TK.TOK_VALUE,p[1],None)
184 |
185 |
186 |
187 | def p_LEFT_VALUE_EXPR(p):
188 | '''LEFT_VALUE_EXPR : VALUE_EXPR
189 | | TOK_FUNCTION_EXPR
190 | | LEFT_RESERVED_VALUES_EXPR'''
191 | p[0] = p[1]
192 |
193 | def p_LEFT_VALUES_EXPR(p):
194 | '''LEFT_VALUES_EXPR : LEFT_VALUE_EXPR
195 | | LEFT_VALUE_EXPR COMMA LEFT_VALUE_EXPR
196 | | LEFT_VALUE_EXPR COMMA LEFT_VALUES_EXPR'''
197 | p[0] = token_list(p)
198 |
199 |
200 | def p_RIGHT_VALUE_EXPR(p):
201 | '''RIGHT_VALUE_EXPR : VALUE_EXPR'''
202 | p[0] = p[1]
203 |
204 |
205 | def p_RIGHT_VALUES_EXPR(p):
206 | '''RIGHT_VALUES_EXPR : VALUE_EXPR
207 | | RIGHT_VALUE_EXPR COMMA RIGHT_VALUE_EXPR
208 | | RIGHT_VALUE_EXPR COMMA RIGHT_VALUES_EXPR'''
209 | p[0] = token_list(p)
210 |
211 |
212 |
213 | def p_VALUE_EXPR(p):
214 | '''VALUE_EXPR : TOK_DOT
215 | | TOK_VALUE
216 | | TOK_DICT_OBJECT
217 | | TOK_LIST_OBJECT'''
218 | p[0] = p[1]
219 |
220 |
221 | def p_TOK_DOT(p):
222 | '''TOK_DOT : TOK_VALUE "." TOK_VALUE
223 | | TOK_VALUE "." TOK_DOT'''
224 | p[0] = ASTNode.Node(TK.TOK_DOT,p[2],[p[1],(p[3])])
225 |
226 |
227 | def p_TOK_DQ_VALUE(p):
228 | '''TOK_VALUE : DQUOTE_STRING'''
229 | p[0] = ASTNode.Node(TK.TOK_VALUE,p[1],[ASTNode.Node(TK.TOK_DQ_VALUE,None,None)])
230 |
231 |
232 | def p_TOK_VALUE(p):
233 | '''TOK_VALUE : WORD
234 | | QUOTE_STRING
235 | | NUMBER
236 | | "*"'''
237 | p[0] = ASTNode.Node(TK.TOK_VALUE,p[1],None)
238 |
239 |
240 |
241 | def p_TOK_WILDCARD_VALUE(p):
242 | '''TOK_VALUE : WORD "*"'''
243 | p[0] = ASTNode.Node(TK.TOK_VALUE,p[1] + p[2],None)
244 |
245 |
246 | '''=======================================operator define=============================================='''
247 |
248 |
249 | def p_EXPRESSIONS_REVERSED_EXPR(p):
250 | '''EXPRESSION_EXPR : NOT EXPRESSION_EXPR'''
251 | p[0] = ASTNode.Node(TK.TOK_REVERSED,p[1].lower(),[p[2]])
252 |
253 |
254 | def p_EXPRESSIONS_GROUP_EXPR(p):
255 | '''EXPRESSION_EXPR : "(" EXPRESSION_EXPR ")"'''
256 | p[0] = p[2]
257 |
258 |
259 | def p_EXPRESSION_OPERATOR_EXPR(p):
260 | '''EXPRESSION_EXPR : EXPRESSION_EXPR OR EXPRESSION_EXPR
261 | | EXPRESSION_EXPR AND EXPRESSION_EXPR'''
262 | p[0] = ASTNode.Node(TK.TOK_COMPOUND,p[2].lower(),[p[1],p[3]])
263 |
264 |
265 |
266 | def p_EXPRESSION_EXPR(p):
267 | '''EXPRESSION_EXPR : TOK_EXPRESSION
268 | | TOK_FUNCTION_EXPR
269 | | TOK_IN_EXPR'''
270 | p[0] = p[1]
271 |
272 |
273 | def p_TOK_EXPRESSION_LEFT(p):
274 | '''TOK_EXPRESSION_LEFT : LEFT_VALUES_EXPR'''
275 | p[0] = ASTNode.Node(TK.TOK_EXPRESSION_LEFT,None,p[1])
276 |
277 | def p_TOK_EXPRESSION_RIGHT(p):
278 | '''TOK_EXPRESSION_RIGHT : RIGHT_VALUE_EXPR'''
279 | p[0] = ASTNode.Node(TK.TOK_EXPRESSION_RIGHT,None,[p[1]])
280 |
281 | def p_TOK_EXPRESSION(p):
282 | '''TOK_EXPRESSION : TOK_EXPRESSION_LEFT COMPARE_TYPE_EXPR TOK_EXPRESSION_RIGHT'''
283 | if p[2] == '!=':
284 | expression = ASTNode.Node(TK.TOK_COMPARE,'=',[p[1],p[3]])
285 | p[0] = ASTNode.Node(TK.TOK_REVERSED,'NOT'.lower(),[expression])
286 | else:
287 | p[0] = ASTNode.Node(TK.TOK_COMPARE,p[2],[p[1],p[3]])
288 |
289 |
290 | def p_COMPARE_TYPE_EXPR(p):
291 | '''COMPARE_TYPE_EXPR : COMPARE_TYPE
292 | | LIKE'''
293 | p[0] = p[1]
294 |
295 |
296 | def p_TOK_FUNCTION_EXPR(p):
297 | '''TOK_FUNCTION_EXPR : TOK_BEWTEEN
298 | | TOK_FUNCTION
299 | | TOK_ISNULL'''
300 | p[0] = p[1]
301 |
302 |
303 | def p_TOK_FUNCTION(p):
304 | '''TOK_FUNCTION : VALUE_EXPR TOK_TUPLE_OBJECT'''
305 | p[0] = ASTNode.Node(TK.TOK_FUNCTION,p[1].get_value(),p[2].get_children())
306 |
307 |
308 | def p_TOK_BEWTEEN(p):
309 | '''TOK_BEWTEEN : VALUE_EXPR BETWEEN RIGHT_VALUE_EXPR AND RIGHT_VALUE_EXPR'''
310 | p[0] = ASTNode.Node(TK.TOK_FUNCTION,p[2],[p[1],p[3],p[5]])
311 |
312 |
313 | def p_TOK_ISNULL(p):
314 | '''TOK_ISNULL : VALUE_EXPR IS NULL
315 | | VALUE_EXPR IS NOT NULL'''
316 | if len(p) == 4:
317 | p[0] = ASTNode.Node(TK.TOK_FUNCTION,'ISNULL',[p[1]])
318 | else:
319 | expression = ASTNode.Node(TK.TOK_FUNCTION,'ISNULL',[p[1]])
320 | p[0] = ASTNode.Node(TK.TOK_REVERSED,'NOT'.lower(),[expression])
321 |
322 |
323 | def p_TOK_IN_EXPR(p):
324 | '''TOK_IN_EXPR : TOK_EXPRESSION_LEFT IN TOK_TUPLE_OBJECT'''
325 | p[0] = p[0] = ASTNode.Node(TK.TOK_IN,p[2],[p[1],p[3]])
326 |
327 | '''==========================================table define==========================================='''
328 |
329 |
330 | def p_TOK_CREATE_TABLE_WITH_OPTIONS(p):
331 | '''TOK_CREATE_TABLE : TOK_CREATE_TABLE WITH OPTION TOK_TABLE_OPTIONS'''
332 | p[0] = p[1]
333 | p[0].append_children(p[4])
334 |
335 |
336 | def p_TOK_CREATE_TABLE_WITH_META(p):
337 | '''TOK_CREATE_TABLE : TOK_CREATE_TABLE WITH META TOK_TABLE_METAS'''
338 | p[0] = p[1]
339 | p[0].append_children(p[4])
340 |
341 |
342 | def p_TOK_CREATE_TABLE(p):
343 | '''TOK_CREATE_TABLE : CREATE TABLE TOK_TABLE_NAME TOK_TABLE_COLS'''
344 | p[0] = ASTNode.Node(TK.TOK_CREATE_TABLE,None,[p[3],p[4]])
345 | p[0].get_value()
346 |
347 |
348 | def p_TOK_META_OPTIONS(p):
349 | '''TOK_META_OPTIONS : TOK_OPTIONS_OBJECT'''
350 | p[0] = ASTNode.Node(TK.TOK_META_OPTIONS,None,[p[1]])
351 |
352 |
353 | def p_TOK_META_DEFINE(p):
354 | '''TOK_META_DEF : WORD TOK_META_OPTIONS'''
355 | p[0] = ASTNode.Node(TK.TOK_META_DEFINE,p[1],[p[2]])
356 |
357 |
358 | def p_TOK_METAS_DEFINE(p):
359 | '''TOK_METAS_DEF : TOK_META_DEF
360 | | TOK_META_DEF COMMA TOK_META_DEF
361 | | TOK_META_DEF COMMA TOK_METAS_DEF'''
362 | p[0] = token_list(p)
363 |
364 |
365 | def p_TOK_TABLE_METAS(p):
366 | '''TOK_TABLE_METAS : "(" ")"
367 | | "(" TOK_METAS_DEF ")"'''
368 | if len(p) == 3:
369 | p[0] = ASTNode.Node(TK.TOK_TABLE_METAS,None,None)
370 | else:
371 | p[0] = ASTNode.Node(TK.TOK_TABLE_METAS,None,p[2])
372 |
373 |
374 | def p_TOK_TABLE_OPTIONS(p):
375 | '''TOK_TABLE_OPTIONS : TOK_OPTIONS_OBJECT'''
376 | p[0] = ASTNode.Node(TK.TOK_TABLE_OPTIONS,None,[p[1]])
377 |
378 |
379 | def p_TOK_TABLE_NAME(p):
380 | '''TOK_TABLE_NAME : VALUE_EXPR'''
381 | p[0] = ASTNode.Node(TK.TOK_TABLE_NAME,None,[p[1]])
382 |
383 |
384 | def p_TOK_TABLE_COLS(p):
385 | '''TOK_TABLE_COLS : "(" ")"
386 | | "(" TOK_COLUMNS_DEFINE ")"'''
387 | if len(p) == 3:
388 | p[0] = ASTNode.Node(TK.TOK_TABLE_COLUMNS,None,None)
389 | else:
390 | p[0] = ASTNode.Node(TK.TOK_TABLE_COLUMNS,None,p[2])
391 |
392 |
393 | def p_TOK_COLUMNS_DEFINE(p):
394 | '''TOK_COLUMNS_DEFINE : TOK_COLUMN_DEFINE
395 | | TOK_COLUMN_DEFINE COMMA TOK_COLUMN_DEFINE
396 | | TOK_COLUMN_DEFINE COMMA TOK_COLUMNS_DEFINE'''
397 | p[0] = token_list(p)
398 |
399 |
400 | def p_COLUMN_TYPE(p):
401 | '''COLUMN_TYPE : WORD'''
402 | p[0] = ASTNode.Node(TK.TOK_CORE_TYPE,p[1],None)
403 |
404 |
405 | def p_TOK_COLUMN_OBJECT_DEFINE(p):
406 | '''TOK_COLUMN_DEFINE : TOK_COLUMN_DEFINE AS TOK_TABLE_COLS'''
407 | p[0] = p[1]
408 | p[0].append_children(p[3])
409 |
410 |
411 | def p_p_TOK_COLUMN_OPTIONS(p):
412 | '''TOK_COLUMN_OPTIONS : TOK_OPTIONS_OBJECT'''
413 | p[0] = ASTNode.Node(TK.TOK_COLUMN_OPTIONS,None,[p[1]])
414 |
415 |
416 | def p_TOK_COLUMN_DEFINE(p):
417 | '''TOK_COLUMN_DEFINE : WORD COLUMN_TYPE
418 | | WORD COLUMN_TYPE TOK_COLUMN_OPTIONS'''
419 | if len(p) == 3:
420 | p[0] = ASTNode.Node(TK.TOK_COLUMN_DEFINE,p[1],[p[2]])
421 | else:
422 | p[0] = ASTNode.Node(TK.TOK_COLUMN_DEFINE,p[1],[p[2],p[3]])
423 |
424 |
425 |
426 |
427 |
428 | '''=================================query define========================================'''
429 |
430 |
431 | def p_TOK_QUERY_WITH_ORDERBY(p):
432 | '''TOK_QUERY : TOK_QUERY ORDER BY TOK_ORDERBY'''
433 | p[0] = p[1]
434 | p[0].append_children(p[4])
435 |
436 |
437 | def p_TOK_QUERY_WITH_EXPRESSIONS(p):
438 | '''TOK_QUERY : TOK_QUERY WHERE TOK_WHERE'''
439 | p[0] = p[1]
440 | p[0].append_children(p[3])
441 |
442 | def p_TOK_QUERY_WITH_LIMITS(p):
443 | '''TOK_QUERY : TOK_QUERY LIMIT TOK_LIMIT'''
444 | p[0] = p[1]
445 | p[0].append_children(p[3])
446 |
447 |
448 | def p_TOK_QUERY(p):
449 | '''TOK_QUERY : SELECT TOK_SELECT FROM TOK_FROM'''
450 | p[0] = ASTNode.Node(TK.TOK_QUERY,None,[p[2],p[4]])
451 |
452 |
453 | def p_TOK_FROM(p):
454 | '''TOK_FROM : TOK_TABLE_NAME'''
455 | p[0] = ASTNode.Node(TK.TOK_FROM,None,[p[1]])
456 |
457 | def p_TOK_FROM_WITH_ROUTING(p):
458 | '''TOK_FROM : TOK_TABLE_NAME "@" TOK_VALUE'''
459 | p[0] = ASTNode.Node(TK.TOK_FROM,None,[p[1],p[3]])
460 |
461 |
462 | def p_TOK_WHRER(p):
463 | '''TOK_WHERE : EXPRESSION_EXPR'''
464 | p[0] = ASTNode.Node(TK.TOK_WHERE,None,[p[1]])
465 |
466 |
467 | def p_TOK_SELECT(p):
468 | '''TOK_SELECT : TOK_SELEXPRS'''
469 | p[0] = ASTNode.Node(TK.TOK_SELECT,None,p[1])
470 |
471 |
472 | def p_TOK_SELEXPR(p):
473 | '''TOK_SELEXPR : LEFT_VALUE_EXPR
474 | | LEFT_VALUE_EXPR AS VALUE_EXPR'''
475 | if len(p) == 2:
476 | p[0] = ASTNode.Node(TK.TOK_SELEXPR,None,[p[1]])
477 | else:
478 | p[0] = ASTNode.Node(TK.TOK_SELEXPR,None,[p[1],p[3]])
479 |
480 | def p_TOK_SELEXPRS(p):
481 | '''TOK_SELEXPRS : TOK_SELEXPR
482 | | TOK_SELEXPR COMMA TOK_SELEXPR
483 | | TOK_SELEXPR COMMA TOK_SELEXPRS'''
484 | p[0] = token_list(p)
485 |
486 |
487 | def p_TOK_LIMIT(p):
488 | '''TOK_LIMIT : LIMITS_EXPR'''
489 | p[0] = ASTNode.Node(TK.TOK_LIMIT,None,p[1])
490 |
491 |
492 | def p_LIMIT_EXPR(p):
493 | '''LIMIT_EXPR : NUMBER'''
494 | p[0] = ASTNode.Node(TK.TOK_VALUE,p[1],None)
495 |
496 |
497 | def p_LIMITS_EXPR(p):
498 | '''LIMITS_EXPR : LIMIT_EXPR
499 | | LIMIT_EXPR COMMA LIMIT_EXPR'''
500 | if len(p) == 2:
501 | p[0] = [p[1]]
502 | else:
503 | p[0] = [p[1],p[3]]
504 |
505 |
506 | def p_TOK_ORDERBY(p):
507 | '''TOK_ORDERBY : TOK_SORTS'''
508 | p[0] = ASTNode.Node(TK.TOK_ORDERBY,None,p[1])
509 |
510 |
511 | def p_TOK_SORTS(p):
512 | '''TOK_SORTS : TOK_SORT
513 | | TOK_SORT COMMA TOK_SORT
514 | | TOK_SORT COMMA TOK_SORTS'''
515 | p[0] = token_list(p)
516 |
517 |
518 | def p_SORT_MODE(p):
519 | '''SORT_MODE : ASC
520 | | DESC'''
521 | p[0] = ASTNode.Node(TK.TOK_SORT_MODE,p[1],None)
522 |
523 |
524 | def p_TOK_SORT(p):
525 | '''TOK_SORT : LEFT_VALUE_EXPR
526 | | LEFT_VALUE_EXPR SORT_MODE'''
527 | if len(p) == 2:
528 | p[0] = ASTNode.Node(TK.TOK_SORT,None,[p[1]])
529 | else:
530 | p[0] = ASTNode.Node(TK.TOK_SORT,None,[p[1],p[2]])
531 |
532 |
533 |
534 |
535 | '''=================================Aggregations define========================================'''
536 |
537 | def p_TOK_QUERY_WITH_GROUPBY(p):
538 | '''TOK_QUERY : TOK_QUERY GROUP BY TOK_GROUPBY'''
539 | p[0] = p[1]
540 | p[0].append_children(p[4])
541 |
542 |
543 | def p_TOK_GROUPBY(p):
544 | '''TOK_GROUPBY : LEFT_VALUES_EXPR'''
545 | p[0] = ASTNode.Node(TK.TOK_GROUPBY,None,p[1])
546 |
547 |
548 |
549 | '''=================================Load data define========================================'''
550 |
551 | def p_TOK_INSERT_INTO(p):
552 | '''TOK_INSERT_INTO : INSERT INTO TOK_TABLE_NAME TOK_INSERT_COLUMNS VALUES TOK_VALUE_ROW'''
553 | p[0] = ASTNode.Node(TK.TOK_INSERT_INTO,None,[p[3]] + [p[4]] + [p[6]])
554 |
555 |
556 |
557 | def p_TOK_INSERT_COLUMNS(p):
558 | '''TOK_INSERT_COLUMNS : TOK_TUPLE_OBJECT'''
559 | p[0] = ASTNode.Node(TK.TOK_INSERT_COLUMNS,None,p[1].get_children())
560 |
561 |
562 | def p_TOK_INSERT_ROW(p):
563 | '''TOK_VALUE_ROW : "(" RIGHT_VALUES_EXPR ")" '''
564 | p[0] = ASTNode.Node(TK.TOK_INSERT_ROW,None,p[2])
565 |
566 |
567 | def p_INSERT_ROWS_EXPR(p):
568 | '''INSERT_ROWS_EXPR : TOK_VALUE_ROW
569 | | TOK_VALUE_ROW COMMA TOK_VALUE_ROW
570 | | TOK_VALUE_ROW COMMA INSERT_ROWS_EXPR'''
571 | p[0] = token_list(p)
572 |
573 |
574 | def p_TOK_BULK_INTO(p):
575 | '''TOK_BULK_INTO : BULK INTO TOK_TABLE_NAME TOK_INSERT_COLUMNS VALUES INSERT_ROWS_EXPR'''
576 |
577 | rows = ASTNode.Node(TK.TOK_INSERT_ROWS,None,p[6])
578 |
579 | p[0] = ASTNode.Node(TK.TOK_BULK_INTO,None,[p[3]] + [p[4]] + [rows])
580 |
581 |
582 | def p_TOK_UPDATE(p):
583 | '''TOK_UPDATE : UPDATE TOK_TABLE_NAME SET TOK_SET_COLUMNS_CLAUSE WHERE TOK_WHERE'''
584 | p[0] = ASTNode.Node(TK.TOK_UPDATE,None,[p[2]] + [p[4]] + [p[6]])
585 |
586 |
587 | def p_TOK_SET_COLUMNS(p):
588 | '''TOK_SET_COLUMNS_CLAUSE : KV_ELEMENTS_EXPR'''
589 | p[0] = ASTNode.Node(TK.TOK_SET_COLUMNS_CLAUSE,None,p[1])
590 |
591 |
592 |
593 | def p_TOK_UPSERT_INTO(p):
594 | '''TOK_UPSERT_INTO : UPSERT TOK_TABLE_NAME SET TOK_SET_COLUMNS_CLAUSE WHERE TOK_WHERE'''
595 | p[0] = ASTNode.Node(TK.TOK_UPSERT_INTO,None,[p[2]] + [p[4]] + [p[6]])
596 |
597 |
598 | def p_TOK_DELETE(p):
599 | '''TOK_DELETE : DELETE FROM TOK_TABLE_NAME WHERE TOK_WHERE'''
600 | p[0] = ASTNode.Node(TK.TOK_DELETE,None,[p[3]] + [p[5]])
601 |
602 |
603 | '''=================================show========================================'''
604 |
605 |
606 | def p_SHOW_TABLES(p):
607 | '''TOK_SHOW_TABLES : SHOW TABLES'''
608 | p[0] = ASTNode.Node(TK.TOK_SHOW_TABLES,None,None)
609 |
610 |
611 | '''=================================desc========================================'''
612 | def p_DESC_TABLE(p):
613 | '''TOK_DESC_TABLE : DESC TOK_TABLE_NAME'''
614 | p[0] = ASTNode.Node(TK.TOK_DESC_TABLE,None,[p[2]])
615 |
616 |
617 | '''=================================drop========================================'''
618 | def p_DROP_TABLE(p):
619 | '''TOK_DROP_TABLE : DROP TABLE TOK_TABLE_NAME'''
620 | p[0] = ASTNode.Node(TK.TOK_DROP_TABLE,None,[p[3]])
621 |
622 |
623 |
624 | def p_error(p):
625 | raise Exception("Illegal syntax")
626 |
--------------------------------------------------------------------------------
/head/vendor.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */
5 | /* FONT PATH
6 | * -------------------------- */
7 | @font-face {
8 | font-family: 'FontAwesome';
9 | src: url('fonts/fontawesome-webfont.eot?v=4.0.3');
10 | src: url('fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');
11 | font-weight: normal;
12 | font-style: normal;
13 | }
14 | .fa {
15 | display: inline-block;
16 | font-family: FontAwesome;
17 | font-style: normal;
18 | font-weight: normal;
19 | line-height: 1;
20 | -webkit-font-smoothing: antialiased;
21 | -moz-osx-font-smoothing: grayscale;
22 | }
23 | /* makes the font 33% larger relative to the icon container */
24 | .fa-lg {
25 | font-size: 1.3333333333333333em;
26 | line-height: 0.75em;
27 | vertical-align: -15%;
28 | }
29 | .fa-2x {
30 | font-size: 2em;
31 | }
32 | .fa-3x {
33 | font-size: 3em;
34 | }
35 | .fa-4x {
36 | font-size: 4em;
37 | }
38 | .fa-5x {
39 | font-size: 5em;
40 | }
41 | .fa-fw {
42 | width: 1.2857142857142858em;
43 | text-align: center;
44 | }
45 | .fa-ul {
46 | padding-left: 0;
47 | margin-left: 2.142857142857143em;
48 | list-style-type: none;
49 | }
50 | .fa-ul > li {
51 | position: relative;
52 | }
53 | .fa-li {
54 | position: absolute;
55 | left: -2.142857142857143em;
56 | width: 2.142857142857143em;
57 | top: 0.14285714285714285em;
58 | text-align: center;
59 | }
60 | .fa-li.fa-lg {
61 | left: -1.8571428571428572em;
62 | }
63 | .fa-border {
64 | padding: .2em .25em .15em;
65 | border: solid 0.08em #eeeeee;
66 | border-radius: .1em;
67 | }
68 | .pull-right {
69 | float: right;
70 | }
71 | .pull-left {
72 | float: left;
73 | }
74 | .fa.pull-left {
75 | margin-right: .3em;
76 | }
77 | .fa.pull-right {
78 | margin-left: .3em;
79 | }
80 | .fa-spin {
81 | -webkit-animation: spin 2s infinite linear;
82 | -moz-animation: spin 2s infinite linear;
83 | -o-animation: spin 2s infinite linear;
84 | animation: spin 2s infinite linear;
85 | }
86 | @-moz-keyframes spin {
87 | 0% {
88 | -moz-transform: rotate(0deg);
89 | }
90 | 100% {
91 | -moz-transform: rotate(359deg);
92 | }
93 | }
94 | @-webkit-keyframes spin {
95 | 0% {
96 | -webkit-transform: rotate(0deg);
97 | }
98 | 100% {
99 | -webkit-transform: rotate(359deg);
100 | }
101 | }
102 | @-o-keyframes spin {
103 | 0% {
104 | -o-transform: rotate(0deg);
105 | }
106 | 100% {
107 | -o-transform: rotate(359deg);
108 | }
109 | }
110 | @-ms-keyframes spin {
111 | 0% {
112 | -ms-transform: rotate(0deg);
113 | }
114 | 100% {
115 | -ms-transform: rotate(359deg);
116 | }
117 | }
118 | @keyframes spin {
119 | 0% {
120 | transform: rotate(0deg);
121 | }
122 | 100% {
123 | transform: rotate(359deg);
124 | }
125 | }
126 | .fa-rotate-90 {
127 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
128 | -webkit-transform: rotate(90deg);
129 | -moz-transform: rotate(90deg);
130 | -ms-transform: rotate(90deg);
131 | -o-transform: rotate(90deg);
132 | transform: rotate(90deg);
133 | }
134 | .fa-rotate-180 {
135 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
136 | -webkit-transform: rotate(180deg);
137 | -moz-transform: rotate(180deg);
138 | -ms-transform: rotate(180deg);
139 | -o-transform: rotate(180deg);
140 | transform: rotate(180deg);
141 | }
142 | .fa-rotate-270 {
143 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
144 | -webkit-transform: rotate(270deg);
145 | -moz-transform: rotate(270deg);
146 | -ms-transform: rotate(270deg);
147 | -o-transform: rotate(270deg);
148 | transform: rotate(270deg);
149 | }
150 | .fa-flip-horizontal {
151 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
152 | -webkit-transform: scale(-1, 1);
153 | -moz-transform: scale(-1, 1);
154 | -ms-transform: scale(-1, 1);
155 | -o-transform: scale(-1, 1);
156 | transform: scale(-1, 1);
157 | }
158 | .fa-flip-vertical {
159 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
160 | -webkit-transform: scale(1, -1);
161 | -moz-transform: scale(1, -1);
162 | -ms-transform: scale(1, -1);
163 | -o-transform: scale(1, -1);
164 | transform: scale(1, -1);
165 | }
166 | .fa-stack {
167 | position: relative;
168 | display: inline-block;
169 | width: 2em;
170 | height: 2em;
171 | line-height: 2em;
172 | vertical-align: middle;
173 | }
174 | .fa-stack-1x,
175 | .fa-stack-2x {
176 | position: absolute;
177 | left: 0;
178 | width: 100%;
179 | text-align: center;
180 | }
181 | .fa-stack-1x {
182 | line-height: inherit;
183 | }
184 | .fa-stack-2x {
185 | font-size: 2em;
186 | }
187 | .fa-inverse {
188 | color: #ffffff;
189 | }
190 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
191 | readers do not read off random characters that represent icons */
192 | .fa-glass:before {
193 | content: "\f000";
194 | }
195 | .fa-music:before {
196 | content: "\f001";
197 | }
198 | .fa-search:before {
199 | content: "\f002";
200 | }
201 | .fa-envelope-o:before {
202 | content: "\f003";
203 | }
204 | .fa-heart:before {
205 | content: "\f004";
206 | }
207 | .fa-star:before {
208 | content: "\f005";
209 | }
210 | .fa-star-o:before {
211 | content: "\f006";
212 | }
213 | .fa-user:before {
214 | content: "\f007";
215 | }
216 | .fa-film:before {
217 | content: "\f008";
218 | }
219 | .fa-th-large:before {
220 | content: "\f009";
221 | }
222 | .fa-th:before {
223 | content: "\f00a";
224 | }
225 | .fa-th-list:before {
226 | content: "\f00b";
227 | }
228 | .fa-check:before {
229 | content: "\f00c";
230 | }
231 | .fa-times:before {
232 | content: "\f00d";
233 | }
234 | .fa-search-plus:before {
235 | content: "\f00e";
236 | }
237 | .fa-search-minus:before {
238 | content: "\f010";
239 | }
240 | .fa-power-off:before {
241 | content: "\f011";
242 | }
243 | .fa-signal:before {
244 | content: "\f012";
245 | }
246 | .fa-gear:before,
247 | .fa-cog:before {
248 | content: "\f013";
249 | }
250 | .fa-trash-o:before {
251 | content: "\f014";
252 | }
253 | .fa-home:before {
254 | content: "\f015";
255 | }
256 | .fa-file-o:before {
257 | content: "\f016";
258 | }
259 | .fa-clock-o:before {
260 | content: "\f017";
261 | }
262 | .fa-road:before {
263 | content: "\f018";
264 | }
265 | .fa-download:before {
266 | content: "\f019";
267 | }
268 | .fa-arrow-circle-o-down:before {
269 | content: "\f01a";
270 | }
271 | .fa-arrow-circle-o-up:before {
272 | content: "\f01b";
273 | }
274 | .fa-inbox:before {
275 | content: "\f01c";
276 | }
277 | .fa-play-circle-o:before {
278 | content: "\f01d";
279 | }
280 | .fa-rotate-right:before,
281 | .fa-repeat:before {
282 | content: "\f01e";
283 | }
284 | .fa-refresh:before {
285 | content: "\f021";
286 | }
287 | .fa-list-alt:before {
288 | content: "\f022";
289 | }
290 | .fa-lock:before {
291 | content: "\f023";
292 | }
293 | .fa-flag:before {
294 | content: "\f024";
295 | }
296 | .fa-headphones:before {
297 | content: "\f025";
298 | }
299 | .fa-volume-off:before {
300 | content: "\f026";
301 | }
302 | .fa-volume-down:before {
303 | content: "\f027";
304 | }
305 | .fa-volume-up:before {
306 | content: "\f028";
307 | }
308 | .fa-qrcode:before {
309 | content: "\f029";
310 | }
311 | .fa-barcode:before {
312 | content: "\f02a";
313 | }
314 | .fa-tag:before {
315 | content: "\f02b";
316 | }
317 | .fa-tags:before {
318 | content: "\f02c";
319 | }
320 | .fa-book:before {
321 | content: "\f02d";
322 | }
323 | .fa-bookmark:before {
324 | content: "\f02e";
325 | }
326 | .fa-print:before {
327 | content: "\f02f";
328 | }
329 | .fa-camera:before {
330 | content: "\f030";
331 | }
332 | .fa-font:before {
333 | content: "\f031";
334 | }
335 | .fa-bold:before {
336 | content: "\f032";
337 | }
338 | .fa-italic:before {
339 | content: "\f033";
340 | }
341 | .fa-text-height:before {
342 | content: "\f034";
343 | }
344 | .fa-text-width:before {
345 | content: "\f035";
346 | }
347 | .fa-align-left:before {
348 | content: "\f036";
349 | }
350 | .fa-align-center:before {
351 | content: "\f037";
352 | }
353 | .fa-align-right:before {
354 | content: "\f038";
355 | }
356 | .fa-align-justify:before {
357 | content: "\f039";
358 | }
359 | .fa-list:before {
360 | content: "\f03a";
361 | }
362 | .fa-dedent:before,
363 | .fa-outdent:before {
364 | content: "\f03b";
365 | }
366 | .fa-indent:before {
367 | content: "\f03c";
368 | }
369 | .fa-video-camera:before {
370 | content: "\f03d";
371 | }
372 | .fa-picture-o:before {
373 | content: "\f03e";
374 | }
375 | .fa-pencil:before {
376 | content: "\f040";
377 | }
378 | .fa-map-marker:before {
379 | content: "\f041";
380 | }
381 | .fa-adjust:before {
382 | content: "\f042";
383 | }
384 | .fa-tint:before {
385 | content: "\f043";
386 | }
387 | .fa-edit:before,
388 | .fa-pencil-square-o:before {
389 | content: "\f044";
390 | }
391 | .fa-share-square-o:before {
392 | content: "\f045";
393 | }
394 | .fa-check-square-o:before {
395 | content: "\f046";
396 | }
397 | .fa-arrows:before {
398 | content: "\f047";
399 | }
400 | .fa-step-backward:before {
401 | content: "\f048";
402 | }
403 | .fa-fast-backward:before {
404 | content: "\f049";
405 | }
406 | .fa-backward:before {
407 | content: "\f04a";
408 | }
409 | .fa-play:before {
410 | content: "\f04b";
411 | }
412 | .fa-pause:before {
413 | content: "\f04c";
414 | }
415 | .fa-stop:before {
416 | content: "\f04d";
417 | }
418 | .fa-forward:before {
419 | content: "\f04e";
420 | }
421 | .fa-fast-forward:before {
422 | content: "\f050";
423 | }
424 | .fa-step-forward:before {
425 | content: "\f051";
426 | }
427 | .fa-eject:before {
428 | content: "\f052";
429 | }
430 | .fa-chevron-left:before {
431 | content: "\f053";
432 | }
433 | .fa-chevron-right:before {
434 | content: "\f054";
435 | }
436 | .fa-plus-circle:before {
437 | content: "\f055";
438 | }
439 | .fa-minus-circle:before {
440 | content: "\f056";
441 | }
442 | .fa-times-circle:before {
443 | content: "\f057";
444 | }
445 | .fa-check-circle:before {
446 | content: "\f058";
447 | }
448 | .fa-question-circle:before {
449 | content: "\f059";
450 | }
451 | .fa-info-circle:before {
452 | content: "\f05a";
453 | }
454 | .fa-crosshairs:before {
455 | content: "\f05b";
456 | }
457 | .fa-times-circle-o:before {
458 | content: "\f05c";
459 | }
460 | .fa-check-circle-o:before {
461 | content: "\f05d";
462 | }
463 | .fa-ban:before {
464 | content: "\f05e";
465 | }
466 | .fa-arrow-left:before {
467 | content: "\f060";
468 | }
469 | .fa-arrow-right:before {
470 | content: "\f061";
471 | }
472 | .fa-arrow-up:before {
473 | content: "\f062";
474 | }
475 | .fa-arrow-down:before {
476 | content: "\f063";
477 | }
478 | .fa-mail-forward:before,
479 | .fa-share:before {
480 | content: "\f064";
481 | }
482 | .fa-expand:before {
483 | content: "\f065";
484 | }
485 | .fa-compress:before {
486 | content: "\f066";
487 | }
488 | .fa-plus:before {
489 | content: "\f067";
490 | }
491 | .fa-minus:before {
492 | content: "\f068";
493 | }
494 | .fa-asterisk:before {
495 | content: "\f069";
496 | }
497 | .fa-exclamation-circle:before {
498 | content: "\f06a";
499 | }
500 | .fa-gift:before {
501 | content: "\f06b";
502 | }
503 | .fa-leaf:before {
504 | content: "\f06c";
505 | }
506 | .fa-fire:before {
507 | content: "\f06d";
508 | }
509 | .fa-eye:before {
510 | content: "\f06e";
511 | }
512 | .fa-eye-slash:before {
513 | content: "\f070";
514 | }
515 | .fa-warning:before,
516 | .fa-exclamation-triangle:before {
517 | content: "\f071";
518 | }
519 | .fa-plane:before {
520 | content: "\f072";
521 | }
522 | .fa-calendar:before {
523 | content: "\f073";
524 | }
525 | .fa-random:before {
526 | content: "\f074";
527 | }
528 | .fa-comment:before {
529 | content: "\f075";
530 | }
531 | .fa-magnet:before {
532 | content: "\f076";
533 | }
534 | .fa-chevron-up:before {
535 | content: "\f077";
536 | }
537 | .fa-chevron-down:before {
538 | content: "\f078";
539 | }
540 | .fa-retweet:before {
541 | content: "\f079";
542 | }
543 | .fa-shopping-cart:before {
544 | content: "\f07a";
545 | }
546 | .fa-folder:before {
547 | content: "\f07b";
548 | }
549 | .fa-folder-open:before {
550 | content: "\f07c";
551 | }
552 | .fa-arrows-v:before {
553 | content: "\f07d";
554 | }
555 | .fa-arrows-h:before {
556 | content: "\f07e";
557 | }
558 | .fa-bar-chart-o:before {
559 | content: "\f080";
560 | }
561 | .fa-twitter-square:before {
562 | content: "\f081";
563 | }
564 | .fa-facebook-square:before {
565 | content: "\f082";
566 | }
567 | .fa-camera-retro:before {
568 | content: "\f083";
569 | }
570 | .fa-key:before {
571 | content: "\f084";
572 | }
573 | .fa-gears:before,
574 | .fa-cogs:before {
575 | content: "\f085";
576 | }
577 | .fa-comments:before {
578 | content: "\f086";
579 | }
580 | .fa-thumbs-o-up:before {
581 | content: "\f087";
582 | }
583 | .fa-thumbs-o-down:before {
584 | content: "\f088";
585 | }
586 | .fa-star-half:before {
587 | content: "\f089";
588 | }
589 | .fa-heart-o:before {
590 | content: "\f08a";
591 | }
592 | .fa-sign-out:before {
593 | content: "\f08b";
594 | }
595 | .fa-linkedin-square:before {
596 | content: "\f08c";
597 | }
598 | .fa-thumb-tack:before {
599 | content: "\f08d";
600 | }
601 | .fa-external-link:before {
602 | content: "\f08e";
603 | }
604 | .fa-sign-in:before {
605 | content: "\f090";
606 | }
607 | .fa-trophy:before {
608 | content: "\f091";
609 | }
610 | .fa-github-square:before {
611 | content: "\f092";
612 | }
613 | .fa-upload:before {
614 | content: "\f093";
615 | }
616 | .fa-lemon-o:before {
617 | content: "\f094";
618 | }
619 | .fa-phone:before {
620 | content: "\f095";
621 | }
622 | .fa-square-o:before {
623 | content: "\f096";
624 | }
625 | .fa-bookmark-o:before {
626 | content: "\f097";
627 | }
628 | .fa-phone-square:before {
629 | content: "\f098";
630 | }
631 | .fa-twitter:before {
632 | content: "\f099";
633 | }
634 | .fa-facebook:before {
635 | content: "\f09a";
636 | }
637 | .fa-github:before {
638 | content: "\f09b";
639 | }
640 | .fa-unlock:before {
641 | content: "\f09c";
642 | }
643 | .fa-credit-card:before {
644 | content: "\f09d";
645 | }
646 | .fa-rss:before {
647 | content: "\f09e";
648 | }
649 | .fa-hdd-o:before {
650 | content: "\f0a0";
651 | }
652 | .fa-bullhorn:before {
653 | content: "\f0a1";
654 | }
655 | .fa-bell:before {
656 | content: "\f0f3";
657 | }
658 | .fa-certificate:before {
659 | content: "\f0a3";
660 | }
661 | .fa-hand-o-right:before {
662 | content: "\f0a4";
663 | }
664 | .fa-hand-o-left:before {
665 | content: "\f0a5";
666 | }
667 | .fa-hand-o-up:before {
668 | content: "\f0a6";
669 | }
670 | .fa-hand-o-down:before {
671 | content: "\f0a7";
672 | }
673 | .fa-arrow-circle-left:before {
674 | content: "\f0a8";
675 | }
676 | .fa-arrow-circle-right:before {
677 | content: "\f0a9";
678 | }
679 | .fa-arrow-circle-up:before {
680 | content: "\f0aa";
681 | }
682 | .fa-arrow-circle-down:before {
683 | content: "\f0ab";
684 | }
685 | .fa-globe:before {
686 | content: "\f0ac";
687 | }
688 | .fa-wrench:before {
689 | content: "\f0ad";
690 | }
691 | .fa-tasks:before {
692 | content: "\f0ae";
693 | }
694 | .fa-filter:before {
695 | content: "\f0b0";
696 | }
697 | .fa-briefcase:before {
698 | content: "\f0b1";
699 | }
700 | .fa-arrows-alt:before {
701 | content: "\f0b2";
702 | }
703 | .fa-group:before,
704 | .fa-users:before {
705 | content: "\f0c0";
706 | }
707 | .fa-chain:before,
708 | .fa-link:before {
709 | content: "\f0c1";
710 | }
711 | .fa-cloud:before {
712 | content: "\f0c2";
713 | }
714 | .fa-flask:before {
715 | content: "\f0c3";
716 | }
717 | .fa-cut:before,
718 | .fa-scissors:before {
719 | content: "\f0c4";
720 | }
721 | .fa-copy:before,
722 | .fa-files-o:before {
723 | content: "\f0c5";
724 | }
725 | .fa-paperclip:before {
726 | content: "\f0c6";
727 | }
728 | .fa-save:before,
729 | .fa-floppy-o:before {
730 | content: "\f0c7";
731 | }
732 | .fa-square:before {
733 | content: "\f0c8";
734 | }
735 | .fa-bars:before {
736 | content: "\f0c9";
737 | }
738 | .fa-list-ul:before {
739 | content: "\f0ca";
740 | }
741 | .fa-list-ol:before {
742 | content: "\f0cb";
743 | }
744 | .fa-strikethrough:before {
745 | content: "\f0cc";
746 | }
747 | .fa-underline:before {
748 | content: "\f0cd";
749 | }
750 | .fa-table:before {
751 | content: "\f0ce";
752 | }
753 | .fa-magic:before {
754 | content: "\f0d0";
755 | }
756 | .fa-truck:before {
757 | content: "\f0d1";
758 | }
759 | .fa-pinterest:before {
760 | content: "\f0d2";
761 | }
762 | .fa-pinterest-square:before {
763 | content: "\f0d3";
764 | }
765 | .fa-google-plus-square:before {
766 | content: "\f0d4";
767 | }
768 | .fa-google-plus:before {
769 | content: "\f0d5";
770 | }
771 | .fa-money:before {
772 | content: "\f0d6";
773 | }
774 | .fa-caret-down:before {
775 | content: "\f0d7";
776 | }
777 | .fa-caret-up:before {
778 | content: "\f0d8";
779 | }
780 | .fa-caret-left:before {
781 | content: "\f0d9";
782 | }
783 | .fa-caret-right:before {
784 | content: "\f0da";
785 | }
786 | .fa-columns:before {
787 | content: "\f0db";
788 | }
789 | .fa-unsorted:before,
790 | .fa-sort:before {
791 | content: "\f0dc";
792 | }
793 | .fa-sort-down:before,
794 | .fa-sort-asc:before {
795 | content: "\f0dd";
796 | }
797 | .fa-sort-up:before,
798 | .fa-sort-desc:before {
799 | content: "\f0de";
800 | }
801 | .fa-envelope:before {
802 | content: "\f0e0";
803 | }
804 | .fa-linkedin:before {
805 | content: "\f0e1";
806 | }
807 | .fa-rotate-left:before,
808 | .fa-undo:before {
809 | content: "\f0e2";
810 | }
811 | .fa-legal:before,
812 | .fa-gavel:before {
813 | content: "\f0e3";
814 | }
815 | .fa-dashboard:before,
816 | .fa-tachometer:before {
817 | content: "\f0e4";
818 | }
819 | .fa-comment-o:before {
820 | content: "\f0e5";
821 | }
822 | .fa-comments-o:before {
823 | content: "\f0e6";
824 | }
825 | .fa-flash:before,
826 | .fa-bolt:before {
827 | content: "\f0e7";
828 | }
829 | .fa-sitemap:before {
830 | content: "\f0e8";
831 | }
832 | .fa-umbrella:before {
833 | content: "\f0e9";
834 | }
835 | .fa-paste:before,
836 | .fa-clipboard:before {
837 | content: "\f0ea";
838 | }
839 | .fa-lightbulb-o:before {
840 | content: "\f0eb";
841 | }
842 | .fa-exchange:before {
843 | content: "\f0ec";
844 | }
845 | .fa-cloud-download:before {
846 | content: "\f0ed";
847 | }
848 | .fa-cloud-upload:before {
849 | content: "\f0ee";
850 | }
851 | .fa-user-md:before {
852 | content: "\f0f0";
853 | }
854 | .fa-stethoscope:before {
855 | content: "\f0f1";
856 | }
857 | .fa-suitcase:before {
858 | content: "\f0f2";
859 | }
860 | .fa-bell-o:before {
861 | content: "\f0a2";
862 | }
863 | .fa-coffee:before {
864 | content: "\f0f4";
865 | }
866 | .fa-cutlery:before {
867 | content: "\f0f5";
868 | }
869 | .fa-file-text-o:before {
870 | content: "\f0f6";
871 | }
872 | .fa-building-o:before {
873 | content: "\f0f7";
874 | }
875 | .fa-hospital-o:before {
876 | content: "\f0f8";
877 | }
878 | .fa-ambulance:before {
879 | content: "\f0f9";
880 | }
881 | .fa-medkit:before {
882 | content: "\f0fa";
883 | }
884 | .fa-fighter-jet:before {
885 | content: "\f0fb";
886 | }
887 | .fa-beer:before {
888 | content: "\f0fc";
889 | }
890 | .fa-h-square:before {
891 | content: "\f0fd";
892 | }
893 | .fa-plus-square:before {
894 | content: "\f0fe";
895 | }
896 | .fa-angle-double-left:before {
897 | content: "\f100";
898 | }
899 | .fa-angle-double-right:before {
900 | content: "\f101";
901 | }
902 | .fa-angle-double-up:before {
903 | content: "\f102";
904 | }
905 | .fa-angle-double-down:before {
906 | content: "\f103";
907 | }
908 | .fa-angle-left:before {
909 | content: "\f104";
910 | }
911 | .fa-angle-right:before {
912 | content: "\f105";
913 | }
914 | .fa-angle-up:before {
915 | content: "\f106";
916 | }
917 | .fa-angle-down:before {
918 | content: "\f107";
919 | }
920 | .fa-desktop:before {
921 | content: "\f108";
922 | }
923 | .fa-laptop:before {
924 | content: "\f109";
925 | }
926 | .fa-tablet:before {
927 | content: "\f10a";
928 | }
929 | .fa-mobile-phone:before,
930 | .fa-mobile:before {
931 | content: "\f10b";
932 | }
933 | .fa-circle-o:before {
934 | content: "\f10c";
935 | }
936 | .fa-quote-left:before {
937 | content: "\f10d";
938 | }
939 | .fa-quote-right:before {
940 | content: "\f10e";
941 | }
942 | .fa-spinner:before {
943 | content: "\f110";
944 | }
945 | .fa-circle:before {
946 | content: "\f111";
947 | }
948 | .fa-mail-reply:before,
949 | .fa-reply:before {
950 | content: "\f112";
951 | }
952 | .fa-github-alt:before {
953 | content: "\f113";
954 | }
955 | .fa-folder-o:before {
956 | content: "\f114";
957 | }
958 | .fa-folder-open-o:before {
959 | content: "\f115";
960 | }
961 | .fa-smile-o:before {
962 | content: "\f118";
963 | }
964 | .fa-frown-o:before {
965 | content: "\f119";
966 | }
967 | .fa-meh-o:before {
968 | content: "\f11a";
969 | }
970 | .fa-gamepad:before {
971 | content: "\f11b";
972 | }
973 | .fa-keyboard-o:before {
974 | content: "\f11c";
975 | }
976 | .fa-flag-o:before {
977 | content: "\f11d";
978 | }
979 | .fa-flag-checkered:before {
980 | content: "\f11e";
981 | }
982 | .fa-terminal:before {
983 | content: "\f120";
984 | }
985 | .fa-code:before {
986 | content: "\f121";
987 | }
988 | .fa-reply-all:before {
989 | content: "\f122";
990 | }
991 | .fa-mail-reply-all:before {
992 | content: "\f122";
993 | }
994 | .fa-star-half-empty:before,
995 | .fa-star-half-full:before,
996 | .fa-star-half-o:before {
997 | content: "\f123";
998 | }
999 | .fa-location-arrow:before {
1000 | content: "\f124";
1001 | }
1002 | .fa-crop:before {
1003 | content: "\f125";
1004 | }
1005 | .fa-code-fork:before {
1006 | content: "\f126";
1007 | }
1008 | .fa-unlink:before,
1009 | .fa-chain-broken:before {
1010 | content: "\f127";
1011 | }
1012 | .fa-question:before {
1013 | content: "\f128";
1014 | }
1015 | .fa-info:before {
1016 | content: "\f129";
1017 | }
1018 | .fa-exclamation:before {
1019 | content: "\f12a";
1020 | }
1021 | .fa-superscript:before {
1022 | content: "\f12b";
1023 | }
1024 | .fa-subscript:before {
1025 | content: "\f12c";
1026 | }
1027 | .fa-eraser:before {
1028 | content: "\f12d";
1029 | }
1030 | .fa-puzzle-piece:before {
1031 | content: "\f12e";
1032 | }
1033 | .fa-microphone:before {
1034 | content: "\f130";
1035 | }
1036 | .fa-microphone-slash:before {
1037 | content: "\f131";
1038 | }
1039 | .fa-shield:before {
1040 | content: "\f132";
1041 | }
1042 | .fa-calendar-o:before {
1043 | content: "\f133";
1044 | }
1045 | .fa-fire-extinguisher:before {
1046 | content: "\f134";
1047 | }
1048 | .fa-rocket:before {
1049 | content: "\f135";
1050 | }
1051 | .fa-maxcdn:before {
1052 | content: "\f136";
1053 | }
1054 | .fa-chevron-circle-left:before {
1055 | content: "\f137";
1056 | }
1057 | .fa-chevron-circle-right:before {
1058 | content: "\f138";
1059 | }
1060 | .fa-chevron-circle-up:before {
1061 | content: "\f139";
1062 | }
1063 | .fa-chevron-circle-down:before {
1064 | content: "\f13a";
1065 | }
1066 | .fa-html5:before {
1067 | content: "\f13b";
1068 | }
1069 | .fa-css3:before {
1070 | content: "\f13c";
1071 | }
1072 | .fa-anchor:before {
1073 | content: "\f13d";
1074 | }
1075 | .fa-unlock-alt:before {
1076 | content: "\f13e";
1077 | }
1078 | .fa-bullseye:before {
1079 | content: "\f140";
1080 | }
1081 | .fa-ellipsis-h:before {
1082 | content: "\f141";
1083 | }
1084 | .fa-ellipsis-v:before {
1085 | content: "\f142";
1086 | }
1087 | .fa-rss-square:before {
1088 | content: "\f143";
1089 | }
1090 | .fa-play-circle:before {
1091 | content: "\f144";
1092 | }
1093 | .fa-ticket:before {
1094 | content: "\f145";
1095 | }
1096 | .fa-minus-square:before {
1097 | content: "\f146";
1098 | }
1099 | .fa-minus-square-o:before {
1100 | content: "\f147";
1101 | }
1102 | .fa-level-up:before {
1103 | content: "\f148";
1104 | }
1105 | .fa-level-down:before {
1106 | content: "\f149";
1107 | }
1108 | .fa-check-square:before {
1109 | content: "\f14a";
1110 | }
1111 | .fa-pencil-square:before {
1112 | content: "\f14b";
1113 | }
1114 | .fa-external-link-square:before {
1115 | content: "\f14c";
1116 | }
1117 | .fa-share-square:before {
1118 | content: "\f14d";
1119 | }
1120 | .fa-compass:before {
1121 | content: "\f14e";
1122 | }
1123 | .fa-toggle-down:before,
1124 | .fa-caret-square-o-down:before {
1125 | content: "\f150";
1126 | }
1127 | .fa-toggle-up:before,
1128 | .fa-caret-square-o-up:before {
1129 | content: "\f151";
1130 | }
1131 | .fa-toggle-right:before,
1132 | .fa-caret-square-o-right:before {
1133 | content: "\f152";
1134 | }
1135 | .fa-euro:before,
1136 | .fa-eur:before {
1137 | content: "\f153";
1138 | }
1139 | .fa-gbp:before {
1140 | content: "\f154";
1141 | }
1142 | .fa-dollar:before,
1143 | .fa-usd:before {
1144 | content: "\f155";
1145 | }
1146 | .fa-rupee:before,
1147 | .fa-inr:before {
1148 | content: "\f156";
1149 | }
1150 | .fa-cny:before,
1151 | .fa-rmb:before,
1152 | .fa-yen:before,
1153 | .fa-jpy:before {
1154 | content: "\f157";
1155 | }
1156 | .fa-ruble:before,
1157 | .fa-rouble:before,
1158 | .fa-rub:before {
1159 | content: "\f158";
1160 | }
1161 | .fa-won:before,
1162 | .fa-krw:before {
1163 | content: "\f159";
1164 | }
1165 | .fa-bitcoin:before,
1166 | .fa-btc:before {
1167 | content: "\f15a";
1168 | }
1169 | .fa-file:before {
1170 | content: "\f15b";
1171 | }
1172 | .fa-file-text:before {
1173 | content: "\f15c";
1174 | }
1175 | .fa-sort-alpha-asc:before {
1176 | content: "\f15d";
1177 | }
1178 | .fa-sort-alpha-desc:before {
1179 | content: "\f15e";
1180 | }
1181 | .fa-sort-amount-asc:before {
1182 | content: "\f160";
1183 | }
1184 | .fa-sort-amount-desc:before {
1185 | content: "\f161";
1186 | }
1187 | .fa-sort-numeric-asc:before {
1188 | content: "\f162";
1189 | }
1190 | .fa-sort-numeric-desc:before {
1191 | content: "\f163";
1192 | }
1193 | .fa-thumbs-up:before {
1194 | content: "\f164";
1195 | }
1196 | .fa-thumbs-down:before {
1197 | content: "\f165";
1198 | }
1199 | .fa-youtube-square:before {
1200 | content: "\f166";
1201 | }
1202 | .fa-youtube:before {
1203 | content: "\f167";
1204 | }
1205 | .fa-xing:before {
1206 | content: "\f168";
1207 | }
1208 | .fa-xing-square:before {
1209 | content: "\f169";
1210 | }
1211 | .fa-youtube-play:before {
1212 | content: "\f16a";
1213 | }
1214 | .fa-dropbox:before {
1215 | content: "\f16b";
1216 | }
1217 | .fa-stack-overflow:before {
1218 | content: "\f16c";
1219 | }
1220 | .fa-instagram:before {
1221 | content: "\f16d";
1222 | }
1223 | .fa-flickr:before {
1224 | content: "\f16e";
1225 | }
1226 | .fa-adn:before {
1227 | content: "\f170";
1228 | }
1229 | .fa-bitbucket:before {
1230 | content: "\f171";
1231 | }
1232 | .fa-bitbucket-square:before {
1233 | content: "\f172";
1234 | }
1235 | .fa-tumblr:before {
1236 | content: "\f173";
1237 | }
1238 | .fa-tumblr-square:before {
1239 | content: "\f174";
1240 | }
1241 | .fa-long-arrow-down:before {
1242 | content: "\f175";
1243 | }
1244 | .fa-long-arrow-up:before {
1245 | content: "\f176";
1246 | }
1247 | .fa-long-arrow-left:before {
1248 | content: "\f177";
1249 | }
1250 | .fa-long-arrow-right:before {
1251 | content: "\f178";
1252 | }
1253 | .fa-apple:before {
1254 | content: "\f179";
1255 | }
1256 | .fa-windows:before {
1257 | content: "\f17a";
1258 | }
1259 | .fa-android:before {
1260 | content: "\f17b";
1261 | }
1262 | .fa-linux:before {
1263 | content: "\f17c";
1264 | }
1265 | .fa-dribbble:before {
1266 | content: "\f17d";
1267 | }
1268 | .fa-skype:before {
1269 | content: "\f17e";
1270 | }
1271 | .fa-foursquare:before {
1272 | content: "\f180";
1273 | }
1274 | .fa-trello:before {
1275 | content: "\f181";
1276 | }
1277 | .fa-female:before {
1278 | content: "\f182";
1279 | }
1280 | .fa-male:before {
1281 | content: "\f183";
1282 | }
1283 | .fa-gittip:before {
1284 | content: "\f184";
1285 | }
1286 | .fa-sun-o:before {
1287 | content: "\f185";
1288 | }
1289 | .fa-moon-o:before {
1290 | content: "\f186";
1291 | }
1292 | .fa-archive:before {
1293 | content: "\f187";
1294 | }
1295 | .fa-bug:before {
1296 | content: "\f188";
1297 | }
1298 | .fa-vk:before {
1299 | content: "\f189";
1300 | }
1301 | .fa-weibo:before {
1302 | content: "\f18a";
1303 | }
1304 | .fa-renren:before {
1305 | content: "\f18b";
1306 | }
1307 | .fa-pagelines:before {
1308 | content: "\f18c";
1309 | }
1310 | .fa-stack-exchange:before {
1311 | content: "\f18d";
1312 | }
1313 | .fa-arrow-circle-o-right:before {
1314 | content: "\f18e";
1315 | }
1316 | .fa-arrow-circle-o-left:before {
1317 | content: "\f190";
1318 | }
1319 | .fa-toggle-left:before,
1320 | .fa-caret-square-o-left:before {
1321 | content: "\f191";
1322 | }
1323 | .fa-dot-circle-o:before {
1324 | content: "\f192";
1325 | }
1326 | .fa-wheelchair:before {
1327 | content: "\f193";
1328 | }
1329 | .fa-vimeo-square:before {
1330 | content: "\f194";
1331 | }
1332 | .fa-turkish-lira:before,
1333 | .fa-try:before {
1334 | content: "\f195";
1335 | }
1336 | .fa-plus-square-o:before {
1337 | content: "\f196";
1338 | }
1339 |
--------------------------------------------------------------------------------