Changeset: 5614092fb16b for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5614092fb16b
Modified Files:
        clients/iotapi/src/Streams/datatypes.py
        clients/iotapi/src/Streams/streampolling.py
        clients/iotapi/src/Streams/streams.py
        clients/iotapi/src/Streams/streamscontext.py
        clients/iotapi/src/WebSockets/jsonschemas.py
        clients/iotapi/src/WebSockets/websockets.py
        clients/iotclient/src/Streams/datatypes.py
        clients/iotclient/src/Streams/streampolling.py
        clients/iotclient/src/Streams/streams.py
        clients/iotclient/src/Streams/streamscontext.py
        clients/iotclient/src/Streams/streamscreator.py
Branch: iot
Log Message:

Added automatic tuple count for iotapi so there is no need for an auxiliary 
file now. Fixed some binary conversions while reading baskets in iotapi. Also 
fixed tuple order in JSON responses.


diffs (truncated from 897 to 300 lines):

diff --git a/clients/iotapi/src/Streams/datatypes.py 
b/clients/iotapi/src/Streams/datatypes.py
--- a/clients/iotapi/src/Streams/datatypes.py
+++ b/clients/iotapi/src/Streams/datatypes.py
@@ -1,22 +1,19 @@
 import struct
 
 from abc import ABCMeta, abstractmethod
-from collections import OrderedDict
 from datetime import date, time, datetime
 from dateutil.relativedelta import relativedelta
+from os import SEEK_END
 
 LITTLE_ENDIAN_ALIGNMENT = '<'  # for now is little-endian for Intel CPU's
 
 NIL_STRING = "\200\n"  # added newline for performance
 NIL_UUID = "00000000-0000-0000-0000-000000000000"
 
-INT8_MIN = 0x80
-INT16_MIN = 0x8000
-INT32_MIN = 0x80000000
-INT64_MIN = 0x8000000000000000
-INT64_MAX = 0xFFFFFFFFFFFFFFFF
-INT128_MIN = 0x80000000000000000000000000000000
-
+INT8_MIN = -128
+INT16_MIN = -32768
+INT32_MIN = -2147483648
+INT64_MIN = -9223372036854775808
 FLOAT_NAN = struct.unpack('f', '\xff\xff\x7f\xff')[0]
 DOUBLE_NAN = struct.unpack('d', '\xff\xff\xff\xff\xff\xff\xef\xff')[0]
 
@@ -31,10 +28,17 @@ class StreamDataType(object):
         self._default_value = kwargs['default']  # default value text
         self._is_nullable = kwargs['nullable']  # is nullable
 
+    def get_column_name(self):
+        return self._column_name
+
     def is_file_mode_binary(self):
         return True
 
     @abstractmethod
+    def calculate_file_size(self, fp):
+        pass
+
+    @abstractmethod
     def skip_tuples(self, fp, offset):
         pass
 
@@ -56,12 +60,12 @@ class StreamDataType(object):
         return results
 
     def to_json_representation(self):  # get a json representation of the data 
type while checking the stream's info
-        return OrderedDict((('name', self._column_name), ('type', 
self._data_type),
-                            ('default', self._default_value), ('nullable', 
self._is_nullable)))
+        return (('name', self._column_name), ('type', self._data_type),
+                ('default', self._default_value), ('nullable', 
self._is_nullable))
 
 
 class TextType(StreamDataType):
-    """Covers: CLOB and Url"""
+    """Covers: CLOB and URL"""
 
     def __init__(self, **kwargs):
         super(TextType, self).__init__(**kwargs)
@@ -70,6 +74,9 @@ class TextType(StreamDataType):
     def is_file_mode_binary(self):
         return False
 
+    def calculate_file_size(self, fp):
+        return sum(1 for _ in fp)
+
     def skip_tuples(self, fp, offset):
         for _ in xrange(offset):
             next(fp)
@@ -93,9 +100,7 @@ class LimitedTextType(TextType):
         self._limit = kwargs['digits']
 
     def to_json_representation(self):
-        json_value = super(LimitedTextType, self).to_json_representation()
-        json_value['limit'] = self._limit
-        return json_value
+        return super(LimitedTextType, self).to_json_representation() + 
(('limit', self._limit),)
 
 
 class INetType(StreamDataType):
