DayOfWeek
代表一星期內七天。
scalar type DayOfWeek extending enum<Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday>;
FuzzyYear
直接extending
int64
。
scalar type FuzzyYear extending int64;
FuzzyMonth
extending
int64
後,再加上一個constraint
,限制其值只能為1~12(註1)。
scalar type FuzzyMonth extending int64 {
constraint expression on (__subject__ >=1 and __subject__ <=12)
}
其中__subject__
代表自身,有點self
或是this
的味道,可以透過expression
來寫出表達式。
FuzzyDay
extending
int64
後,再加上一個constraint
,限制其值只能為1~31。
scalar type FuzzyDay extending int64 {
constraint expression on (__subject__ >=1 and __subject__ <=31)
}
FuzzyHour
extending
int64
後,再加上一個constraint
,限制其值只能為0~23。
scalar type FuzzyHour extending int64 {
constraint expression on (__subject__ >=0 and __subject__ <=23)
}
FuzzyMinute
extending
int64
後,再加上一個constraint
,限制其值只能為0~59。
scalar type FuzzyMinute extending int64 {
constraint expression on (__subject__ >=0 and __subject__ <=59)
}
FuzzySecond
extending
int64
後,再加上一個constraint
,限制其值只能為0~59。
scalar type FuzzySecond extending int64 {
constraint expression on (__subject__ >=0 and __subject__ <=59)
}
FuzzyTime
除了包含前述七個scalar type
為property
外,還加了一個fuzzy_fmt roperty
,一個trigger
及一個constraint
。
type FuzzyTime {
fuzzy_year: FuzzyYear;
fuzzy_month: FuzzyMonth;
fuzzy_day: FuzzyDay;
fuzzy_hour: FuzzyHour;
fuzzy_minute: FuzzyMinute;
fuzzy_second: FuzzySecond;
fuzzy_dow: DayOfWeek;
fuzzy_fmt:= (
with Y:= <str>.fuzzy_year ?? "YYYY",
m:= <str>.fuzzy_month ?? "MM",
m:= m if len(m) > 1 else "0" ++ m,
d:= <str>.fuzzy_day ?? "DD",
d:= d if len(d) > 1 else "0" ++ d,
H:= <str>.fuzzy_hour ?? "HH24",
H:= H if len(H) > 1 else "0" ++ H,
M:= <str>.fuzzy_minute ?? "MI",
M:= M if len(M) > 1 else "0" ++ M,
S:= <str>.fuzzy_second ?? "SS",
S:= S if len(S) > 1 else "0" ++ S,
dow:= <str>.fuzzy_dow ?? "ID",
select Y ++ "/" ++ m ++ "/" ++ d ++ "_" ++
H ++ ":" ++ M ++ ":" ++ S ++ "_" ++
dow
);
trigger fuzzy_month_day_check after insert, update for each
when (exists __new__.fuzzy_month and exists __new__.fuzzy_day)
do (
assert_exists(
cal::to_local_date(
__new__.fuzzy_year ?? 2002,
__new__.fuzzy_month,
__new__.fuzzy_day
)
)
);
constraint exclusive on (.fuzzy_fmt);
}
fuzzy_fmt
為computed property
,為一特殊的str
格式來表達每個FuzzyTime object
。其中??
是指當該scalar type
為空的set
時(即<str>{}
),所給予的預設值。
當同時給定fuzzy_month
及fuzzy_day
時,我們可以透過cal::to_local_date
來驗證這樣的月份與日期,是否為一有效的組合。
逐步拆解各部份語法:
fuzzy_month_day_check
為此trigger
名字,可自行定義。after
至for each
中間,輸入想要trigger
的類型。本例中是想要當對FuzzyTime
進行insert
及update
時,才會觸發trigger
。
trigger fuzzy_month_day_check after insert, update for each
when
為選擇性條件,當其後expression
為true
時,才會觸發trigger
。其中__new__
是指我們想要insert
或update
的object
。
when (exists __new__.fuzzy_month and exists __new__.fuzzy_day)
do
為這個trigger
想要執行的內容。我們這裡使用assert_exists
搭配cal::to_local_date
來驗證給定的月份及日期組合是否合理。當沒有給定年份時,使用??
語法指定為無間道主要劇情時間的2002年。由於我們的fuzzy_day
已經被FuzzyDay
限制在1~31之間,所以這個trigger
可以幫我們去除掉2/30
、2/31
、4/31
、6/31
、9/31
、11/31
等不合理的時間,至於沒有給定年份的2/29
是無法生成的(因為2002年不是閏年)。如果真的要生成2/29
這麼特別的日子,需強制加上年份來鑒別其是否為一合理的時間。
do (
assert_exists(
cal::to_local_date(
__new__.fuzzy_year ?? 2002,
__new__.fuzzy_month,
__new__.fuzzy_day
)
)
);
另外,當您使用略為超過合理時間的日期(如4/31
),cal::to_local_date
報錯訊息會和一般情況不太一樣,會貼心地提示您這個日期剛好超出合理區間。
例如,使用4/31會報錯如下:
edgedb error: InvalidValueError: cal::local_date field value out of range: 2002-04-31
4/40則會報錯如下:
edgedb error: ConstraintViolationError: invalid FuzzyDay
Detail: invalid scalar type 'default::FuzzyDay'
針對fuzzy_fmt
property
加上exclusive
後,可以確保當使用FuzzyTime
時,不會生成一個以上可以表達同一模糊時間的FuzzyTime object
。
註1: EdgeDB內建了許多好用的constraint,可以節省大家寫constraint exression on
的功夫。例如這邊我們可以搭配使用min_value()與max_value()兩個constraint
來取代expression
。