Skip to content

Commit

Permalink
[BUGFIX]: JavaScripts max int is 2^53 - 1, longs are bigger (apache#4005
Browse files Browse the repository at this point in the history
)

* [BUGFIX]: Java scripts max int is 2^53 - 1 longs are bigger and frequently used as IDs this is a hacky fix.

* Keep tuple as tuple
  • Loading branch information
fabianmenges authored and timifasubaa committed May 31, 2018
1 parent fe42cbb commit 67fd0e5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 8 deletions.
13 changes: 11 additions & 2 deletions superset/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from pandas.core.dtypes.dtypes import ExtensionDtype
from past.builtins import basestring

from superset.utils import JS_MAX_INTEGER

INFER_COL_TYPES_THRESHOLD = 95
INFER_COL_TYPES_SAMPLE_SIZE = 100
Expand Down Expand Up @@ -51,9 +52,17 @@ def size(self):
@property
def data(self):
# work around for https://github.com/pandas-dev/pandas/issues/18372
return [dict((k, _maybe_box_datetimelike(v))
for k, v in zip(self.__df.columns, np.atleast_1d(row)))
data = [dict((k, _maybe_box_datetimelike(v))
for k, v in zip(self.__df.columns, np.atleast_1d(row)))
for row in self.__df.values]
for d in data:
for k, v in list(d.items()):
# if an int is too big for Java Script to handle
# convert it to a string
if isinstance(v, int):
if abs(v) > JS_MAX_INTEGER:
d[k] = str(v)
return data

@classmethod
def db_type(cls, dtype):
Expand Down
2 changes: 2 additions & 0 deletions superset/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
EPOCH = datetime(1970, 1, 1)
DTTM_ALIAS = '__timestamp'

JS_MAX_INTEGER = 9007199254740991 # Largest int Java Script can handle 2^53-1


def flasher(msg, severity=None):
"""Flask's flash if available, logging call if not"""
Expand Down
31 changes: 25 additions & 6 deletions superset/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from six.moves import cPickle as pkl, reduce

from superset import app, cache, get_manifest_file, utils
from superset.utils import DTTM_ALIAS, merge_extra_filters
from superset.utils import DTTM_ALIAS, JS_MAX_INTEGER, merge_extra_filters


config = app.config
Expand Down Expand Up @@ -88,6 +88,17 @@ def __init__(self, datasource, form_data, force=False):
self._any_cached_dttm = None
self._extra_chart_data = None

@staticmethod
def handle_js_int_overflow(data):
for d in data.get('records', dict()):
for k, v in list(d.items()):
if isinstance(v, int):
# if an int is too big for Java Script to handle
# convert it to a string
if abs(v) > JS_MAX_INTEGER:
d[k] = str(v)
return data

def run_extra_queries(self):
"""Lyfecycle method to use when more than one query is needed
Expand Down Expand Up @@ -515,10 +526,13 @@ def get_data(self, df):
):
del df[m]

return dict(
records=df.to_dict(orient='records'),
columns=list(df.columns),
)
data = self.handle_js_int_overflow(
dict(
records=df.to_dict(orient='records'),
columns=list(df.columns),
))

return data

def json_dumps(self, obj, sort_keys=False):
if self.form_data.get('all_columns'):
Expand Down Expand Up @@ -1033,7 +1047,12 @@ def to_series(self, df, classed='', title_suffix=''):
ys = series[name]
if df[name].dtype.kind not in 'biufc':
continue
series_title = name
if isinstance(name, list):
series_title = [str(title) for title in name]
elif isinstance(name, tuple):
series_title = tuple(str(title) for title in name)
else:
series_title = str(name)
if (
isinstance(series_title, (list, tuple)) and
len(series_title) > 1 and
Expand Down

0 comments on commit 67fd0e5

Please sign in to comment.