@@ -104,6 +109,10 @@ class INetType(StreamDataType):
     def __init__(self, **kwargs):
         super(INetType, self).__init__(**kwargs)
 
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> 3  # a inet has a size of 8 bytes
+
     def skip_tuples(self, fp, offset):
         fp.seek(offset << 3)
 
@@ -129,6 +138,10 @@ class UUIDType(StreamDataType):
     def __init__(self, **kwargs):
         super(UUIDType, self).__init__(**kwargs)
 
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> 4  # a inet has a size of 16 bytes
+
     def skip_tuples(self, fp, offset):
         fp.seek(offset << 4)
 
@@ -145,7 +158,6 @@ class UUIDType(StreamDataType):
                     next_uuid.append("-")
                 else:
                     next_uuid.append("%02x" % next(iterator))
-
             built_uuid = ''.join(next_uuid)
             if built_uuid == NIL_UUID:
                 built_uuid = None
@@ -158,14 +170,17 @@ class BooleanType(StreamDataType):
 
     def __init__(self, **kwargs):
         super(BooleanType, self).__init__(**kwargs)
-        self._nullable_constant = INT8_MIN
+
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell()  # a boolean has a size of 1 byte
 
     def skip_tuples(self, fp, offset):
         fp.seek(offset)
 
     def read_next_batch(self, fp, limit):
         array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 'b', 
fp.read(limit))
-        return map(lambda x: None if x == self._nullable_constant else 
bool(x), array)
+        return map(lambda x: None if x == INT8_MIN else bool(x), array)
 
 
 class SmallIntegerType(StreamDataType):
@@ -175,16 +190,20 @@ class SmallIntegerType(StreamDataType):
         super(SmallIntegerType, self).__init__(**kwargs)
         self._pack_sym = {'tinyint': 'b', 'smallint': 'h', 'int': 'i', 
'integer': 'i', 'bigint': 'q'} \
             .get(self._data_type)
-        self._size = struct.calcsize(self._pack_sym)
+        self._size = {'tinyint': 0, 'smallint': 1, 'int': 2, 'integer': 2, 
'bigint': 3}.get(self._data_type)
         self._nullable_constant = {'tinyint': INT8_MIN, 'smallint': INT16_MIN, 
'int': INT32_MIN, 'integer': INT32_MIN,
                                    'bigint': INT64_MIN}.get(self._data_type)
 
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> self._size
+
     def skip_tuples(self, fp, offset):
-        fp.seek(offset * self._size)
+        fp.seek(offset << self._size)
 
     def read_next_batch(self, fp, limit):
-        array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit * self._size))
-        return map(lambda x: None if x == self._nullable_constant else int(x), 
array)
+        array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit << self._size))
+        return map(lambda x: None if x == self._nullable_constant else x, 
array)
 
 
 class HugeIntegerType(StreamDataType):
@@ -192,21 +211,25 @@ class HugeIntegerType(StreamDataType):
 
     def __init__(self, **kwargs):
         super(HugeIntegerType, self).__init__(**kwargs)
-        self._nullable_constant = INT128_MIN
+
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> 4
 
     def skip_tuples(self, fp, offset):
         fp.seek(offset << 4)
 
-    def read_next_batch(self, fp, limit):  # [entry & INT64_MAX, (entry >> 64) 
& INT64_MAX]
+    def read_next_batch(self, fp, limit):
         array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit << 1) + 'Q', 
fp.read(limit << 4))
         results = []
         iterator = iter(array)  # has to iterate two values at once, so use 
iterator
         for value in iterator:
-            next_huge = next(iterator) + (value << 64)
-            if next_huge == self._nullable_constant:
+            second_value = next(iterator)
+            next_huge = (second_value << 64) + value
+            if next_huge == 0x80000000000000000000000000000000:
                 results.append(None)
             else:
-                results.append(int(next_huge))
+                results.append(next_huge)
         return results
 
 
@@ -216,15 +239,19 @@ class FloatType(StreamDataType):
     def __init__(self, **kwargs):
         super(FloatType, self).__init__(**kwargs)
         self._pack_sym = {'real': 'f', 'float': 'd', 'double': 
'd'}.get(self._data_type)
-        self._size = struct.calcsize(self._pack_sym)
+        self._size = {'real': 2, 'float': 3, 'double': 3}.get(self._data_type)
         self._nullable_constant = {'real': FLOAT_NAN, 'float': DOUBLE_NAN, 
'double': DOUBLE_NAN}.get(self._data_type)
 
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> self._size
+
     def skip_tuples(self, fp, offset):
