-
Notifications
You must be signed in to change notification settings - Fork 4
/
Value.ToPowerQuery.pq
146 lines (126 loc) · 9.79 KB
/
Value.ToPowerQuery.pq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Value_ToPowerQuery
// Value_ToPowerQuery
/*
serializes values as power query source code
from: https://github.com/microsoft/DataConnectors/blob/master/samples/UnitTesting/UnitTesting.query.pq
*/
let Value.ToPowerQuery = (value, optional depth) =>
let
List.TransformAndCombine = (list, transform, separator) => Text.Combine(List.Transform(list, transform), separator),
Serialize.Binary = (x) => "#binary(" & Serialize(Binary.ToList(x)) & ") ",
Serialize.Function = (x) => _serialize_function_param_type(
Type.FunctionParameters(Value.Type(x)),
Type.FunctionRequiredParameters(Value.Type(x)) ) &
" as " &
_serialize_function_return_type(Value.Type(x)) &
" => (...) ",
Serialize.List = (x) => "{" & List.TransformAndCombine(x, Serialize, ", ") & "} ",
Serialize.Record = (x) => "[ " &
List.TransformAndCombine(
Record.FieldNames(x),
(item) => Serialize.Identifier(item) & " = " & Serialize(Record.Field(x, item)),
", ") &
" ] ",
Serialize.Table = (x) => "#table( type " &
_serialize_table_type(Value.Type(x)) &
", " &
Serialize(Table.ToRows(x)) &
") ",
Serialize.Identifier = Expression.Identifier,
Serialize.Type = (x) => "type " & _serialize_typename(x),
_serialize_typename = (x, optional funtype as logical) => /* Optional parameter: Is this being used as part of a function signature? */
let
isFunctionType = (x as type) => try if Type.FunctionReturn(x) is type then true else false otherwise false,
isTableType = (x as type) => try if Type.TableSchema(x) is table then true else false otherwise false,
isRecordType = (x as type) => try if Type.ClosedRecord(x) is type then true else false otherwise false,
isListType = (x as type) => try if Type.ListItem(x) is type then true else false otherwise false
in
if funtype=null and isTableType(x) then _serialize_table_type(x) else
if funtype=null and isListType(x) then "{ " & @_serialize_typename( Type.ListItem(x) ) & " }" else
if funtype=null and isFunctionType(x) then "function " & _serialize_function_type(x) else
if funtype=null and isRecordType(x) then _serialize_record_type(x) else
if x = type any then "any" else
let base = Type.NonNullable(x) in
(if Type.IsNullable(x) then "nullable " else "") &
(if base = type anynonnull then "anynonnull" else
if base = type binary then "binary" else
if base = type date then "date" else
if base = type datetime then "datetime" else
if base = type datetimezone then "datetimezone" else
if base = type duration then "duration" else
if base = type logical then "logical" else
if base = type none then "none" else
if base = type null then "null" else
if base = type number then "number" else
if base = type text then "text" else
if base = type time then "time" else
if base = type type then "type" else
/* Abstract types: */
if base = type function then "function" else
if base = type table then "table" else
if base = type record then "record" else
if base = type list then "list" else
"any /*Actually unknown type*/"),
_serialize_table_type = (x) =>
let
schema = Type.TableSchema(x)
in
"table " &
(if Table.IsEmpty(schema) then "" else
"[" & List.TransformAndCombine(
Table.ToRecords(Table.Sort(schema,"Position")),
each Serialize.Identifier(_[Name]) & " = " & _[Kind],
", ") &
"] "),
_serialize_record_type = (x) =>
let flds = Type.RecordFields(x)
in
if Record.FieldCount(flds)=0 then "record" else
"[" & List.TransformAndCombine(
Record.FieldNames(flds),
(item) => Serialize.Identifier(item) & "=" & _serialize_typename(Record.Field(flds,item)[Type]),
", ") &
(if Type.IsOpenRecord(x) then ", ..." else "") &
"]",
_serialize_function_type = (x) => _serialize_function_param_type(
Type.FunctionParameters(x),
Type.FunctionRequiredParameters(x) ) &
" as " &
_serialize_function_return_type(x),
_serialize_function_param_type = (t,n) =>
let
funsig = Table.ToRecords(
Table.TransformColumns(
Table.AddIndexColumn( Record.ToTable( t ), "isOptional", 1 ),
{ "isOptional", (x)=> x>n } ) )
in
"(" &
List.TransformAndCombine(
funsig,
(item)=>
(if item[isOptional] then "optional " else "") &
Serialize.Identifier(item[Name]) & " as " & _serialize_typename(item[Value], true),
", ") &
")",
_serialize_function_return_type = (x) => _serialize_typename(Type.FunctionReturn(x), true),
Serialize = (x) as text =>
if x is binary then try Serialize.Binary(x) otherwise "null /*serialize failed*/" else
if x is date then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is datetime then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is datetimezone then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is duration then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is function then try Serialize.Function(x) otherwise "null /*serialize failed*/" else
if x is list then try Serialize.List(x) otherwise "null /*serialize failed*/" else
if x is logical then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is null then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is number then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is record then try Serialize.Record(x) otherwise "null /*serialize failed*/" else
if x is table then try Serialize.Table(x) otherwise "null /*serialize failed*/" else
if x is text then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is time then try Expression.Constant(x) otherwise "null /*serialize failed*/" else
if x is type then try Serialize.Type(x) otherwise "null /*serialize failed*/" else
"[#_unable_to_serialize_#]"
in
try Serialize(value) otherwise "<serialization failed>"
in
Value.ToPowerQuery