Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_22812535
incubator-superset
提交
0a3b1212
I
incubator-superset
项目概览
qq_22812535
/
incubator-superset
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
incubator-superset
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
0a3b1212
编写于
10月 29, 2019
作者:
J
John Bodley
提交者:
GitHub
10月 29, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[sql] Fixing datetime SQL literal (#8464)
上级
7afda6e4
变更
33
隐藏空白更改
内联
并排
Showing
33 changed file
with
433 addition
and
79 deletion
+433
-79
superset/connectors/sqla/models.py
superset/connectors/sqla/models.py
+17
-9
superset/db_engine_specs/athena.py
superset/db_engine_specs/athena.py
+5
-4
superset/db_engine_specs/base.py
superset/db_engine_specs/base.py
+6
-6
superset/db_engine_specs/bigquery.py
superset/db_engine_specs/bigquery.py
+8
-4
superset/db_engine_specs/clickhouse.py
superset/db_engine_specs/clickhouse.py
+5
-4
superset/db_engine_specs/db2.py
superset/db_engine_specs/db2.py
+0
-6
superset/db_engine_specs/drill.py
superset/db_engine_specs/drill.py
+5
-4
superset/db_engine_specs/elasticsearch.py
superset/db_engine_specs/elasticsearch.py
+5
-5
superset/db_engine_specs/hive.py
superset/db_engine_specs/hive.py
+4
-4
superset/db_engine_specs/impala.py
superset/db_engine_specs/impala.py
+6
-4
superset/db_engine_specs/kylin.py
superset/db_engine_specs/kylin.py
+5
-4
superset/db_engine_specs/mssql.py
superset/db_engine_specs/mssql.py
+9
-2
superset/db_engine_specs/mysql.py
superset/db_engine_specs/mysql.py
+7
-6
superset/db_engine_specs/oracle.py
superset/db_engine_specs/oracle.py
+8
-4
superset/db_engine_specs/postgres.py
superset/db_engine_specs/postgres.py
+9
-4
superset/db_engine_specs/presto.py
superset/db_engine_specs/presto.py
+4
-4
superset/db_engine_specs/sqlite.py
superset/db_engine_specs/sqlite.py
+4
-5
tests/db_engine_specs/athena_tests.py
tests/db_engine_specs/athena_tests.py
+33
-0
tests/db_engine_specs/base_engine_spec_tests.py
tests/db_engine_specs/base_engine_spec_tests.py
+4
-0
tests/db_engine_specs/base_tests.py
tests/db_engine_specs/base_tests.py
+5
-0
tests/db_engine_specs/bigquery_tests.py
tests/db_engine_specs/bigquery_tests.py
+17
-0
tests/db_engine_specs/clickhouse_tests.py
tests/db_engine_specs/clickhouse_tests.py
+32
-0
tests/db_engine_specs/drill_tests.py
tests/db_engine_specs/drill_tests.py
+33
-0
tests/db_engine_specs/elasticsearch_tests.py
tests/db_engine_specs/elasticsearch_tests.py
+28
-0
tests/db_engine_specs/hive_tests.py
tests/db_engine_specs/hive_tests.py
+12
-0
tests/db_engine_specs/impala_tests.py
tests/db_engine_specs/impala_tests.py
+32
-0
tests/db_engine_specs/kylin_tests.py
tests/db_engine_specs/kylin_tests.py
+32
-0
tests/db_engine_specs/mssql_tests.py
tests/db_engine_specs/mssql_tests.py
+18
-0
tests/db_engine_specs/mysql_tests.py
tests/db_engine_specs/mysql_tests.py
+13
-0
tests/db_engine_specs/oracle_tests.py
tests/db_engine_specs/oracle_tests.py
+14
-0
tests/db_engine_specs/postgres_tests.py
tests/db_engine_specs/postgres_tests.py
+13
-0
tests/db_engine_specs/presto_tests.py
tests/db_engine_specs/presto_tests.py
+13
-0
tests/db_engine_specs/sqlite_tests.py
tests/db_engine_specs/sqlite_tests.py
+27
-0
未找到文件。
superset/connectors/sqla/models.py
浏览文件 @
0a3b1212
...
...
@@ -220,19 +220,27 @@ class TableColumn(Model, BaseColumn):
def
dttm_sql_literal
(
self
,
dttm
:
DateTime
)
->
str
:
"""Convert datetime object to a SQL expression string"""
sql
=
(
self
.
table
.
database
.
db_engine_spec
.
convert_dttm
(
self
.
type
,
dttm
)
if
self
.
type
else
None
)
if
sql
:
return
sql
tf
=
self
.
python_date_format
if
tf
:
seconds_since_epoch
=
int
(
dttm
.
timestamp
())
if
tf
==
"epoch_s"
:
return
str
(
seconds_since_epoch
)
elif
tf
==
"epoch_ms"
:
if
tf
in
[
"epoch_ms"
,
"epoch_s"
]:
seconds_since_epoch
=
int
(
dttm
.
timestamp
())
if
tf
==
"epoch_s"
:
return
str
(
seconds_since_epoch
)
return
str
(
seconds_since_epoch
*
1000
)
return
"'{}'"
.
format
(
dttm
.
strftime
(
tf
))
else
:
s
=
self
.
table
.
database
.
db_engine_spec
.
convert_dttm
(
self
.
type
or
""
,
dttm
)
return
f
"'
{
dttm
.
strftime
(
tf
)
}
'"
# TODO(john-bodley): SIP-15 will explicitly require a type conversion.
return
s
or
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S.%f"
))
# TODO(john-bodley): SIP-15 will explicitly require a type conversion.
return
f
"""'
{
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S.%f"
)
}
'"""
class
SqlMetric
(
Model
,
BaseMetric
):
...
...
superset/db_engine_specs/athena.py
浏览文件 @
0a3b1212
...
...
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
Optional
from
superset.db_engine_specs.base
import
BaseEngineSpec
...
...
@@ -39,13 +40,13 @@ class AthenaEngineSpec(BaseEngineSpec):
}
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"from_iso8601_date('{}')"
.
format
(
dttm
.
isoformat
()[:
10
])
return
f
"from_iso8601_date('
{
dttm
.
date
().
isoformat
()
}
')"
if
tt
==
"TIMESTAMP"
:
return
"from_iso8601_timestamp('{}')"
.
format
(
dttm
.
isoformat
())
return
"CAST ('{}' AS TIMESTAMP)"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""from_iso8601_timestamp('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
')"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
epoch_to_dttm
(
cls
)
->
str
:
...
...
superset/db_engine_specs/base.py
浏览文件 @
0a3b1212
...
...
@@ -439,15 +439,15 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods
db
.
session
.
commit
()
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
"""
Convert
DateTime object to sql
expression
Convert
Python datetime object to a SQL
expression
:param target_type: Target type of expression
:param dttm:
DateT
ime object
:return: SQL expression
:param target_type: T
he t
arget type of expression
:param dttm:
The datet
ime object
:return:
The
SQL expression
"""
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
None
@
classmethod
def
get_all_datasource_names
(
...
...
superset/db_engine_specs/bigquery.py
浏览文件 @
0a3b1212
...
...
@@ -17,7 +17,7 @@
import
hashlib
import
re
from
datetime
import
datetime
from
typing
import
Any
,
Dict
,
List
,
Tuple
from
typing
import
Any
,
Dict
,
List
,
Optional
,
Tuple
import
pandas
as
pd
from
sqlalchemy
import
literal_column
...
...
@@ -72,11 +72,15 @@ class BigQueryEngineSpec(BaseEngineSpec):
}
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"CAST('
{
dttm
.
date
().
isoformat
()
}
' AS DATE)"
if
tt
==
"DATETIME"
:
return
f
"""CAST('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
' AS DATETIME)"""
if
tt
==
"TIMESTAMP"
:
return
f
"""CAST('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
' AS TIMESTAMP)"""
return
None
@
classmethod
def
fetch_data
(
cls
,
cursor
,
limit
:
int
)
->
List
[
Tuple
]:
...
...
superset/db_engine_specs/clickhouse.py
浏览文件 @
0a3b1212
...
...
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
Optional
from
superset.db_engine_specs.base
import
BaseEngineSpec
...
...
@@ -43,10 +44,10 @@ class ClickHouseEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method
}
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"toDate('{}')"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d"
))
return
f
"toDate('
{
dttm
.
date
().
isoformat
()
}
')"
if
tt
==
"DATETIME"
:
return
"toDateTime('{}')"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""toDateTime('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"seconds"
)
}
')"""
return
None
superset/db_engine_specs/db2.py
浏览文件 @
0a3b1212
...
...
@@ -14,8 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
superset.db_engine_specs.base
import
BaseEngineSpec
,
LimitMethod
...
...
@@ -51,7 +49,3 @@ class Db2EngineSpec(BaseEngineSpec):
@
classmethod
def
epoch_to_dttm
(
cls
)
->
str
:
return
"(TIMESTAMP('1970-01-01', '00:00:00') + {col} SECONDS)"
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d-%H.%M.%S"
))
superset/db_engine_specs/drill.py
浏览文件 @
0a3b1212
...
...
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
Optional
from
urllib
import
parse
from
superset.db_engine_specs.base
import
BaseEngineSpec
...
...
@@ -49,13 +50,13 @@ class DrillEngineSpec(BaseEngineSpec):
return
"TO_DATE({col})"
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"CAST('{}' AS DATE)"
.
format
(
dttm
.
isoformat
()[:
10
])
return
f
"TO_DATE('
{
dttm
.
date
().
isoformat
()
}
', 'yyyy-MM-dd')"
elif
tt
==
"TIMESTAMP"
:
return
"CAST('{}' AS TIMESTAMP)"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""TO_TIMESTAMP('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"seconds"
)
}
', 'yyyy-MM-dd HH:mm:ss')"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
adjust_database_uri
(
cls
,
uri
,
selected_schema
):
...
...
superset/db_engine_specs/elasticsearch.py
浏览文件 @
0a3b1212
...
...
@@ -16,7 +16,7 @@
# under the License.
# pylint: disable=C,R,W
from
datetime
import
datetime
from
typing
import
Dict
from
typing
import
Dict
,
Optional
from
superset.db_engine_specs.base
import
BaseEngineSpec
...
...
@@ -41,7 +41,7 @@ class ElasticSearchEngineSpec(BaseEngineSpec):
type_code_map
:
Dict
[
int
,
str
]
=
{}
# loaded from get_datatype only if needed
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
if
target_type
.
upper
()
in
(
"DATETIME"
,
"DATE"
)
:
return
f
"
'
{
dttm
.
isoformat
()
}
'
"
return
f
"'
{
dttm
.
strftime
(
'%Y-%m-%d %H:%M:%S'
)
}
'"
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
if
target_type
.
upper
()
==
"DATETIME"
:
return
f
"
""CAST('
{
dttm
.
isoformat
(
timespec
=
"seconds"
)
}
' AS DATETIME)""
"
return
None
superset/db_engine_specs/hive.py
浏览文件 @
0a3b1212
...
...
@@ -179,13 +179,13 @@ class HiveEngineSpec(PrestoEngineSpec):
engine
.
execute
(
sql
)
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"CAST('{}' AS DATE)"
.
format
(
dttm
.
isoformat
()[:
10
])
return
f
"CAST('
{
dttm
.
date
().
isoformat
()
}
' AS DATE)"
elif
tt
==
"TIMESTAMP"
:
return
"CAST('{}' AS TIMESTAMP)"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""CAST('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"microseconds"
)
}
' AS TIMESTAMP)"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
adjust_database_uri
(
cls
,
uri
,
selected_schema
=
None
):
...
...
superset/db_engine_specs/impala.py
浏览文件 @
0a3b1212
...
...
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
List
from
typing
import
List
,
Optional
from
sqlalchemy.engine.reflection
import
Inspector
...
...
@@ -43,11 +43,13 @@ class ImpalaEngineSpec(BaseEngineSpec):
return
"from_unixtime({col})"
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"CAST('
{
dttm
.
date
().
isoformat
()
}
' AS DATE)"
elif
tt
==
"TIMESTAMP"
:
return
f
"""CAST('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
' AS TIMESTAMP)"""
return
None
@
classmethod
def
get_schema_names
(
cls
,
inspector
:
Inspector
)
->
List
[
str
]:
...
...
superset/db_engine_specs/kylin.py
浏览文件 @
0a3b1212
...
...
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
Optional
from
superset.db_engine_specs.base
import
BaseEngineSpec
...
...
@@ -39,10 +40,10 @@ class KylinEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method
}
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"CAST('{}' AS DATE)"
.
format
(
dttm
.
isoformat
()[:
10
])
return
f
"CAST('
{
dttm
.
date
().
isoformat
()
}
' AS DATE)"
if
tt
==
"TIMESTAMP"
:
return
"CAST('{}' AS TIMESTAMP)"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""CAST('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"seconds"
)
}
' AS TIMESTAMP)"""
# pylint: disable=line-too-long
return
None
superset/db_engine_specs/mssql.py
浏览文件 @
0a3b1212
...
...
@@ -50,8 +50,15 @@ class MssqlEngineSpec(BaseEngineSpec):
return
"dateadd(S, {col}, '1970-01-01')"
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
return
"CONVERT(DATETIME, '{}', 126)"
.
format
(
dttm
.
isoformat
())
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
f
"CONVERT(DATE, '
{
dttm
.
date
().
isoformat
()
}
', 23)"
if
tt
==
"DATETIME"
:
return
f
"""CONVERT(DATETIME, '
{
dttm
.
isoformat
(
timespec
=
"milliseconds"
)
}
', 126)"""
# pylint: disable=line-too-long
if
tt
==
"SMALLDATETIME"
:
return
f
"""CONVERT(SMALLDATETIME, '
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"seconds"
)
}
', 20)"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
fetch_data
(
cls
,
cursor
,
limit
:
int
)
->
List
[
Tuple
]:
...
...
superset/db_engine_specs/mysql.py
浏览文件 @
0a3b1212
...
...
@@ -50,12 +50,13 @@ class MySQLEngineSpec(BaseEngineSpec):
type_code_map
:
Dict
[
int
,
str
]
=
{}
# loaded from get_datatype only if needed
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
if
target_type
.
upper
()
in
(
"DATETIME"
,
"DATE"
):
return
"STR_TO_DATE('{}', '%Y-%m-%d %H:%i:%s')"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
)
)
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
f
"STR_TO_DATE('
{
dttm
.
date
().
isoformat
()
}
', '%Y-%m-%d')"
if
tt
==
"DATETIME"
:
return
f
"""STR_TO_DATE('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"microseconds"
)
}
', '%Y-%m-%d %H:%i:%s.%f')"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
adjust_database_uri
(
cls
,
uri
,
selected_schema
=
None
):
...
...
superset/db_engine_specs/oracle.py
浏览文件 @
0a3b1212
...
...
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
typing
import
Optional
from
superset.db_engine_specs.base
import
LimitMethod
from
superset.db_engine_specs.postgres
import
PostgresBaseEngineSpec
...
...
@@ -39,7 +40,10 @@ class OracleEngineSpec(PostgresBaseEngineSpec):
}
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
return
(
"""TO_TIMESTAMP('{}', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')"""
).
format
(
dttm
.
isoformat
()
)
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
f
"TO_DATE('
{
dttm
.
date
().
isoformat
()
}
', 'YYYY-MM-DD')"
if
tt
==
"TIMESTAMP"
:
return
f
"""TO_TIMESTAMP('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')"""
# pylint: disable=line-too-long
return
None
superset/db_engine_specs/postgres.py
浏览文件 @
0a3b1212
...
...
@@ -55,10 +55,6 @@ class PostgresBaseEngineSpec(BaseEngineSpec):
def
epoch_to_dttm
(
cls
)
->
str
:
return
"(timestamp 'epoch' + {col} * interval '1 second')"
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
class
PostgresEngineSpec
(
PostgresBaseEngineSpec
):
engine
=
"postgresql"
...
...
@@ -73,3 +69,12 @@ class PostgresEngineSpec(PostgresBaseEngineSpec):
tables
=
inspector
.
get_table_names
(
schema
)
tables
.
extend
(
inspector
.
get_foreign_table_names
(
schema
))
return
sorted
(
tables
)
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
f
"TO_DATE('
{
dttm
.
date
().
isoformat
()
}
', 'YYYY-MM-DD')"
if
tt
==
"TIMESTAMP"
:
return
f
"""TO_TIMESTAMP('
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"microseconds"
)
}
', 'YYYY-MM-DD HH24:MI:SS.US')"""
# pylint: disable=line-too-long
return
None
superset/db_engine_specs/presto.py
浏览文件 @
0a3b1212
...
...
@@ -520,13 +520,13 @@ class PrestoEngineSpec(BaseEngineSpec):
return
uri
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]
:
tt
=
target_type
.
upper
()
if
tt
==
"DATE"
:
return
"from_iso8601_date('{}')"
.
format
(
dttm
.
isoformat
()[:
10
])
return
f
"""from_iso8601_date('
{
dttm
.
date
().
isoformat
()
}
')"""
if
tt
==
"TIMESTAMP"
:
return
"from_iso8601_timestamp('{}')"
.
format
(
dttm
.
isoformat
())
return
"'{}'"
.
format
(
dttm
.
strftime
(
"%Y-%m-%d %H:%M:%S"
))
return
f
"""from_iso8601_timestamp('
{
dttm
.
isoformat
(
timespec
=
"microseconds"
)
}
')"""
# pylint: disable=line-too-long
return
None
@
classmethod
def
epoch_to_dttm
(
cls
)
->
str
:
...
...
superset/db_engine_specs/sqlite.py
浏览文件 @
0a3b1212
...
...
@@ -75,11 +75,10 @@ class SqliteEngineSpec(BaseEngineSpec):
raise
Exception
(
f
"Unsupported datasource_type:
{
datasource_type
}
"
)
@
classmethod
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
str
:
iso
=
dttm
.
isoformat
().
replace
(
"T"
,
" "
)
if
"."
not
in
iso
:
iso
+=
".000000"
return
"'{}'"
.
format
(
iso
)
def
convert_dttm
(
cls
,
target_type
:
str
,
dttm
:
datetime
)
->
Optional
[
str
]:
if
target_type
.
upper
()
==
"TEXT"
:
return
f
"""'
{
dttm
.
isoformat
(
sep
=
" "
,
timespec
=
"microseconds"
)
}
'"""
return
None
@
classmethod
def
get_table_names
(
...
...
tests/db_engine_specs/athena_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.athena
import
AthenaEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
AthenaTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
AthenaEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"from_iso8601_date('2019-01-02')"
,
)
self
.
assertEqual
(
AthenaEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"from_iso8601_timestamp('2019-01-02T03:04:05.678900')"
,
)
tests/db_engine_specs/base_engine_spec_tests.py
浏览文件 @
0a3b1212
...
...
@@ -202,3 +202,7 @@ class DbEngineSpecsTests(DbEngineSpecTestCase):
else
:
expected
=
[
"VARCHAR(255)"
,
"VARCHAR(255)"
,
"FLOAT"
]
self
.
assertEqual
(
col_names
,
expected
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertIsNone
(
BaseEngineSpec
.
convert_dttm
(
""
,
dttm
))
tests/db_engine_specs/base_tests.py
浏览文件 @
0a3b1212
...
...
@@ -14,6 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
datetime
import
datetime
from
superset.db_engine_specs.mysql
import
MySQLEngineSpec
from
superset.models.core
import
Database
from
tests.base_tests
import
SupersetTestCase
...
...
@@ -26,3 +28,6 @@ class DbEngineSpecTestCase(SupersetTestCase):
main
=
Database
(
database_name
=
"test_database"
,
sqlalchemy_uri
=
"sqlite://"
)
limited
=
engine_spec_class
.
apply_limit_to_sql
(
sql
,
limit
,
main
)
self
.
assertEqual
(
expected_sql
,
limited
)
def
get_dttm
(
self
):
return
datetime
.
strptime
(
"2019-01-02 03:04:05.678900"
,
"%Y-%m-%d %H:%M:%S.%f"
)
tests/db_engine_specs/bigquery_tests.py
浏览文件 @
0a3b1212
...
...
@@ -37,3 +37,20 @@ class BigQueryTestCase(DbEngineSpecTestCase):
label
=
BigQueryEngineSpec
.
make_label_compatible
(
column
(
"12345_col"
).
name
)
label_expected
=
"_12345_col_8d390"
self
.
assertEqual
(
label
,
label_expected
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
BigQueryEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"CAST('2019-01-02' AS DATE)"
)
self
.
assertEqual
(
BigQueryEngineSpec
.
convert_dttm
(
"DATETIME"
,
dttm
),
"CAST('2019-01-02T03:04:05.678900' AS DATETIME)"
,
)
self
.
assertEqual
(
BigQueryEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"CAST('2019-01-02T03:04:05.678900' AS TIMESTAMP)"
,
)
tests/db_engine_specs/clickhouse_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.clickhouse
import
ClickHouseEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
ClickHouseTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
ClickHouseEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"toDate('2019-01-02')"
)
self
.
assertEqual
(
ClickHouseEngineSpec
.
convert_dttm
(
"DATETIME"
,
dttm
),
"toDateTime('2019-01-02 03:04:05')"
,
)
tests/db_engine_specs/drill_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.drill
import
DrillEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
DrillTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
DrillEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"TO_DATE('2019-01-02', 'yyyy-MM-dd')"
,
)
self
.
assertEqual
(
DrillEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"TO_TIMESTAMP('2019-01-02 03:04:05', 'yyyy-MM-dd HH:mm:ss')"
,
)
tests/db_engine_specs/elasticsearch_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.elasticsearch
import
ElasticSearchEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
ElasticSearchTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
ElasticSearchEngineSpec
.
convert_dttm
(
"DATETIME"
,
dttm
),
"CAST('2019-01-02T03:04:05' AS DATETIME)"
,
)
tests/db_engine_specs/hive_tests.py
浏览文件 @
0a3b1212
...
...
@@ -150,3 +150,15 @@ class HiveTests(DbEngineSpecTestCase):
self
.
assertEqual
(
[],
HiveEngineSpec
.
get_view_names
(
mock
.
ANY
,
mock
.
ANY
,
mock
.
ANY
)
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
HiveEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"CAST('2019-01-02' AS DATE)"
)
self
.
assertEqual
(
HiveEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"CAST('2019-01-02 03:04:05.678900' AS TIMESTAMP)"
,
)
tests/db_engine_specs/impala_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.impala
import
ImpalaEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
ImpalaTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
ImpalaEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"CAST('2019-01-02' AS DATE)"
)
self
.
assertEqual
(
ImpalaEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"CAST('2019-01-02T03:04:05.678900' AS TIMESTAMP)"
,
)
tests/db_engine_specs/kylin_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.kylin
import
KylinEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
KylinTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
KylinEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"CAST('2019-01-02' AS DATE)"
)
self
.
assertEqual
(
KylinEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"CAST('2019-01-02 03:04:05' AS TIMESTAMP)"
,
)
tests/db_engine_specs/mssql_tests.py
浏览文件 @
0a3b1212
...
...
@@ -69,3 +69,21 @@ class MssqlEngineSpecTest(DbEngineSpecTestCase):
expr
=
MssqlEngineSpec
.
get_timestamp_expr
(
col
,
None
,
"P1Y"
)
result
=
str
(
expr
.
compile
(
None
,
dialect
=
mssql
.
dialect
()))
self
.
assertEqual
(
result
,
"DATEADD(year, DATEDIFF(year, 0, [MixedCase]), 0)"
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
MssqlEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"CONVERT(DATE, '2019-01-02', 23)"
,
)
self
.
assertEqual
(
MssqlEngineSpec
.
convert_dttm
(
"DATETIME"
,
dttm
),
"CONVERT(DATETIME, '2019-01-02T03:04:05.678', 126)"
,
)
self
.
assertEqual
(
MssqlEngineSpec
.
convert_dttm
(
"SMALLDATETIME"
,
dttm
),
"CONVERT(SMALLDATETIME, '2019-01-02 03:04:05', 20)"
,
)
tests/db_engine_specs/mysql_tests.py
浏览文件 @
0a3b1212
...
...
@@ -28,3 +28,16 @@ class MySQLEngineSpecsTestCase(DbEngineSpecTestCase):
"""Tests related to datatype mapping for MySQL"""
self
.
assertEqual
(
"TINY"
,
MySQLEngineSpec
.
get_datatype
(
1
))
self
.
assertEqual
(
"VARCHAR"
,
MySQLEngineSpec
.
get_datatype
(
15
))
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
MySQLEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"STR_TO_DATE('2019-01-02', '%Y-%m-%d')"
,
)
self
.
assertEqual
(
MySQLEngineSpec
.
convert_dttm
(
"DATETIME"
,
dttm
),
"STR_TO_DATE('2019-01-02 03:04:05.678900', '%Y-%m-%d %H:%i:%s.%f')"
,
)
tests/db_engine_specs/oracle_tests.py
浏览文件 @
0a3b1212
...
...
@@ -34,3 +34,17 @@ class OracleTestCase(DbEngineSpecTestCase):
expr
=
OracleEngineSpec
.
get_timestamp_expr
(
col
,
None
,
"P1M"
)
result
=
str
(
expr
.
compile
(
dialect
=
oracle
.
dialect
()))
self
.
assertEqual
(
result
,
"TRUNC(CAST(
\"
decimal
\"
as DATE), 'MONTH')"
)
dttm
=
self
.
get_dttm
()
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
OracleEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"TO_DATE('2019-01-02', 'YYYY-MM-DD')"
,
)
self
.
assertEqual
(
OracleEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"""TO_TIMESTAMP('2019-01-02T03:04:05.678900', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')"""
,
)
tests/db_engine_specs/postgres_tests.py
浏览文件 @
0a3b1212
...
...
@@ -70,3 +70,16 @@ class PostgresTests(DbEngineSpecTestCase):
expr
=
PostgresEngineSpec
.
get_timestamp_expr
(
col
,
None
,
"P1Y"
)
result
=
str
(
expr
.
compile
(
None
,
dialect
=
postgresql
.
dialect
()))
self
.
assertEqual
(
result
,
"DATE_TRUNC('year',
\"
MixedCase
\"
)"
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
PostgresEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"TO_DATE('2019-01-02', 'YYYY-MM-DD')"
,
)
self
.
assertEqual
(
PostgresEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"TO_TIMESTAMP('2019-01-02 03:04:05.678900', 'YYYY-MM-DD HH24:MI:SS.US')"
,
)
tests/db_engine_specs/presto_tests.py
浏览文件 @
0a3b1212
...
...
@@ -341,3 +341,16 @@ class PrestoTests(DbEngineSpecTestCase):
)
query_result
=
str
(
result
.
compile
(
compile_kwargs
=
{
"literal_binds"
:
True
}))
self
.
assertEqual
(
"SELECT
\n
WHERE ds = '01-01-19' AND hour = 1"
,
query_result
)
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
PrestoEngineSpec
.
convert_dttm
(
"DATE"
,
dttm
),
"from_iso8601_date('2019-01-02')"
,
)
self
.
assertEqual
(
PrestoEngineSpec
.
convert_dttm
(
"TIMESTAMP"
,
dttm
),
"from_iso8601_timestamp('2019-01-02T03:04:05.678900')"
,
)
tests/db_engine_specs/sqlite_tests.py
0 → 100644
浏览文件 @
0a3b1212
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from
superset.db_engine_specs.sqlite
import
SqliteEngineSpec
from
tests.db_engine_specs.base_tests
import
DbEngineSpecTestCase
class
SQliteTestCase
(
DbEngineSpecTestCase
):
def
test_convert_dttm
(
self
):
dttm
=
self
.
get_dttm
()
self
.
assertEqual
(
SqliteEngineSpec
.
convert_dttm
(
"TEXT"
,
dttm
),
"'2019-01-02 03:04:05.678900'"
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录