From 680ee59a3721d9907586e42f74136bc3ae760d06 Mon Sep 17 00:00:00 2001 From: izavits Date: Thu, 8 Sep 2016 14:26:41 +0300 Subject: [PATCH 1/4] Add Date Time Range type --- CHANGELOG.md | 2 ++ Type.sbvr | 17 +++++++++- src/types/Date Time Range.coffee | 55 ++++++++++++++++++++++++++++++++ test/Date Time Range.coffee | 22 +++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/types/Date Time Range.coffee create mode 100644 test/Date Time Range.coffee diff --git a/CHANGELOG.md b/CHANGELOG.md index 27c072b..d98f085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +* Add Date Time Range type + v1.2.0 * Return null for null dates rather than the unix epoch. diff --git a/Type.sbvr b/Type.sbvr index 27ac05e..9e9b746 100644 --- a/Type.sbvr +++ b/Type.sbvr @@ -86,4 +86,19 @@ Fact type: Color has Green Component Fact type: Color has Blue Component Necessity: Each Color has exactly one Blue Component Fact type: Color has Alpha Component - Necessity: Each Color has exactly one Alpha Component \ No newline at end of file + Necessity: Each Color has exactly one Alpha Component + +Term: Begin + Concept Type: Date Time +Term: End + Concept Type: Date Time +Term: Bounds + Concept Type: Short Text +Term: Date Time Range + Concept Type: Short Text +Fact type: Date Time Range has Begin + Necessity: Each Date Time Range has exactly one Begin +Fact Type: Date Time Range has End + Necessity: Each Date Time Range has at most one End +Fact Type: Date Time Range has Bounds + Necessity: Each Date Time Range has exactly one Bounds \ No newline at end of file diff --git a/src/types/Date Time Range.coffee b/src/types/Date Time Range.coffee new file mode 100644 index 0000000..8c55377 --- /dev/null +++ b/src/types/Date Time Range.coffee @@ -0,0 +1,55 @@ +{ + types: + postgres: 'TSTZRANGE' + mysql: 'VARCHAR(255)' + websql: 'VARCHAR(255)' + odata: + name: 'Self.DateTimeRange' + complexType: ''' + + \ + \ + \ + ''' + + nativeProperties: + has: + Begin: (from) -> ['RangeBegin', from] + End: (from) -> ['RangeEng', from] + Bounds: (from) -> ['RangeBounds', from] + + fetchProcessing: (data, callback) -> + if data? + res = + Begin: data.split(',')[0].slice(1) + End: data.split(',')[1].trim().slice(0, -1) + Bounds: data[0] + data[data.length - 1] + callback(null, res) + else + callback(null, data) + + validate: (value, required, callback) -> + if !_.isObject(value) + callback('is not a date time range object: ' + value) + else + # Check with hasOwnProperty since null values are allowed + if value.hasOwnProperty('Begin') and value.hasOwnProperty('End') and value.hasOwnProperty('Bounds') + processedValue = '' + begin = undefined + end = undefined + bounds = undefined + for own component, componentValue of value + switch component.toLowerCase() + when 'begin' + begin = componentValue + when 'end' + end = componentValue + when 'bounds' + bounds = componentValue + else + callback('has an unknown component: ' + component) + processedValue = bounds[0] + begin + ', ' + end + bounds[1] + callback(null, processedValue) + else + callback('has unknown components: ' + value) +} \ No newline at end of file diff --git a/test/Date Time Range.coffee b/test/Date Time Range.coffee new file mode 100644 index 0000000..effab61 --- /dev/null +++ b/test/Date Time Range.coffee @@ -0,0 +1,22 @@ +helpers = require './helpers' + +helpers.describe 'Date Time Range', (test) -> + begin = new Date() + end = null + '' + bounds = '[)' + describe 'fetchProcessing', -> + test.fetch(bounds[0] + begin + ', ' + end + bounds[1], { + Begin: begin.toString() + End: end + Bounds: bounds + }) + + describe 'validate', -> + begin = new Date() + end = null + bounds = '[)' + test.validate({ + Begin: begin + End: end + Bounds: bounds + }, true, bounds[0] + begin + ', ' + end + bounds[1]) \ No newline at end of file From 283beb1c569a4c153bfa93dc97ca145b4334ae2b Mon Sep 17 00:00:00 2001 From: izavits Date: Fri, 9 Sep 2016 11:11:20 +0300 Subject: [PATCH 2/4] Naming and error descr improvements --- src/types/Date Time Range.coffee | 20 ++++++++++---------- test/Date Time Range.coffee | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/types/Date Time Range.coffee b/src/types/Date Time Range.coffee index 8c55377..256fa2c 100644 --- a/src/types/Date Time Range.coffee +++ b/src/types/Date Time Range.coffee @@ -7,21 +7,21 @@ name: 'Self.DateTimeRange' complexType: ''' - \ + \ \ \ ''' nativeProperties: has: - Begin: (from) -> ['RangeBegin', from] - End: (from) -> ['RangeEng', from] + Start: (from) -> ['RangeStart', from] + End: (from) -> ['RangeEnd', from] Bounds: (from) -> ['RangeBounds', from] fetchProcessing: (data, callback) -> if data? res = - Begin: data.split(',')[0].slice(1) + Start: data.split(',')[0].slice(1) End: data.split(',')[1].trim().slice(0, -1) Bounds: data[0] + data[data.length - 1] callback(null, res) @@ -33,23 +33,23 @@ callback('is not a date time range object: ' + value) else # Check with hasOwnProperty since null values are allowed - if value.hasOwnProperty('Begin') and value.hasOwnProperty('End') and value.hasOwnProperty('Bounds') + if value.hasOwnProperty('Start') and value.hasOwnProperty('End') and value.hasOwnProperty('Bounds') processedValue = '' - begin = undefined + start = undefined end = undefined bounds = undefined for own component, componentValue of value switch component.toLowerCase() - when 'begin' - begin = componentValue + when 'start' + start = componentValue when 'end' end = componentValue when 'bounds' bounds = componentValue else callback('has an unknown component: ' + component) - processedValue = bounds[0] + begin + ', ' + end + bounds[1] + processedValue = bounds[0] + start + ', ' + end + bounds[1] callback(null, processedValue) else - callback('has unknown components: ' + value) + callback('is missing components: ' + value) } \ No newline at end of file diff --git a/test/Date Time Range.coffee b/test/Date Time Range.coffee index effab61..630d817 100644 --- a/test/Date Time Range.coffee +++ b/test/Date Time Range.coffee @@ -1,22 +1,22 @@ helpers = require './helpers' helpers.describe 'Date Time Range', (test) -> - begin = new Date() - end = null + '' + start = new Date() + end = 'null' bounds = '[)' describe 'fetchProcessing', -> - test.fetch(bounds[0] + begin + ', ' + end + bounds[1], { - Begin: begin.toString() + test.fetch(bounds[0] + start + ', ' + end + bounds[1], { + Start: start.toString() End: end Bounds: bounds }) describe 'validate', -> - begin = new Date() + start = new Date() end = null bounds = '[)' test.validate({ - Begin: begin + Start: start End: end Bounds: bounds - }, true, bounds[0] + begin + ', ' + end + bounds[1]) \ No newline at end of file + }, true, bounds[0] + start + ', ' + end + bounds[1]) \ No newline at end of file From 344fb85017bf5d03b3a12837fe5712496c81a629 Mon Sep 17 00:00:00 2001 From: izavits Date: Thu, 22 Sep 2016 12:59:50 +0300 Subject: [PATCH 3/4] add additional fact types --- Type.sbvr | 10 ++++++---- src/types/Date Time Range.coffee | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Type.sbvr b/Type.sbvr index 9e9b746..d133427 100644 --- a/Type.sbvr +++ b/Type.sbvr @@ -88,7 +88,7 @@ Fact type: Color has Blue Component Fact type: Color has Alpha Component Necessity: Each Color has exactly one Alpha Component -Term: Begin +Term: Start Concept Type: Date Time Term: End Concept Type: Date Time @@ -96,9 +96,11 @@ Term: Bounds Concept Type: Short Text Term: Date Time Range Concept Type: Short Text -Fact type: Date Time Range has Begin - Necessity: Each Date Time Range has exactly one Begin +Fact type: Date Time Range has Start + Necessity: Each Date Time Range has exactly one Start Fact Type: Date Time Range has End Necessity: Each Date Time Range has at most one End Fact Type: Date Time Range has Bounds - Necessity: Each Date Time Range has exactly one Bounds \ No newline at end of file + Necessity: Each Date Time Range has exactly one Bounds +Fact Type: Date Time Range is inclusive or exclusive of Start +Fact Type: Date Time Range is inclusive or exclusive of End \ No newline at end of file diff --git a/src/types/Date Time Range.coffee b/src/types/Date Time Range.coffee index 256fa2c..69596ae 100644 --- a/src/types/Date Time Range.coffee +++ b/src/types/Date Time Range.coffee @@ -20,9 +20,10 @@ fetchProcessing: (data, callback) -> if data? + [start, end] = data.slice(1, -1).split(',') res = - Start: data.split(',')[0].slice(1) - End: data.split(',')[1].trim().slice(0, -1) + Start: start + End: end.trim() Bounds: data[0] + data[data.length - 1] callback(null, res) else From ee6efee24db15d1e873f5e3a04098d6b71567339 Mon Sep 17 00:00:00 2001 From: izavits Date: Thu, 15 Dec 2016 16:20:06 +0200 Subject: [PATCH 4/4] Move dataTypeGen from abstract-sql-compiler here --- src/TypeUtils.coffee | 13 +++++++++++++ src/types/Boolean.coffee | 10 ++++++++++ src/types/Color.coffee | 10 ++++++++++ src/types/ConceptType.coffee | 10 ++++++++++ src/types/Date Time Range.coffee | 10 ++++++++++ src/types/Date Time.coffee | 10 ++++++++++ src/types/Date.coffee | 10 ++++++++++ src/types/File.coffee | 10 ++++++++++ src/types/ForeignKey.coffee | 10 ++++++++++ src/types/Hashed.coffee | 10 ++++++++++ src/types/Integer.coffee | 10 ++++++++++ src/types/Interval.coffee | 10 ++++++++++ src/types/JSON.coffee | 10 ++++++++++ src/types/Real.coffee | 10 ++++++++++ src/types/Serial.coffee | 10 ++++++++++ src/types/Short Text.coffee | 10 ++++++++++ src/types/Text.coffee | 10 ++++++++++ src/types/Time.coffee | 10 ++++++++++ 18 files changed, 183 insertions(+) diff --git a/src/TypeUtils.coffee b/src/TypeUtils.coffee index a8148d3..bb3066a 100644 --- a/src/TypeUtils.coffee +++ b/src/TypeUtils.coffee @@ -37,4 +37,17 @@ do -> callback('is not a valid date: ' + value) else callback(null, processedValue) + + dataTypeGen: (dbType, engine, dataType, necessity, index = '', defaultValue) -> + necessity = if necessity then ' NOT NULL' else ' NULL' + defaultValue = if defaultValue then " DEFAULT #{defaultValue}" + if index != '' + index = ' ' + index + if dbType? + if _.isFunction(dbType) + return dbType(necessity, index) + defaultValue ?= '' + return dbType + defaultValue + necessity + index + else + throw new Error("Unknown data type '#{dataType}' for engine: #{engine}") } diff --git a/src/types/Boolean.coffee b/src/types/Boolean.coffee index e0b3ad8..0348534 100644 --- a/src/types/Boolean.coffee +++ b/src/types/Boolean.coffee @@ -19,4 +19,14 @@ do -> callback("is not a boolean: #{JSON.stringify(originalValue)} (#{typeof originalValue})") else callback(null, value) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Color.coffee b/src/types/Color.coffee index 6852b1e..0b4f4d4 100644 --- a/src/types/Color.coffee +++ b/src/types/Color.coffee @@ -53,4 +53,14 @@ callback('has an unknown component: ' + component) return callback(null, processedValue) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/ConceptType.coffee b/src/types/ConceptType.coffee index 6fe02b6..fae5970 100644 --- a/src/types/ConceptType.coffee +++ b/src/types/ConceptType.coffee @@ -11,4 +11,14 @@ Real: TypeUtils.nativeFactTypeTemplates.comparison validate: TypeUtils.validate.integer + +dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Date Time Range.coffee b/src/types/Date Time Range.coffee index 69596ae..a1a6791 100644 --- a/src/types/Date Time Range.coffee +++ b/src/types/Date Time Range.coffee @@ -53,4 +53,14 @@ callback(null, processedValue) else callback('is missing components: ' + value) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } \ No newline at end of file diff --git a/src/types/Date Time.coffee b/src/types/Date Time.coffee index 8c19caa..cdc4add 100644 --- a/src/types/Date Time.coffee +++ b/src/types/Date Time.coffee @@ -12,4 +12,14 @@ callback(null, data) validate: TypeUtils.validate.date + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue != 'CURRENT_TIMESTAMP' + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Date.coffee b/src/types/Date.coffee index 644c3e1..7d9d808 100644 --- a/src/types/Date.coffee +++ b/src/types/Date.coffee @@ -12,4 +12,14 @@ callback(null, data) validate: TypeUtils.validate.date + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/File.coffee b/src/types/File.coffee index 97d03c7..51917bc 100644 --- a/src/types/File.coffee +++ b/src/types/File.coffee @@ -17,4 +17,14 @@ callback(null, value) else callback("could not be converted to binary: #{typeof value}") + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/ForeignKey.coffee b/src/types/ForeignKey.coffee index 6fe02b6..940c24e 100644 --- a/src/types/ForeignKey.coffee +++ b/src/types/ForeignKey.coffee @@ -11,4 +11,14 @@ Real: TypeUtils.nativeFactTypeTemplates.comparison validate: TypeUtils.validate.integer + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Hashed.coffee b/src/types/Hashed.coffee index 5ea7bbb..745da0e 100644 --- a/src/types/Hashed.coffee +++ b/src/types/Hashed.coffee @@ -22,4 +22,14 @@ do -> .asCallback(callback) compare: _.bind(bcrypt.compareAsync, bcrypt) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Integer.coffee b/src/types/Integer.coffee index 6fe02b6..940c24e 100644 --- a/src/types/Integer.coffee +++ b/src/types/Integer.coffee @@ -11,4 +11,14 @@ Real: TypeUtils.nativeFactTypeTemplates.comparison validate: TypeUtils.validate.integer + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Interval.coffee b/src/types/Interval.coffee index 6437c1b..df65b52 100644 --- a/src/types/Interval.coffee +++ b/src/types/Interval.coffee @@ -7,4 +7,14 @@ name: 'Edm.Int64' validate: TypeUtils.validate.integer + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/JSON.coffee b/src/types/JSON.coffee index 2bacd1c..b3e9f2a 100644 --- a/src/types/JSON.coffee +++ b/src/types/JSON.coffee @@ -18,4 +18,14 @@ catch e console.error(e) callback('cannot be turned into JSON: ' + value) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Real.coffee b/src/types/Real.coffee index 72a84b0..264fcf0 100644 --- a/src/types/Real.coffee +++ b/src/types/Real.coffee @@ -16,4 +16,14 @@ callback('is not a number: ' + value) else callback(null, processedValue) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Serial.coffee b/src/types/Serial.coffee index 3e32004..e076b0d 100644 --- a/src/types/Serial.coffee +++ b/src/types/Serial.coffee @@ -9,4 +9,14 @@ name: 'Edm.Int64' validate: TypeUtils.validate.integer + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Short Text.coffee b/src/types/Short Text.coffee index 16e11b5..edf7d43 100644 --- a/src/types/Short Text.coffee +++ b/src/types/Short Text.coffee @@ -7,4 +7,14 @@ name: 'Edm.String' validate: TypeUtils.validate.text(255) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Text.coffee b/src/types/Text.coffee index 8eec34f..60e5933 100644 --- a/src/types/Text.coffee +++ b/src/types/Text.coffee @@ -14,4 +14,14 @@ Text: TypeUtils.nativeFactTypeTemplates.equality validate: TypeUtils.validate.text() + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue } diff --git a/src/types/Time.coffee b/src/types/Time.coffee index a2d83f6..c5314d6 100644 --- a/src/types/Time.coffee +++ b/src/types/Time.coffee @@ -18,4 +18,14 @@ callback(err) return callback(null, value.toLocaleTimeString()) + + dataTypeGen: (engine, dataType, necessity, index = '', defaultValue) -> + if defaultValue + @validate defaultValue, true, (err, value) -> + if !err + defaultValue = value + else + defaultValue = null + dbType = @types?[engine] + TypeUtils.dataTypeGen dbType, engine, dataType, necessity, index, defaultValue }