-        fp.seek(offset * self._size)
+        fp.seek(offset << self._size)
 
     def read_next_batch(self, fp, limit):
-        array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit * self._size))
-        return map(lambda x: None if x == self._nullable_constant else 
float(x), array)
+        array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit << self._size))
+        return map(lambda x: None if x == self._nullable_constant else x, 
array)
 
 
 class DecimalType(StreamDataType):
@@ -246,35 +273,40 @@ class DecimalType(StreamDataType):
         elif 18 < self._precision <= 38:
             self._pack_sym = 'Q'
 
-        self._nullable_constant = {'b': INT8_MIN, 'h': INT16_MIN, 'i': 
INT32_MIN, 'q': INT64_MIN, 'Q': INT128_MIN} \
-            .get(self._pack_sym)
-        self._size = struct.calcsize(self._pack_sym)
-        if self._pack_sym == 'Q':
-            self._size <<= 1  # has to read two values at once
+        self._nullable_constant = {'b': INT8_MIN, 'h': INT16_MIN, 'i': 
INT32_MIN, 'q': INT64_MIN,
+                                   'Q': 
0x80000000000000000000000000000000}.get(self._pack_sym)
+        self._size = {'b': 0, 'h': 1, 'i': 2, 'q': 3, 'Q': 
4}.get(self._pack_sym)
+
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> self._size
 
     def skip_tuples(self, fp, offset):
-        fp.seek(offset * self._size)
+        fp.seek(offset << self._size)
 
     def read_next_batch(self, fp, limit):
-        array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit * self._size))
         if self._pack_sym != 'Q':
+            array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 
self._pack_sym, fp.read(limit << self._size))
             return map(lambda x: None if x == self._nullable_constant else 
float(x), array)
         else:
+            array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit << 1) + 
self._pack_sym,
+                                  fp.read(limit << self._size))
             results = []
             iterator = iter(array)  # has to iterate two values at once, so 
use iterator
             for value in iterator:
-                next_huge_decimal = next(iterator) + (value << 64)
+                second_value = next(iterator)
+                next_huge_decimal = (second_value << 64) + value
                 if next_huge_decimal == self._nullable_constant:
                     results.append(None)
                 else:
-                    results.append(next_huge_decimal)
+                    results.append(float(next_huge_decimal))
             return results
 
     def to_json_representation(self):
-        json_value = super(DecimalType, self).to_json_representation()
-        json_value['precision'] = self._precision
-        json_value['scale'] = self._scale
-        return json_value
+        return super(DecimalType, self).to_json_representation() + \
+               (('precision', self._precision), ('scale', self._scale),)
+
+year_delta = relativedelta(years=1)
 
 
 class DateType(StreamDataType):  # Stored as an uint with the number of days 
since day 1 of month 1 (Jan) from year 0
@@ -282,7 +314,10 @@ class DateType(StreamDataType):  # Store
 
     def __init__(self, **kwargs):
         super(DateType, self).__init__(**kwargs)
-        self._nullable_constant = INT32_MIN
+
+    def calculate_file_size(self, fp):
+        fp.seek(0, SEEK_END)
+        return fp.tell() >> 2
 
     def skip_tuples(self, fp, offset):
         fp.seek(offset << 2)
@@ -291,10 +326,10 @@ class DateType(StreamDataType):  # Store
         array = struct.unpack(LITTLE_ENDIAN_ALIGNMENT + str(limit) + 'I', 
fp.read(limit << 2))
         results = []
         for value in array:
-            if value == self._nullable_constant:
+            if value == 0x80000000:
                 results.append(None)
             else:  # dates in python start on year 1, so we must subtract one 
year
-                results.append((date.fromordinal(value) - 
relativedelta(years=1)).isoformat())
+                results.append((date.fromordinal(value) - 
year_delta).isoformat())
         return results
 
 
@@ -303,10 +338,13 @@ class TimeType(StreamDataType):  # Store
 
     def __init__(self, **kwargs):
         super(TimeType, self).__init__(**kwargs)
-        self._nullable_constant = INT32_MIN
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to