diff --git a/go/src/print.go b/go/src/print.go new file mode 100644 index 00000000..e5026e31 --- /dev/null +++ b/go/src/print.go @@ -0,0 +1,1376 @@ +package lqp + +import ( + "bytes" + "fmt" + "math" + "math/big" + "sort" + "strings" + + pb "logical-query-protocol/src/lqp/v1" +) + +// PrettyParams holds parameters for pretty printing +type PrettyParams struct { + w *bytes.Buffer + DebugInfo map[string]string + indentLevel int +} + +// Some helper methods for pretty printing +func (pp PrettyParams) Write(s string) { pp.w.Write([]byte(s)) } + +func (pp PrettyParams) SPACE() { pp.w.Write([]byte(" ")) } +func (pp PrettyParams) NEWLINE() { pp.w.Write([]byte("\n")) } + +// Go doesn't allow hsep and vsep to be a method of pp because it is generic over T +func hsep[T any](pp PrettyParams, x []T, sep string, f func(T)) { + for i, item := range x { + if i > 0 { + pp.Write(sep) + } + f(item) + } +} + +func (pp PrettyParams) writeEscapedString(s string) { + escaped := strings.ReplaceAll(s, "\\", "\\\\") + escaped = strings.ReplaceAll(escaped, "\"", "\\\"") + escaped = strings.ReplaceAll(escaped, "\n", "\\n") + escaped = strings.ReplaceAll(escaped, "\r", "\\r") + escaped = strings.ReplaceAll(escaped, "\t", "\\t") + pp.Write("\"") + pp.Write(escaped) + pp.Write("\"") +} +func vsep[T any](pp PrettyParams, x []T, sep string, f func(T)) { + for i, item := range x { + if i > 0 { + pp.Write(sep) + pp.NEWLINE() + } + f(item) + } +} + +func (pp PrettyParams) PARENS(f func(PrettyParams)) { + pp.Write("(") + f(pp) + pp.Write(")") +} +func (pp PrettyParams) BRACKET(f func(PrettyParams)) { + pp.Write("[") + f(pp) + pp.Write("]") +} +func (pp PrettyParams) BRACES(f func(PrettyParams)) { + pp.Write("{") + f(pp) + pp.Write("}") +} +func (pp PrettyParams) INDENT(n int, f func(PrettyParams)) { + indent := strings.Repeat(" ", n) + + var innerBuf bytes.Buffer + innerPP := PrettyParams{&innerBuf, pp.DebugInfo, pp.indentLevel} + f(innerPP) + + content := innerBuf.String() + indentStr := strings.Repeat(indent, pp.indentLevel+1) + + lines := strings.Split(content, "\n") + for i, line := range lines { + if i > 0 { + pp.w.Write([]byte("\n")) + } + // Don't add trailing spaces for empty lines + if line != "" { + pp.w.Write([]byte(indentStr + line)) + } + } +} + +func (pp PrettyParams) Dump() string { return pp.w.String() } + +func (pp PrettyParams) idToName(rid *pb.RelationId) string { + idStr := relationIdToString(rid) + // Default behavior: print_names=true (use debug names if available) + if len(pp.DebugInfo) == 0 { + return idStr + } + if name, ok := pp.DebugInfo[idStr]; ok { + return ":" + name + } + return idStr +} + +// Main pretty printing function +func (pp PrettyParams) pprint(node interface{}) { + switch n := node.(type) { + case *pb.Transaction: + pp.PARENS(func(pp PrettyParams) { + pp.Write("transaction") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + if n.GetConfigure() != nil { + pp.pprint(n.GetConfigure()) + pp.NEWLINE() + } + if n.GetSync() != nil { + pp.pprint(n.GetSync()) + pp.NEWLINE() + } + for i, epoch := range n.GetEpochs() { + if i > 0 { + pp.NEWLINE() + } + pp.pprint(epoch) + } + }) + }) + + case *pb.Configure: + configDict := make(map[string]interface{}) + if n != nil { + configDict["semantics_version"] = n.GetSemanticsVersion() + ivmConfig := n.GetIvmConfig() + if ivmConfig != nil && ivmConfig.GetLevel() != pb.MaintenanceLevel_MAINTENANCE_LEVEL_UNSPECIFIED { + levelStr := ivmConfig.GetLevel().String() + levelStr = strings.ToLower(strings.TrimPrefix(levelStr, "MAINTENANCE_LEVEL_")) + configDict["ivm.maintenance_level"] = levelStr + } + optimization_level := n.GetOptimizationLevel() + if optimization_level != pb.OptimizationLevel_OPTIMIZATION_LEVEL_UNSPECIFIED{ + levelStr := optimization_level.String() + levelStr = strings.ToLower(strings.TrimPrefix(levelStr, "OPTIMIZATION_LEVEL_")) + configDict["optimization_level"] = levelStr + } + } + pp.PARENS(func(pp PrettyParams) { + pp.Write("configure") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.configDictToStr(configDict) + }) + }) + + case *pb.Sync: + pp.PARENS(func(pp PrettyParams) { + pp.Write("sync") + if len(n.GetFragments()) > 0 { + pp.SPACE() + hsep(pp, n.GetFragments(), " ", func(id *pb.FragmentId) { + pp.pprint(id) + }) + } + }) + + case *pb.Declaration: + if def := n.GetDef(); def != nil { + pp.pprint(def) + } else if alg := n.GetAlgorithm(); alg != nil { + pp.pprint(alg) + } else if constraint := n.GetConstraint(); constraint != nil { + pp.pprint(constraint) + } else if data := n.GetData(); data != nil { + pp.pprint(data) + } + + case *pb.Def: + pp.PARENS(func(pp PrettyParams) { + pp.Write("def") + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(n.GetBody()) + }) + if len(n.GetAttrs()) != 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.Constraint: + if fd := n.GetFunctionalDependency(); fd != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("functional_dependency") + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(fd.GetGuard()) + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("keys") + if len(fd.GetKeys()) > 0 { + pp.SPACE() + for i, v := range fd.GetKeys() { + if i > 0 { + pp.SPACE() + } + pp.pprint(v) + } + } + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("values") + if len(fd.GetValues()) > 0 { + pp.SPACE() + for i, v := range fd.GetValues() { + if i > 0 { + pp.SPACE() + } + pp.pprint(v) + } + } + }) + }) + }) + return + } + + case *pb.Algorithm: + pp.PARENS(func(pp PrettyParams) { + pp.Write("algorithm") + if len(n.GetGlobal()) > 0 { + pp.SPACE() + hsep(pp, n.GetGlobal(), " ", func(id *pb.RelationId) { + pp.pprint(id) + }) + } + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { pp.pprint(n.GetBody()) }) + }) + + case *pb.Script: + pp.PARENS(func(pp PrettyParams) { + pp.Write("script") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n.GetConstructs(), "", func(id *pb.Construct) { + pp.pprint(id) + }) + }) + }) + + case *pb.Data: + if rel := n.GetRelEdb(); rel != nil { + pp.pprint(rel) + } else if betree := n.GetBetreeRelation(); betree != nil { + pp.pprint(betree) + } else if csv := n.GetCsvData(); csv != nil { + pp.pprint(csv) + } + + case *pb.RelEDB: + pp.PARENS(func(pp PrettyParams) { + pp.Write("rel_edb") + pp.SPACE() + pp.pprint(n.GetTargetId()) + pp.SPACE() + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, n.GetPath(), " ", func(path string) { + pp.pprint(path) + }) + }) + pp.SPACE() + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, n.GetTypes(), " ", func(t *pb.Type) { + pp.pprint(t) + }) + }) + }) + + case *pb.BeTreeRelation: + pp.PARENS(func(pp PrettyParams) { + pp.Write("betree_relation") + pp.SPACE() + pp.pprint(n.GetName()) + info := n.GetRelationInfo() + if info != nil { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(info) + }) + } + }) + + case *pb.BeTreeInfo: + pp.PARENS(func(pp PrettyParams) { + pp.Write("betree_info") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.Write("key_types") + if len(n.GetKeyTypes()) > 0 { + pp.SPACE() + hsep(pp, n.GetKeyTypes(), " ", func(t *pb.Type) { + pp.pprint(t) + }) + } + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("value_types") + if len(n.GetValueTypes()) > 0 { + pp.SPACE() + hsep(pp, n.GetValueTypes(), " ", func(t *pb.Type) { + pp.pprint(t) + }) + } + }) + pp.NEWLINE() + configDict := make(map[string]interface{}) + if storage := n.GetStorageConfig(); storage != nil { + configDict["betree_config_epsilon"] = storage.GetEpsilon() + configDict["betree_config_max_pivots"] = storage.GetMaxPivots() + configDict["betree_config_max_deltas"] = storage.GetMaxDeltas() + configDict["betree_config_max_leaf"] = storage.GetMaxLeaf() + } + if locator := n.GetRelationLocator(); locator != nil { + if root := locator.GetRootPageid(); root != nil { + configDict["betree_locator_root_pageid"] = rawString(fmt.Sprintf("0x%s", uint128ToHexString(root.GetLow(), root.GetHigh()))) + } + inline := locator.GetInlineData() + if len(inline) > 0 { + configDict["betree_locator_inline_data"] = string(inline) + } + configDict["betree_locator_element_count"] = locator.GetElementCount() + configDict["betree_locator_tree_height"] = locator.GetTreeHeight() + } + pp.configDictToStr(configDict) + }) + }) + + case *pb.CSVData: + pp.PARENS(func(pp PrettyParams) { + pp.Write("csv_data") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + printed := false + printSection := func(f func()) { + if printed { + pp.NEWLINE() + } + f() + printed = true + } + if locator := n.GetLocator(); locator != nil { + printSection(func() { pp.pprint(locator) }) + } + if config := n.GetConfig(); config != nil { + printSection(func() { pp.pprint(config) }) + } + printSection(func() { + pp.PARENS(func(pp PrettyParams) { + pp.Write("columns") + cols := n.GetColumns() + if len(cols) > 0 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, cols, "", func(col *pb.CSVColumn) { + pp.pprint(col) + }) + }) + } + }) + }) + printSection(func() { + pp.PARENS(func(pp PrettyParams) { + pp.Write("asof") + pp.SPACE() + pp.pprint(n.GetAsof()) + }) + }) + }) + }) + + case *pb.CSVLocator: + pp.PARENS(func(pp PrettyParams) { + pp.Write("csv_locator") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + if len(n.GetPaths()) > 0 { + pp.PARENS(func(pp PrettyParams) { + pp.Write("paths") + pp.SPACE() + hsep(pp, n.GetPaths(), " ", func(path string) { + pp.pprint(path) + }) + }) + } else if inline := n.GetInlineData(); len(inline) > 0 { + pp.PARENS(func(pp PrettyParams) { + pp.Write("inline_data") + pp.SPACE() + pp.pprint(string(inline)) + }) + } + }) + }) + + case *pb.CSVConfig: + pp.PARENS(func(pp PrettyParams) { + pp.Write("csv_config") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + configDict := make(map[string]interface{}) + configDict["csv_header_row"] = n.GetHeaderRow() + configDict["csv_skip"] = n.GetSkip() + if n.GetNewLine() != "" { + configDict["csv_new_line"] = n.GetNewLine() + } + configDict["csv_delimiter"] = n.GetDelimiter() + configDict["csv_quotechar"] = n.GetQuotechar() + configDict["csv_escapechar"] = n.GetEscapechar() + if n.GetComment() != "" { + configDict["csv_comment"] = n.GetComment() + } + missingStrings := n.GetMissingStrings() + if len(missingStrings) > 0 { + configDict["csv_missing_strings"] = missingStrings[0] + } + configDict["csv_decimal_separator"] = n.GetDecimalSeparator() + configDict["csv_encoding"] = n.GetEncoding() + configDict["csv_compression"] = n.GetCompression() + pp.configDictToStr(configDict) + }) + }) + + case *pb.CSVColumn: + pp.PARENS(func(pp PrettyParams) { + pp.Write("column") + pp.SPACE() + pp.pprint(n.GetColumnName()) + pp.SPACE() + pp.pprint(n.GetTargetId()) + pp.SPACE() + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, n.GetTypes(), " ", func(t *pb.Type) { + pp.pprint(t) + }) + }) + }) + + case *pb.Construct: + if loop := n.GetLoop(); loop != nil { + pp.pprint(loop) + return + } else if instr := n.GetInstruction(); instr != nil { + pp.pprint(instr) + return + } + + case *pb.Loop: + pp.PARENS(func(pp PrettyParams) { + pp.Write("loop") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.Write("init") + if len(n.GetInit()) > 0 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n.GetInit(), "", func(id *pb.Instruction) { + pp.pprint(id) + }) + }) + } + }) + pp.NEWLINE() + pp.pprint(n.GetBody()) + }) + }) + + case *pb.Instruction: + if assign := n.GetAssign(); assign != nil { + pp.pprint(assign) + return + } else if upsert := n.GetUpsert(); upsert != nil { + pp.pprint(upsert) + return + } else if brk := n.GetBreak(); brk != nil { + pp.pprint(brk) + return + } else if monoidDef := n.GetMonoidDef(); monoidDef != nil { + pp.pprint(monoidDef) + return + } else if monusDef := n.GetMonusDef(); monusDef != nil { + pp.pprint(monusDef) + return + } + + case *pb.Assign: + pp.PARENS(func(pp PrettyParams) { + pp.Write("assign") + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(n.GetBody()) + }) + if len(n.GetAttrs()) > 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.Break: + pp.PARENS(func(pp PrettyParams) { + pp.Write("break") + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(n.GetBody()) + }) + if len(n.GetAttrs()) > 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.Upsert: + pp.PARENS(func(pp PrettyParams) { + pp.Write("upsert") + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + body := n.GetBody() + if n.GetValueArity() == 0 { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(body) + }) + } else { + partition := len(body.GetVars()) - int(n.GetValueArity()) + lvars := body.GetVars()[:partition] + rvars := body.GetVars()[partition:] + pp.PARENS(func(pp PrettyParams) { + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, lvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + pp.SPACE() + pp.Write("|") + pp.SPACE() + hsep(pp, rvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + }) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(body.GetValue()) + }) + }) + } + if len(n.GetAttrs()) > 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.MonoidDef: + pp.PARENS(func(pp PrettyParams) { + pp.Write("monoid") + pp.SPACE() + pp.pprint(n.GetMonoid()) + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + body := n.GetBody() + if n.GetValueArity() == 0 { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(body) + }) + } else { + partition := len(body.GetVars()) - int(n.GetValueArity()) + lvars := body.GetVars()[:partition] + rvars := body.GetVars()[partition:] + pp.PARENS(func(pp PrettyParams) { + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, lvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + pp.SPACE() + pp.Write("|") + pp.SPACE() + hsep(pp, rvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + }) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(body.GetValue()) + }) + }) + } + if len(n.GetAttrs()) > 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.MonusDef: + pp.PARENS(func(pp PrettyParams) { + pp.Write("monus") + pp.SPACE() + pp.pprint(n.GetMonoid()) + pp.SPACE() + pp.pprint(n.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + body := n.GetBody() + if n.GetValueArity() == 0 { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(body) + }) + } else { + partition := len(body.GetVars()) - int(n.GetValueArity()) + lvars := body.GetVars()[:partition] + rvars := body.GetVars()[partition:] + pp.PARENS(func(pp PrettyParams) { + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, lvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + pp.SPACE() + pp.Write("|") + pp.SPACE() + hsep(pp, rvars, " ", func(x *pb.Binding) { pp.pprint(x) }) + }) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(body.GetValue()) + }) + }) + } + if len(n.GetAttrs()) > 0 { + pp.NEWLINE() + pp.pprint(n.GetAttrs()) + } + }) + }) + + case *pb.Monoid: + if n.GetOrMonoid() != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("or") + }) + } else if minMonoid := n.GetMinMonoid(); minMonoid != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("min") + pp.SPACE() + pp.pprint(minMonoid.GetType()) + }) + } else if maxMonoid := n.GetMaxMonoid(); maxMonoid != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("max") + pp.SPACE() + pp.pprint(maxMonoid.GetType()) + }) + } else if sumMonoid := n.GetSumMonoid(); sumMonoid != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("sum") + pp.SPACE() + pp.pprint(sumMonoid.GetType()) + }) + } + + case *pb.Type: + switch { + case n.GetUnspecifiedType() != nil: + pp.Write("UNSPECIFIED") + case n.GetStringType() != nil: + pp.Write("STRING") + case n.GetIntType() != nil: + pp.Write("INT") + case n.GetFloatType() != nil: + pp.Write("FLOAT") + case n.GetUint128Type() != nil: + pp.Write("UINT128") + case n.GetInt128Type() != nil: + pp.Write("INT128") + case n.GetDateType() != nil: + pp.Write("DATE") + case n.GetDatetimeType() != nil: + pp.Write("DATETIME") + case n.GetMissingType() != nil: + pp.Write("MISSING") + case n.GetDecimalType() != nil: + pp.PARENS(func(pp PrettyParams) { + decType := n.GetDecimalType() + pp.Write("DECIMAL") + pp.SPACE() + pp.pprint(decType.GetPrecision()) + pp.SPACE() + pp.pprint(decType.GetScale()) + }) + case n.GetBooleanType() != nil: + pp.Write("BOOLEAN") + default: + pp.Write("UNKNOWN") + } + + case *pb.Abstraction: + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, n.GetVars(), " ", func(x *pb.Binding) { pp.pprint(x) }) + }) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { pp.pprint(n.GetValue()) }) + case *pb.Formula: + if exists := n.GetExists(); exists != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("exists") + pp.SPACE() + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, exists.GetBody().GetVars(), " ", func(x *pb.Binding) { + pp.pprint(x) + }) + }) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(exists.GetBody().GetValue()) + }) + }) + } else if reduce := n.GetReduce(); reduce != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("reduce") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.pprint(reduce.GetOp()) + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.pprint(reduce.GetBody()) + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("terms") + if len(reduce.GetTerms()) > 0 { + pp.SPACE() + hsep(pp, reduce.GetTerms(), " ", func(id *pb.Term) { + pp.pprint(id) + }) + } + }) + }) + }) + } else if conj := n.GetConjunction(); conj != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("and") + if len(conj.GetArgs()) > 0 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, conj.GetArgs(), "", func(id *pb.Formula) { + pp.pprint(id) + }) + }) + } + }) + } else if disj := n.GetDisjunction(); disj != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("or") + if len(disj.GetArgs()) > 0 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, disj.GetArgs(), "", func(id *pb.Formula) { + pp.pprint(id) + }) + }) + } + }) + } else if not := n.GetNot(); not != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("not") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.pprint(not.GetArg()) + }) + }) + } else if ffi := n.GetFfi(); ffi != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("ffi") + pp.SPACE() + pp.Write(":") + pp.Write(ffi.GetName()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.Write("args") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + // Wrap each abstraction in PARENS + for i, arg := range ffi.GetArgs() { + if i > 0 { + pp.NEWLINE() + } + pp.PARENS(func(pp PrettyParams) { + pp.pprint(arg) + }) + } + }) + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("terms") + if len(ffi.GetTerms()) > 0 { + pp.SPACE() + hsep(pp, ffi.GetTerms(), " ", func(id *pb.Term) { + pp.pprint(id) + }) + } + }) + }) + }) + } else if atom := n.GetAtom(); atom != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("atom") + pp.SPACE() + pp.pprint(atom.GetName()) + if len(atom.GetTerms()) > 4 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, atom.GetTerms(), "", func(id *pb.Term) { + pp.pprint(id) + }) + }) + } else { + pp.SPACE() + hsep(pp, atom.GetTerms(), " ", func(id *pb.Term) { + pp.pprint(id) + }) + } + }) + } else if pragma := n.GetPragma(); pragma != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("pragma") + pp.SPACE() + pp.Write(":") + pp.Write(pragma.GetName()) + if len(pragma.GetTerms()) > 4 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, pragma.GetTerms(), "", func(id *pb.Term) { + pp.pprint(id) + }) + }) + } else { + pp.SPACE() + hsep(pp, pragma.GetTerms(), " ", func(id *pb.Term) { + pp.pprint(id) + }) + } + }) + } else if primitive := n.GetPrimitive(); primitive != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("primitive") + pp.SPACE() + pp.Write(":") + pp.Write(primitive.GetName()) + if len(primitive.GetTerms()) > 4 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, primitive.GetTerms(), "", func(id *pb.RelTerm) { + pp.pprint(id) + }) + }) + } else { + pp.SPACE() + hsep(pp, primitive.GetTerms(), " ", func(id *pb.RelTerm) { + pp.pprint(id) + }) + } + }) + } else if relAtom := n.GetRelAtom(); relAtom != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("relatom") + pp.SPACE() + pp.Write(":") + pp.Write(relAtom.GetName()) + if len(relAtom.GetTerms()) > 4 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, relAtom.GetTerms(), "", func(id *pb.RelTerm) { + pp.pprint(id) + }) + }) + } else { + pp.SPACE() + hsep(pp, relAtom.GetTerms(), " ", func(id *pb.RelTerm) { + pp.pprint(id) + }) + } + }) + } else if cast := n.GetCast(); cast != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("cast") + pp.SPACE() + pp.pprint(cast.GetInput()) + pp.SPACE() + pp.pprint(cast.GetResult()) + }) + } + + case *pb.Term: + if v := n.GetVar(); v != nil { + pp.Write(v.GetName()) + } else if val := n.GetConstant(); val != nil { + pp.pprint(val) + } + + case *pb.RelTerm: + if term := n.GetTerm(); term != nil { + pp.pprint(term) + return + } else if spec := n.GetSpecializedValue(); spec != nil { + pp.Write("#") + pp.pprint(spec) + } + + case *pb.Attribute: + pp.PARENS(func(pp PrettyParams) { + pp.Write("attribute") + pp.SPACE() + pp.Write(":") + pp.Write(n.GetName()) + if len(n.GetArgs()) > 0 { + pp.SPACE() + hsep(pp, n.GetArgs(), " ", func(id *pb.Value) { + pp.pprint(id) + }) + } + }) + case *pb.RelationId: + name := pp.idToName(n) + pp.Write(name) + + case *pb.Write: + if define := n.GetDefine(); define != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("define") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { pp.pprint(define.GetFragment()) }) + }) + } else if undef := n.GetUndefine(); undef != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("undefine") + pp.SPACE() + pp.pprint(undef.GetFragmentId()) + }) + } else if ctx := n.GetContext(); ctx != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("context") + pp.SPACE() + pp.BRACKET(func(pp PrettyParams) { + hsep(pp, ctx.GetRelations(), " ", func(id *pb.RelationId) { + pp.pprint(id) + }) + }) + }) + } + + case *pb.FragmentId: + // Decode fragment ID as string (it's stored as UTF-8 bytes) + idStr := string(n.GetId()) + if idStr == "" { + idStr = "empty" + } + pp.Write(":") + pp.Write(idStr) + + case *pb.Read: + if demand := n.GetDemand(); demand != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("demand") + pp.SPACE() + pp.pprint(demand.GetRelationId()) + }) + } else if output := n.GetOutput(); output != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("output") + pp.SPACE() + pp.Write(":") + pp.Write(output.GetName()) + pp.SPACE() + pp.pprint(output.GetRelationId()) + }) + } else if export := n.GetExport(); export != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("export") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { pp.pprint(export.GetCsvConfig()) }) + }) + } else if whatIf := n.GetWhatIf(); whatIf != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("whatif") + pp.SPACE() + pp.Write(":") + pp.Write(whatIf.GetBranch()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { pp.pprint(whatIf.GetEpoch()) }) + }) + } else if abort := n.GetAbort(); abort != nil { + pp.PARENS(func(pp PrettyParams) { + pp.Write("abort") + pp.SPACE() + pp.Write(":") + pp.Write(abort.GetName()) + pp.SPACE() + pp.pprint(abort.GetRelationId()) + }) + } + + case *pb.ExportCSVConfig: + pp.PARENS(func(pp PrettyParams) { + pp.Write("export_csv_config") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.PARENS(func(pp PrettyParams) { + pp.Write("path") + pp.SPACE() + pp.pprint(n.GetPath()) + }) + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("columns") + pp.SPACE() + hsep(pp, n.GetDataColumns(), " ", func(x *pb.ExportCSVColumn) { + pp.pprint(x) + }) + }) + pp.NEWLINE() + configDict := make(map[string]interface{}) + configDict["partition_size"] = n.GetPartitionSize() + configDict["compression"] = n.GetCompression() + if n.GetSyntaxHeaderRow() { + configDict["syntax_header_row"] = 1 + } else { + configDict["syntax_header_row"] = 0 + } + configDict["syntax_missing_string"] = n.GetSyntaxMissingString() + configDict["syntax_delim"] = n.GetSyntaxDelim() + configDict["syntax_quotechar"] = n.GetSyntaxQuotechar() + configDict["syntax_escapechar"] = n.GetSyntaxEscapechar() + pp.configDictToStr(configDict) + }) + }) + + case *pb.ExportCSVColumn: + pp.PARENS(func(pp PrettyParams) { + pp.Write("column") + pp.SPACE() + pp.pprint(n.GetColumnName()) + pp.SPACE() + pp.pprint(n.GetColumnData()) + }) + + case *pb.Epoch: + pp.PARENS(func(pp PrettyParams) { + pp.Write("epoch") + pp.INDENT(2, func(pp PrettyParams) { + if len(n.GetWrites()) > 0 { + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("writes") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n.GetWrites(), "", func(w *pb.Write) { + pp.pprint(w) + }) + }) + }) + } + if len(n.GetReads()) > 0 { + pp.NEWLINE() + pp.PARENS(func(pp PrettyParams) { + pp.Write("reads") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n.GetReads(), "", func(w *pb.Read) { + pp.pprint(w) + }) + }) + }) + } + }) + }) + + case *pb.Fragment: + pp.PARENS(func(pp PrettyParams) { + pp.Write("fragment") + pp.SPACE() + pp.pprint(n.GetId()) + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n.GetDeclarations(), "", func(id *pb.Declaration) { + pp.pprint(id) + }) + }) + }) + + case *pb.Binding: + pp.Write(n.GetVar().GetName()) + pp.Write("::") + pp.pprint(n.GetType()) + + case *pb.Var: + pp.Write(n.GetName()) + + case *pb.Value: + // Handle Value oneof - check the actual oneof type + switch n.GetValue().(type) { + case *pb.Value_StringValue: + pp.writeEscapedString(n.GetStringValue()) + case *pb.Value_IntValue: + pp.Write(fmt.Sprintf("%d", n.GetIntValue())) + case *pb.Value_FloatValue: + floatVal := n.GetFloatValue() + if math.IsInf(floatVal, 0) { + pp.Write("inf") + } else if math.IsNaN(floatVal) { + pp.Write("nan") + } else if floatVal == float64(int64(floatVal)) { + pp.Write(fmt.Sprintf("%.1f", floatVal)) + } else { + pp.Write(fmt.Sprintf("%v", floatVal)) + } + case *pb.Value_Uint128Value: + uint128 := n.GetUint128Value() + pp.Write("0x") + pp.Write(uint128ToHexString(uint128.GetLow(), uint128.GetHigh())) + case *pb.Value_Int128Value: + int128 := n.GetInt128Value() + result := int128ToString(int128.GetLow(), int128.GetHigh()) + pp.Write(result) + pp.Write("i128") + case *pb.Value_MissingValue: + pp.Write("missing") + case *pb.Value_DateValue: + date := n.GetDateValue() + pp.PARENS(func(pp PrettyParams) { + pp.Write("date") + pp.SPACE() + pp.Write(fmt.Sprintf("%d %d %d", date.GetYear(), date.GetMonth(), date.GetDay())) + }) + case *pb.Value_DatetimeValue: + datetime := n.GetDatetimeValue() + pp.PARENS(func(pp PrettyParams) { + pp.Write("datetime") + pp.SPACE() + pp.Write(fmt.Sprintf("%d %d %d %d %d %d %d", + datetime.GetYear(), datetime.GetMonth(), datetime.GetDay(), + datetime.GetHour(), datetime.GetMinute(), datetime.GetSecond(), + datetime.GetMicrosecond())) + }) + case *pb.Value_DecimalValue: + decimal := n.GetDecimalValue() + int128Val := decimal.GetValue() + if int128Val != nil { + // Get the raw integer value (using int128 for proper sign handling) + rawValue := int128ToString(int128Val.GetLow(), int128Val.GetHigh()) + precision := decimal.GetPrecision() + scale := decimal.GetScale() + + // Handle negative sign separately + isNegative := strings.HasPrefix(rawValue, "-") + if isNegative { + rawValue = rawValue[1:] // Remove the negative sign temporarily + } + + // Format as decimal with proper placement of decimal point + // The raw value is the number * 10^scale + // We need to insert a decimal point 'scale' digits from the right + var decStr string + if scale == 0 { + // No decimal point needed + decStr = rawValue + } else { + // Need to add decimal point + if len(rawValue) <= int(scale) { + // Need leading zeros: e.g., "5" with scale 3 -> "0.005" + leadingZeros := int(scale) - len(rawValue) + decStr = "0." + strings.Repeat("0", leadingZeros) + rawValue + } else { + // Insert decimal point: e.g., "12345" with scale 3 -> "12.345" + insertPos := len(rawValue) - int(scale) + decStr = rawValue[:insertPos] + "." + rawValue[insertPos:] + } + } + + // Add back the negative sign if needed + if isNegative { + decStr = "-" + decStr + } + + pp.Write(decStr) + pp.Write("d") + pp.Write(fmt.Sprintf("%d", precision)) + } + case *pb.Value_BooleanValue: + if n.GetBooleanValue() { + pp.Write("true") + } else { + pp.Write("false") + } + } + + case []*pb.Attribute: + pp.PARENS(func(pp PrettyParams) { + pp.Write("attrs") + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + vsep(pp, n, "", func(id *pb.Attribute) { + pp.pprint(id) + }) + }) + }) + + case string: + pp.writeEscapedString(n) + + case int: + pp.Write(fmt.Sprintf("%d", n)) + + case int32: + pp.Write(fmt.Sprintf("%d", n)) + + case int64: + pp.Write(fmt.Sprintf("%d", n)) + + case uint32: + pp.Write(fmt.Sprintf("%d", n)) + + case uint64: + pp.Write(fmt.Sprintf("%d", n)) + + default: + panic(fmt.Sprintf("pprint not implemented for %T", node)) + } +} + +// Small traversal to collect DebugInfos +func collectDebugInfos(node interface{}) map[string]string { + debugInfos := make(map[string]string) + + switch n := node.(type) { + case *pb.Fragment: + debugInfo := n.GetDebugInfo() + if debugInfo != nil { + ids := debugInfo.GetIds() + names := debugInfo.GetOrigNames() + for i, id := range ids { + if i < len(names) { + debugInfos[relationIdToString(id)] = names[i] + } + } + } + case *pb.Transaction: + for _, epoch := range n.GetEpochs() { + for _, write := range epoch.GetWrites() { + if define := write.GetDefine(); define != nil { + for k, v := range collectDebugInfos(define.GetFragment()) { + debugInfos[k] = v + } + } + } + } + } + + return debugInfos +} + +type rawString string + +func writeConfigValue(pp PrettyParams, value interface{}) { + switch v := value.(type) { + case rawString: + pp.Write(string(v)) + case string: + pp.Write(fmt.Sprintf("%q", v)) + default: + pp.Write(fmt.Sprintf("%v", v)) + } +} + +func (pp PrettyParams) configDictToStr(config map[string]interface{}) { + keys := make([]string, 0, len(config)) + for k := range config { + keys = append(keys, k) + } + sort.Strings(keys) + + pp.BRACES(func(pp PrettyParams) { + pp.SPACE() + for i, k := range keys { + if i > 0 { + pp.NEWLINE() + pp.INDENT(2, func(pp PrettyParams) { + pp.Write(":") + pp.Write(k) + pp.SPACE() + writeConfigValue(pp, config[k]) + }) + } else { + pp.Write(":") + pp.Write(k) + pp.SPACE() + writeConfigValue(pp, config[k]) + } + } + }) +} + +// Value-specific print functions +func uint128ToString(low, high uint64) string { + if high == 0 { + return fmt.Sprintf("%d", low) + } + // Convert to big.Int for proper display + result := new(big.Int).SetUint64(high) + result.Lsh(result, 64) + result.Add(result, new(big.Int).SetUint64(low)) + + return result.String() +} + +func int128ToString(low, high uint64) string { + isNegative := (high & 0x8000000000000000) != 0 + + if !isNegative { + return uint128ToString(low, high) + } + + result := new(big.Int).SetUint64(^high) + result.Lsh(result, 64) + result.Add(result, new(big.Int).SetUint64(^low)) + result.Add(result, big.NewInt(1)) + + return "-" + result.String() +} + +func uint128ToHexString(low, high uint64) string { + if high == 0 { + return fmt.Sprintf("%x", low) + } + return fmt.Sprintf("%x%016x", high, low) +} + +func relationIdToString(rid *pb.RelationId) string { + return "0x" + uint128ToHexString(rid.GetIdLow(), rid.GetIdHigh()) +} + +// Entry point +func ProgramToStr(node *pb.Transaction) string { + debugInfo := collectDebugInfos(node) + var buf bytes.Buffer + + pp := PrettyParams{&buf, debugInfo, 0} + pp.pprint(node) + pp.NEWLINE() + return pp.Dump() +} diff --git a/julia/LQPParser/Manifest.toml b/julia/LQPParser/Manifest.toml new file mode 100644 index 00000000..90238a62 --- /dev/null +++ b/julia/LQPParser/Manifest.toml @@ -0,0 +1,66 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.2" +manifest_format = "2.0" +project_hash = "587d3049ed50c675b827f51e5f2e2828932b1397" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.BufferedStreams]] +git-tree-sha1 = "6863c5b7fc997eadcabdbaf6c5f201dc30032643" +uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d" +version = "1.2.2" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.EnumX]] +git-tree-sha1 = "7bebc8aad6ee6217c78c5ddcf7ed289d65d0263e" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.6" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.ProtoBuf]] +deps = ["BufferedStreams", "Dates", "EnumX", "TOML"] +git-tree-sha1 = "eabdb811dbacadc9d7e0dee9ac11c1a12705e12a" +uuid = "3349acd9-ac6a-5e09-bcdb-63829b23a429" +version = "1.2.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" diff --git a/julia/LQPParser/src/parser.jl b/julia/LQPParser/src/parser.jl new file mode 100644 index 00000000..04bc24e5 --- /dev/null +++ b/julia/LQPParser/src/parser.jl @@ -0,0 +1,3455 @@ +""" +Auto-generated LL(k) recursive-descent parser. + +Generated from protobuf specifications. +Do not modify this file! If you need to modify the parser, edit the generator code +in `python-tools/src/meta` or edit the protobuf specification in `proto/v1`. + + +Command: python -m meta.cli ../proto/relationalai/lqp/v1/fragments.proto ../proto/relationalai/lqp/v1/logic.proto ../proto/relationalai/lqp/v1/transactions.proto --grammar src/meta/grammar.y --parser julia +""" + +using SHA +using ProtoBuf: OneOf + +# Import protobuf modules +include("proto_generated.jl") +using .Proto + + +function _has_proto_field(obj, field_sym::Symbol)::Bool + if hasproperty(obj, field_sym) + return !isnothing(getproperty(obj, field_sym)) + end + for fname in fieldnames(typeof(obj)) + fval = getfield(obj, fname) + if fval isa OneOf && fval.name == field_sym + return true + end + end + return false +end + +function _get_oneof_field(obj, field_sym::Symbol) + for fname in fieldnames(typeof(obj)) + fval = getfield(obj, fname) + if fval isa OneOf && fval.name == field_sym + return fval[] + end + end + error("No oneof field $field_sym on $(typeof(obj))") +end + + +struct ParseError <: Exception + msg::String +end + +Base.showerror(io::IO, e::ParseError) = print(io, "ParseError: ", e.msg) + + +struct Token + type::String + value::Any + pos::Int +end + +Base.show(io::IO, t::Token) = print(io, "Token(", t.type, ", ", repr(t.value), ", ", t.pos, ")") + + +mutable struct Lexer + input::String + pos::Int + tokens::Vector{Token} + + function Lexer(input::String) + lexer = new(input, 1, Token[]) + tokenize!(lexer) + return lexer + end +end + + +function tokenize!(lexer::Lexer) + token_specs = [ + ("LITERAL", r"::", identity), + ("LITERAL", r"<=", identity), + ("LITERAL", r">=", identity), + ("LITERAL", r"\#", identity), + ("LITERAL", r"\(", identity), + ("LITERAL", r"\)", identity), + ("LITERAL", r"\*", identity), + ("LITERAL", r"\+", identity), + ("LITERAL", r"\-", identity), + ("LITERAL", r"/", identity), + ("LITERAL", r":", identity), + ("LITERAL", r"<", identity), + ("LITERAL", r"=", identity), + ("LITERAL", r">", identity), + ("LITERAL", r"\[", identity), + ("LITERAL", r"\]", identity), + ("LITERAL", r"\{", identity), + ("LITERAL", r"\|", identity), + ("LITERAL", r"\}", identity), + ("DECIMAL", r"[-]?\d+\.\d+d\d+", scan_decimal), + ("FLOAT", r"[-]?\d+\.\d+|inf|nan", scan_float), + ("INT", r"[-]?\d+", scan_int), + ("INT128", r"[-]?\d+i128", scan_int128), + ("STRING", r"\"(?:[^\"\\]|\\.)*\"", scan_string), + ("SYMBOL", r"[a-zA-Z_][a-zA-Z0-9_.-]*", scan_symbol), + ("UINT128", r"0x[0-9a-fA-F]+", scan_uint128), + ] + + whitespace_re = r"\s+" + comment_re = r";;.*" + + # Use ncodeunits for byte-based position tracking (UTF-8 safe) + while lexer.pos <= ncodeunits(lexer.input) + # Skip whitespace + m = match(whitespace_re, lexer.input, lexer.pos) + if m !== nothing && m.offset == lexer.pos + lexer.pos = m.offset + ncodeunits(m.match) + continue + end + + # Skip comments + m = match(comment_re, lexer.input, lexer.pos) + if m !== nothing && m.offset == lexer.pos + lexer.pos = m.offset + ncodeunits(m.match) + continue + end + + # Collect all matching tokens + candidates = Tuple{String,String,Function,Int}[] + + for (token_type, regex, action) in token_specs + m = match(regex, lexer.input, lexer.pos) + if m !== nothing && m.offset == lexer.pos + value = m.match + push!(candidates, (token_type, value, action, m.offset + ncodeunits(value))) + end + end + + if isempty(candidates) + throw(ParseError("Unexpected character at position $(lexer.pos): $(repr(lexer.input[lexer.pos]))")) + end + + # Pick the longest match + token_type, value, action, end_pos = candidates[argmax([c[4] for c in candidates])] + push!(lexer.tokens, Token(token_type, action(value), lexer.pos)) + lexer.pos = end_pos + end + + push!(lexer.tokens, Token("\$", "", lexer.pos)) + return nothing +end + + +# Scanner functions for each token type +scan_symbol(s::String) = s +scan_colon_symbol(s::String) = chop(s, head=1, tail=0) + +function scan_string(s::String) + # Strip quotes using Unicode-safe chop (handles multi-byte characters) + content = chop(s, head=1, tail=1) + # Simple escape processing - Julia handles most escapes natively + result = replace(content, "\\n" => "\n") + result = replace(result, "\\t" => "\t") + result = replace(result, "\\r" => "\r") + result = replace(result, "\\\\" => "\\") + result = replace(result, "\\\"" => "\"") + return result +end + +scan_int(n::String) = Base.parse(Int64, n) + +function scan_float(f::String) + if f == "inf" + return Inf + elseif f == "nan" + return NaN + end + return Base.parse(Float64, f) +end + +function scan_uint128(u::String) + # Remove the '0x' prefix + hex_str = u[3:end] + uint128_val = Base.parse(UInt128, hex_str, base=16) + low = UInt64(uint128_val & 0xFFFFFFFFFFFFFFFF) + high = UInt64((uint128_val >> 64) & 0xFFFFFFFFFFFFFFFF) + return Proto.UInt128Value(low, high) +end + +function scan_int128(u::String) + # Remove the 'i128' suffix + u = u[1:end-4] + int128_val = Base.parse(Int128, u) + low = UInt64(int128_val & 0xFFFFFFFFFFFFFFFF) + high = UInt64((int128_val >> 64) & 0xFFFFFFFFFFFFFFFF) + return Proto.Int128Value(low, high) +end + +function scan_decimal(d::String) + # Decimal is a string like '123.456d12' where the last part after `d` is the + # precision, and the scale is the number of digits between the decimal point and `d` + parts = split(d, 'd') + if length(parts) != 2 + throw(ArgumentError("Invalid decimal format: $d")) + end + scale = length(split(parts[1], '.')[2]) + precision = Base.parse(Int32, parts[2]) + # Parse the integer value + int_str = replace(parts[1], "." => "") + int128_val = Base.parse(Int128, int_str) + low = UInt64(int128_val & 0xFFFFFFFFFFFFFFFF) + high = UInt64((int128_val >> 64) & 0xFFFFFFFFFFFFFFFF) + value = Proto.Int128Value(low, high) + return Proto.DecimalValue(precision, scale, value) +end + + +mutable struct Parser + tokens::Vector{Token} + pos::Int + id_to_debuginfo::Dict{Vector{UInt8},Vector{Pair{Tuple{UInt64,UInt64},String}}} + _current_fragment_id::Union{Nothing,Vector{UInt8}} + _relation_id_to_name::Dict{Tuple{UInt64,UInt64},String} + + function Parser(tokens::Vector{Token}) + return new(tokens, 1, Dict(), nothing, Dict()) + end +end + + +function lookahead(parser::Parser, k::Int=0)::Token + idx = parser.pos + k + return idx <= length(parser.tokens) ? parser.tokens[idx] : Token("\$", "", -1) +end + + +function consume_literal!(parser::Parser, expected::String) + if !match_lookahead_literal(parser, expected, 0) + token = lookahead(parser, 0) + throw(ParseError("Expected literal $(repr(expected)) but got $(token.type)=`$(repr(token.value))` at position $(token.pos)")) + end + parser.pos += 1 + return nothing +end + + +function consume_terminal!(parser::Parser, expected::String) + if !match_lookahead_terminal(parser, expected, 0) + token = lookahead(parser, 0) + throw(ParseError("Expected terminal $expected but got $(token.type)=`$(repr(token.value))` at position $(token.pos)")) + end + token = lookahead(parser, 0) + parser.pos += 1 + return token.value +end + + +function match_lookahead_literal(parser::Parser, literal::String, k::Int)::Bool + token = lookahead(parser, k) + # Support soft keywords: alphanumeric literals are lexed as SYMBOL tokens + if token.type == "LITERAL" && token.value == literal + return true + end + if token.type == "SYMBOL" && token.value == literal + return true + end + return false +end + + +function match_lookahead_terminal(parser::Parser, terminal::String, k::Int)::Bool + token = lookahead(parser, k) + return token.type == terminal +end + + +function start_fragment!(parser::Parser, fragment_id::Proto.FragmentId) + parser._current_fragment_id = fragment_id.id + return fragment_id +end + + +function relation_id_from_string(parser::Parser, name::String) + # Create RelationId from string and track mapping for debug info + hash_bytes = sha256(name) + val = Base.parse(UInt64, bytes2hex(hash_bytes[1:8]), base=16) + id_low = UInt64(val & 0xFFFFFFFFFFFFFFFF) + id_high = UInt64((val >> 64) & 0xFFFFFFFFFFFFFFFF) + relation_id = Proto.RelationId(id_low, id_high) + + # Store the mapping for the current fragment if we're inside one + if parser._current_fragment_id !== nothing + if !haskey(parser.id_to_debuginfo, parser._current_fragment_id) + parser.id_to_debuginfo[parser._current_fragment_id] = Pair{Tuple{UInt64,UInt64},String}[] + end + entries = parser.id_to_debuginfo[parser._current_fragment_id] + key = (relation_id.id_low, relation_id.id_high) + if !any(p -> p.first == key, entries) + push!(entries, key => name) + end + end + + return relation_id +end + +function construct_fragment( + parser::Parser, + fragment_id::Proto.FragmentId, + declarations::Vector{Proto.Declaration} +) + # Get the debug info for this fragment + debug_info_entries = get(parser.id_to_debuginfo, fragment_id.id, Pair{Tuple{UInt64,UInt64},String}[]) + + # Convert to DebugInfo protobuf (preserving insertion order) + ids = Proto.RelationId[] + orig_names = String[] + for (key, name) in debug_info_entries + push!(ids, Proto.RelationId(key[1], key[2])) + push!(orig_names, name) + end + + # Create DebugInfo + debug_info = Proto.DebugInfo(ids, orig_names) + + # Clear _current_fragment_id before the return + parser._current_fragment_id = nothing + + # Create and return Fragment + return Proto.Fragment(fragment_id, declarations, debug_info) +end + +# --- Helper functions --- + +function _extract_value_int64(parser::Parser, value::Union{Nothing, Proto.Value}, default::Int64)::Int64 + if (!isnothing(value) && _has_proto_field(value, Symbol("int_value"))) + return _get_oneof_field(value, :int_value) + end + return default +end + +function _extract_value_float64(parser::Parser, value::Union{Nothing, Proto.Value}, default::Float64)::Float64 + if (!isnothing(value) && _has_proto_field(value, Symbol("float_value"))) + return _get_oneof_field(value, :float_value) + end + return default +end + +function _extract_value_string(parser::Parser, value::Union{Nothing, Proto.Value}, default::String)::String + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return _get_oneof_field(value, :string_value) + end + return default +end + +function _extract_value_boolean(parser::Parser, value::Union{Nothing, Proto.Value}, default::Bool)::Bool + if (!isnothing(value) && _has_proto_field(value, Symbol("boolean_value"))) + return _get_oneof_field(value, :boolean_value) + end + return default +end + +function _extract_value_bytes(parser::Parser, value::Union{Nothing, Proto.Value}, default::Vector{UInt8})::Vector{UInt8} + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return Vector{UInt8}(_get_oneof_field(value, :string_value)) + end + return default +end + +function _extract_value_uint128(parser::Parser, value::Union{Nothing, Proto.Value}, default::Proto.UInt128Value)::Proto.UInt128Value + if (!isnothing(value) && _has_proto_field(value, Symbol("uint128_value"))) + return _get_oneof_field(value, :uint128_value) + end + return default +end + +function _extract_value_string_list(parser::Parser, value::Union{Nothing, Proto.Value}, default::Vector{String})::Vector{String} + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return String[_get_oneof_field(value, :string_value)] + end + return default +end + +function _try_extract_value_int64(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, Int64} + if (!isnothing(value) && _has_proto_field(value, Symbol("int_value"))) + return _get_oneof_field(value, :int_value) + end + return nothing +end + +function _try_extract_value_float64(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, Float64} + if (!isnothing(value) && _has_proto_field(value, Symbol("float_value"))) + return _get_oneof_field(value, :float_value) + end + return nothing +end + +function _try_extract_value_string(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, String} + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return _get_oneof_field(value, :string_value) + end + return nothing +end + +function _try_extract_value_bytes(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, Vector{UInt8}} + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return Vector{UInt8}(_get_oneof_field(value, :string_value)) + end + return nothing +end + +function _try_extract_value_uint128(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, Proto.UInt128Value} + if (!isnothing(value) && _has_proto_field(value, Symbol("uint128_value"))) + return _get_oneof_field(value, :uint128_value) + end + return nothing +end + +function _try_extract_value_string_list(parser::Parser, value::Union{Nothing, Proto.Value})::Union{Nothing, Vector{String}} + if (!isnothing(value) && _has_proto_field(value, Symbol("string_value"))) + return String[_get_oneof_field(value, :string_value)] + end + return nothing +end + +function construct_csv_config(parser::Parser, config_dict::Vector{Tuple{String, Proto.Value}})::Proto.CSVConfig + config = Dict(config_dict) + _t946 = _extract_value_int64(parser, get(config, "csv_header_row", nothing), 1) + header_row = _t946 + _t947 = _extract_value_int64(parser, get(config, "csv_skip", nothing), 0) + skip = _t947 + _t948 = _extract_value_string(parser, get(config, "csv_new_line", nothing), "") + new_line = _t948 + _t949 = _extract_value_string(parser, get(config, "csv_delimiter", nothing), ",") + delimiter = _t949 + _t950 = _extract_value_string(parser, get(config, "csv_quotechar", nothing), "\"") + quotechar = _t950 + _t951 = _extract_value_string(parser, get(config, "csv_escapechar", nothing), "\"") + escapechar = _t951 + _t952 = _extract_value_string(parser, get(config, "csv_comment", nothing), "") + comment = _t952 + _t953 = _extract_value_string_list(parser, get(config, "csv_missing_strings", nothing), String[]) + missing_strings = _t953 + _t954 = _extract_value_string(parser, get(config, "csv_decimal_separator", nothing), ".") + decimal_separator = _t954 + _t955 = _extract_value_string(parser, get(config, "csv_encoding", nothing), "utf-8") + encoding = _t955 + _t956 = _extract_value_string(parser, get(config, "csv_compression", nothing), "auto") + compression = _t956 + _t957 = Proto.CSVConfig(header_row=Int32(header_row), skip=skip, new_line=new_line, delimiter=delimiter, quotechar=quotechar, escapechar=escapechar, comment=comment, missing_strings=missing_strings, decimal_separator=decimal_separator, encoding=encoding, compression=compression) + return _t957 +end + +function construct_betree_info(parser::Parser, key_types::Vector{Proto.var"#Type"}, value_types::Vector{Proto.var"#Type"}, config_dict::Vector{Tuple{String, Proto.Value}})::Proto.BeTreeInfo + config = Dict(config_dict) + _t958 = _try_extract_value_float64(parser, get(config, "betree_config_epsilon", nothing)) + epsilon = _t958 + _t959 = _try_extract_value_int64(parser, get(config, "betree_config_max_pivots", nothing)) + max_pivots = _t959 + _t960 = _try_extract_value_int64(parser, get(config, "betree_config_max_deltas", nothing)) + max_deltas = _t960 + _t961 = _try_extract_value_int64(parser, get(config, "betree_config_max_leaf", nothing)) + max_leaf = _t961 + _t962 = Proto.BeTreeConfig(epsilon=epsilon, max_pivots=max_pivots, max_deltas=max_deltas, max_leaf=max_leaf) + storage_config = _t962 + _t963 = _try_extract_value_uint128(parser, get(config, "betree_locator_root_pageid", nothing)) + root_pageid = _t963 + _t964 = _try_extract_value_bytes(parser, get(config, "betree_locator_inline_data", nothing)) + inline_data = _t964 + _t965 = _try_extract_value_int64(parser, get(config, "betree_locator_element_count", nothing)) + element_count = _t965 + _t966 = _try_extract_value_int64(parser, get(config, "betree_locator_tree_height", nothing)) + tree_height = _t966 + _t967 = Proto.BeTreeLocator(location=(!isnothing(root_pageid) ? OneOf(:root_pageid, root_pageid) : (!isnothing(inline_data) ? OneOf(:inline_data, inline_data) : nothing)), element_count=element_count, tree_height=tree_height) + relation_locator = _t967 + _t968 = Proto.BeTreeInfo(key_types=key_types, value_types=value_types, storage_config=storage_config, relation_locator=relation_locator) + return _t968 +end + +function default_configure(parser::Parser)::Proto.Configure + _t969 = Proto.IVMConfig(level=Proto.MaintenanceLevel.MAINTENANCE_LEVEL_OFF) + ivm_config = _t969 + _t970 = Proto.Configure(0, ivm_config, Proto.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT) + return _t970 +end + +function construct_configure(parser::Parser, config_dict::Vector{Tuple{String, Proto.Value}})::Proto.Configure + config = Dict(config_dict) + maintenance_level_val = get(config, "ivm.maintenance_level", nothing) + maintenance_level = Proto.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + if (!isnothing(maintenance_level_val) && _has_proto_field(maintenance_level_val, Symbol("string_value"))) + if _get_oneof_field(maintenance_level_val, :string_value) == "off" + maintenance_level = Proto.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + else + if _get_oneof_field(maintenance_level_val, :string_value) == "auto" + maintenance_level = Proto.MaintenanceLevel.MAINTENANCE_LEVEL_AUTO + else + if _get_oneof_field(maintenance_level_val, :string_value) == "all" + maintenance_level = Proto.MaintenanceLevel.MAINTENANCE_LEVEL_ALL + else + maintenance_level = Proto.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + end + end + end + end + _t971 = Proto.IVMConfig(level=maintenance_level) + ivm_config = _t971 + _t972 = _extract_value_int64(parser, get(config, "semantics_version", nothing), 0) + semantics_version = _t972 + optimization_level_val = get(config, "optimization_level", nothing) + optimization_level = Proto.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + if (!isnothing(optimization_level_val) && _has_proto_field(optimization_level_val, Symbol("string_value"))) + if _get_oneof_field(optimization_level_val, :string_value) == "default" + optimization_level = Proto.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + else + if _get_oneof_field(optimization_level_val, :string_value) == "conservative" + optimization_level = Proto.OptimizationLevel.OPTIMIZATION_LEVEL_CONSERVATIVE + else + if _get_oneof_field(optimization_level_val, :string_value) == "aggressive" + optimization_level = Proto.OptimizationLevel.OPTIMIZATION_LEVEL_AGGRESSIVE + else + optimization_level = Proto.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + end + end + end + end + _t973 = Proto.Configure(semantics_version, ivm_config, optimization_level) + return _t973 +end + +function export_csv_config(parser::Parser, path::String, columns::Vector{Proto.ExportCSVColumn}, config_dict::Vector{Tuple{String, Proto.Value}})::Proto.ExportCSVConfig + config = Dict(config_dict) + _t974 = _extract_value_int64(parser, get(config, "partition_size", nothing), 0) + partition_size = _t974 + _t975 = _extract_value_string(parser, get(config, "compression", nothing), "") + compression = _t975 + _t976 = _extract_value_boolean(parser, get(config, "syntax_header_row", nothing), true) + syntax_header_row = _t976 + _t977 = _extract_value_string(parser, get(config, "syntax_missing_string", nothing), "") + syntax_missing_string = _t977 + _t978 = _extract_value_string(parser, get(config, "syntax_delim", nothing), ",") + syntax_delim = _t978 + _t979 = _extract_value_string(parser, get(config, "syntax_quotechar", nothing), "\"") + syntax_quotechar = _t979 + _t980 = _extract_value_string(parser, get(config, "syntax_escapechar", nothing), "\\") + syntax_escapechar = _t980 + _t981 = Proto.ExportCSVConfig(path=path, data_columns=columns, partition_size=partition_size, compression=compression, syntax_header_row=syntax_header_row, syntax_missing_string=syntax_missing_string, syntax_delim=syntax_delim, syntax_quotechar=syntax_quotechar, syntax_escapechar=syntax_escapechar) + return _t981 +end + +# --- Parse functions --- + +function parse_transaction(parser::Parser)::Proto.Transaction + consume_literal!(parser, "(") + consume_literal!(parser, "transaction") + + if (match_lookahead_literal(parser, "(", 0) && match_lookahead_literal(parser, "configure", 1)) + _t354 = parse_configure(parser) + _t353 = _t354 + else + _t353 = nothing + end + configure0 = _t353 + + if (match_lookahead_literal(parser, "(", 0) && match_lookahead_literal(parser, "sync", 1)) + _t356 = parse_sync(parser) + _t355 = _t356 + else + _t355 = nothing + end + sync1 = _t355 + xs2 = Proto.Epoch[] + cond3 = match_lookahead_literal(parser, "(", 0) + while cond3 + _t357 = parse_epoch(parser) + item4 = _t357 + push!(xs2, item4) + cond3 = match_lookahead_literal(parser, "(", 0) + end + epochs5 = xs2 + consume_literal!(parser, ")") + _t358 = default_configure(parser) + _t359 = Proto.Transaction(epochs=epochs5, configure=(!isnothing(configure0) ? configure0 : _t358), sync=sync1) + return _t359 +end + +function parse_configure(parser::Parser)::Proto.Configure + consume_literal!(parser, "(") + consume_literal!(parser, "configure") + _t360 = parse_config_dict(parser) + config_dict6 = _t360 + consume_literal!(parser, ")") + _t361 = construct_configure(parser, config_dict6) + return _t361 +end + +function parse_config_dict(parser::Parser)::Vector{Tuple{String, Proto.Value}} + consume_literal!(parser, "{") + xs7 = Tuple{String, Proto.Value}[] + cond8 = match_lookahead_literal(parser, ":", 0) + while cond8 + _t362 = parse_config_key_value(parser) + item9 = _t362 + push!(xs7, item9) + cond8 = match_lookahead_literal(parser, ":", 0) + end + config_key_values10 = xs7 + consume_literal!(parser, "}") + return config_key_values10 +end + +function parse_config_key_value(parser::Parser)::Tuple{String, Proto.Value} + consume_literal!(parser, ":") + symbol11 = consume_terminal!(parser, "SYMBOL") + _t363 = parse_value(parser) + value12 = _t363 + return (symbol11, value12,) +end + +function parse_value(parser::Parser)::Proto.Value + + if match_lookahead_literal(parser, "true", 0) + _t364 = 9 + else + + if match_lookahead_literal(parser, "missing", 0) + _t365 = 8 + else + + if match_lookahead_literal(parser, "false", 0) + _t366 = 9 + else + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "datetime", 1) + _t368 = 1 + else + + if match_lookahead_literal(parser, "date", 1) + _t369 = 0 + else + _t369 = -1 + end + _t368 = _t369 + end + _t367 = _t368 + else + + if match_lookahead_terminal(parser, "UINT128", 0) + _t370 = 5 + else + + if match_lookahead_terminal(parser, "STRING", 0) + _t371 = 2 + else + + if match_lookahead_terminal(parser, "INT128", 0) + _t372 = 6 + else + + if match_lookahead_terminal(parser, "INT", 0) + _t373 = 3 + else + + if match_lookahead_terminal(parser, "FLOAT", 0) + _t374 = 4 + else + + if match_lookahead_terminal(parser, "DECIMAL", 0) + _t375 = 7 + else + _t375 = -1 + end + _t374 = _t375 + end + _t373 = _t374 + end + _t372 = _t373 + end + _t371 = _t372 + end + _t370 = _t371 + end + _t367 = _t370 + end + _t366 = _t367 + end + _t365 = _t366 + end + _t364 = _t365 + end + prediction13 = _t364 + + if prediction13 == 9 + _t377 = parse_boolean_value(parser) + boolean_value22 = _t377 + _t378 = Proto.Value(value=OneOf(:boolean_value, boolean_value22)) + _t376 = _t378 + else + + if prediction13 == 8 + consume_literal!(parser, "missing") + _t380 = Proto.MissingValue() + _t381 = Proto.Value(value=OneOf(:missing_value, _t380)) + _t379 = _t381 + else + + if prediction13 == 7 + decimal21 = consume_terminal!(parser, "DECIMAL") + _t383 = Proto.Value(value=OneOf(:decimal_value, decimal21)) + _t382 = _t383 + else + + if prediction13 == 6 + int12820 = consume_terminal!(parser, "INT128") + _t385 = Proto.Value(value=OneOf(:int128_value, int12820)) + _t384 = _t385 + else + + if prediction13 == 5 + uint12819 = consume_terminal!(parser, "UINT128") + _t387 = Proto.Value(value=OneOf(:uint128_value, uint12819)) + _t386 = _t387 + else + + if prediction13 == 4 + float18 = consume_terminal!(parser, "FLOAT") + _t389 = Proto.Value(value=OneOf(:float_value, float18)) + _t388 = _t389 + else + + if prediction13 == 3 + int17 = consume_terminal!(parser, "INT") + _t391 = Proto.Value(value=OneOf(:int_value, int17)) + _t390 = _t391 + else + + if prediction13 == 2 + string16 = consume_terminal!(parser, "STRING") + _t393 = Proto.Value(value=OneOf(:string_value, string16)) + _t392 = _t393 + else + + if prediction13 == 1 + _t395 = parse_datetime(parser) + datetime15 = _t395 + _t396 = Proto.Value(value=OneOf(:datetime_value, datetime15)) + _t394 = _t396 + else + + if prediction13 == 0 + _t398 = parse_date(parser) + date14 = _t398 + _t399 = Proto.Value(value=OneOf(:date_value, date14)) + _t397 = _t399 + else + throw(ParseError("Unexpected token in value" * ": " * string(lookahead(parser, 0)))) + end + _t394 = _t397 + end + _t392 = _t394 + end + _t390 = _t392 + end + _t388 = _t390 + end + _t386 = _t388 + end + _t384 = _t386 + end + _t382 = _t384 + end + _t379 = _t382 + end + _t376 = _t379 + end + return _t376 +end + +function parse_date(parser::Parser)::Proto.DateValue + consume_literal!(parser, "(") + consume_literal!(parser, "date") + int23 = consume_terminal!(parser, "INT") + int_324 = consume_terminal!(parser, "INT") + int_425 = consume_terminal!(parser, "INT") + consume_literal!(parser, ")") + _t400 = Proto.DateValue(year=Int32(int23), month=Int32(int_324), day=Int32(int_425)) + return _t400 +end + +function parse_datetime(parser::Parser)::Proto.DateTimeValue + consume_literal!(parser, "(") + consume_literal!(parser, "datetime") + int26 = consume_terminal!(parser, "INT") + int_327 = consume_terminal!(parser, "INT") + int_428 = consume_terminal!(parser, "INT") + int_529 = consume_terminal!(parser, "INT") + int_630 = consume_terminal!(parser, "INT") + int_731 = consume_terminal!(parser, "INT") + + if match_lookahead_terminal(parser, "INT", 0) + _t401 = consume_terminal!(parser, "INT") + else + _t401 = nothing + end + int_832 = _t401 + consume_literal!(parser, ")") + _t402 = Proto.DateTimeValue(year=Int32(int26), month=Int32(int_327), day=Int32(int_428), hour=Int32(int_529), minute=Int32(int_630), second=Int32(int_731), microsecond=Int32((!isnothing(int_832) ? int_832 : 0))) + return _t402 +end + +function parse_boolean_value(parser::Parser)::Bool + + if match_lookahead_literal(parser, "true", 0) + _t403 = 0 + else + + if match_lookahead_literal(parser, "false", 0) + _t404 = 1 + else + _t404 = -1 + end + _t403 = _t404 + end + prediction33 = _t403 + + if prediction33 == 1 + consume_literal!(parser, "false") + _t405 = false + else + + if prediction33 == 0 + consume_literal!(parser, "true") + _t406 = true + else + throw(ParseError("Unexpected token in boolean_value" * ": " * string(lookahead(parser, 0)))) + end + _t405 = _t406 + end + return _t405 +end + +function parse_sync(parser::Parser)::Proto.Sync + consume_literal!(parser, "(") + consume_literal!(parser, "sync") + xs34 = Proto.FragmentId[] + cond35 = match_lookahead_literal(parser, ":", 0) + while cond35 + _t407 = parse_fragment_id(parser) + item36 = _t407 + push!(xs34, item36) + cond35 = match_lookahead_literal(parser, ":", 0) + end + fragment_ids37 = xs34 + consume_literal!(parser, ")") + _t408 = Proto.Sync(fragments=fragment_ids37) + return _t408 +end + +function parse_fragment_id(parser::Parser)::Proto.FragmentId + consume_literal!(parser, ":") + symbol38 = consume_terminal!(parser, "SYMBOL") + return Proto.FragmentId(Vector{UInt8}(symbol38)) +end + +function parse_epoch(parser::Parser)::Proto.Epoch + consume_literal!(parser, "(") + consume_literal!(parser, "epoch") + + if (match_lookahead_literal(parser, "(", 0) && match_lookahead_literal(parser, "writes", 1)) + _t410 = parse_epoch_writes(parser) + _t409 = _t410 + else + _t409 = nothing + end + epoch_writes39 = _t409 + + if match_lookahead_literal(parser, "(", 0) + _t412 = parse_epoch_reads(parser) + _t411 = _t412 + else + _t411 = nothing + end + epoch_reads40 = _t411 + consume_literal!(parser, ")") + _t413 = Proto.Epoch(writes=(!isnothing(epoch_writes39) ? epoch_writes39 : Proto.Write[]), reads=(!isnothing(epoch_reads40) ? epoch_reads40 : Proto.Read[])) + return _t413 +end + +function parse_epoch_writes(parser::Parser)::Vector{Proto.Write} + consume_literal!(parser, "(") + consume_literal!(parser, "writes") + xs41 = Proto.Write[] + cond42 = match_lookahead_literal(parser, "(", 0) + while cond42 + _t414 = parse_write(parser) + item43 = _t414 + push!(xs41, item43) + cond42 = match_lookahead_literal(parser, "(", 0) + end + writes44 = xs41 + consume_literal!(parser, ")") + return writes44 +end + +function parse_write(parser::Parser)::Proto.Write + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "undefine", 1) + _t416 = 1 + else + + if match_lookahead_literal(parser, "define", 1) + _t417 = 0 + else + + if match_lookahead_literal(parser, "context", 1) + _t418 = 2 + else + _t418 = -1 + end + _t417 = _t418 + end + _t416 = _t417 + end + _t415 = _t416 + else + _t415 = -1 + end + prediction45 = _t415 + + if prediction45 == 2 + _t420 = parse_context(parser) + context48 = _t420 + _t421 = Proto.Write(write_type=OneOf(:context, context48)) + _t419 = _t421 + else + + if prediction45 == 1 + _t423 = parse_undefine(parser) + undefine47 = _t423 + _t424 = Proto.Write(write_type=OneOf(:undefine, undefine47)) + _t422 = _t424 + else + + if prediction45 == 0 + _t426 = parse_define(parser) + define46 = _t426 + _t427 = Proto.Write(write_type=OneOf(:define, define46)) + _t425 = _t427 + else + throw(ParseError("Unexpected token in write" * ": " * string(lookahead(parser, 0)))) + end + _t422 = _t425 + end + _t419 = _t422 + end + return _t419 +end + +function parse_define(parser::Parser)::Proto.Define + consume_literal!(parser, "(") + consume_literal!(parser, "define") + _t428 = parse_fragment(parser) + fragment49 = _t428 + consume_literal!(parser, ")") + _t429 = Proto.Define(fragment=fragment49) + return _t429 +end + +function parse_fragment(parser::Parser)::Proto.Fragment + consume_literal!(parser, "(") + consume_literal!(parser, "fragment") + _t430 = parse_new_fragment_id(parser) + new_fragment_id50 = _t430 + xs51 = Proto.Declaration[] + cond52 = match_lookahead_literal(parser, "(", 0) + while cond52 + _t431 = parse_declaration(parser) + item53 = _t431 + push!(xs51, item53) + cond52 = match_lookahead_literal(parser, "(", 0) + end + declarations54 = xs51 + consume_literal!(parser, ")") + return construct_fragment(parser, new_fragment_id50, declarations54) +end + +function parse_new_fragment_id(parser::Parser)::Proto.FragmentId + _t432 = parse_fragment_id(parser) + fragment_id55 = _t432 + start_fragment!(parser, fragment_id55) + return fragment_id55 +end + +function parse_declaration(parser::Parser)::Proto.Declaration + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "rel_edb", 1) + _t434 = 3 + else + + if match_lookahead_literal(parser, "functional_dependency", 1) + _t435 = 2 + else + + if match_lookahead_literal(parser, "def", 1) + _t436 = 0 + else + + if match_lookahead_literal(parser, "csv_data", 1) + _t437 = 3 + else + + if match_lookahead_literal(parser, "betree_relation", 1) + _t438 = 3 + else + + if match_lookahead_literal(parser, "algorithm", 1) + _t439 = 1 + else + _t439 = -1 + end + _t438 = _t439 + end + _t437 = _t438 + end + _t436 = _t437 + end + _t435 = _t436 + end + _t434 = _t435 + end + _t433 = _t434 + else + _t433 = -1 + end + prediction56 = _t433 + + if prediction56 == 3 + _t441 = parse_data(parser) + data60 = _t441 + _t442 = Proto.Declaration(declaration_type=OneOf(:data, data60)) + _t440 = _t442 + else + + if prediction56 == 2 + _t444 = parse_constraint(parser) + constraint59 = _t444 + _t445 = Proto.Declaration(declaration_type=OneOf(:constraint, constraint59)) + _t443 = _t445 + else + + if prediction56 == 1 + _t447 = parse_algorithm(parser) + algorithm58 = _t447 + _t448 = Proto.Declaration(declaration_type=OneOf(:algorithm, algorithm58)) + _t446 = _t448 + else + + if prediction56 == 0 + _t450 = parse_def(parser) + def57 = _t450 + _t451 = Proto.Declaration(declaration_type=OneOf(:def, def57)) + _t449 = _t451 + else + throw(ParseError("Unexpected token in declaration" * ": " * string(lookahead(parser, 0)))) + end + _t446 = _t449 + end + _t443 = _t446 + end + _t440 = _t443 + end + return _t440 +end + +function parse_def(parser::Parser)::Proto.Def + consume_literal!(parser, "(") + consume_literal!(parser, "def") + _t452 = parse_relation_id(parser) + relation_id61 = _t452 + _t453 = parse_abstraction(parser) + abstraction62 = _t453 + + if match_lookahead_literal(parser, "(", 0) + _t455 = parse_attrs(parser) + _t454 = _t455 + else + _t454 = nothing + end + attrs63 = _t454 + consume_literal!(parser, ")") + _t456 = Proto.Def(name=relation_id61, body=abstraction62, attrs=(!isnothing(attrs63) ? attrs63 : Proto.Attribute[])) + return _t456 +end + +function parse_relation_id(parser::Parser)::Proto.RelationId + + if match_lookahead_literal(parser, ":", 0) + _t457 = 0 + else + + if match_lookahead_terminal(parser, "UINT128", 0) + _t458 = 1 + else + _t458 = -1 + end + _t457 = _t458 + end + prediction64 = _t457 + + if prediction64 == 1 + uint12866 = consume_terminal!(parser, "UINT128") + _t459 = Proto.RelationId(uint12866.low, uint12866.high) + else + + if prediction64 == 0 + consume_literal!(parser, ":") + symbol65 = consume_terminal!(parser, "SYMBOL") + _t460 = relation_id_from_string(parser, symbol65) + else + throw(ParseError("Unexpected token in relation_id" * ": " * string(lookahead(parser, 0)))) + end + _t459 = _t460 + end + return _t459 +end + +function parse_abstraction(parser::Parser)::Proto.Abstraction + consume_literal!(parser, "(") + _t461 = parse_bindings(parser) + bindings67 = _t461 + _t462 = parse_formula(parser) + formula68 = _t462 + consume_literal!(parser, ")") + _t463 = Proto.Abstraction(vars=vcat(bindings67[1], !isnothing(bindings67[2]) ? bindings67[2] : []), value=formula68) + return _t463 +end + +function parse_bindings(parser::Parser)::Tuple{Vector{Proto.Binding}, Vector{Proto.Binding}} + consume_literal!(parser, "[") + xs69 = Proto.Binding[] + cond70 = match_lookahead_terminal(parser, "SYMBOL", 0) + while cond70 + _t464 = parse_binding(parser) + item71 = _t464 + push!(xs69, item71) + cond70 = match_lookahead_terminal(parser, "SYMBOL", 0) + end + bindings72 = xs69 + + if match_lookahead_literal(parser, "|", 0) + _t466 = parse_value_bindings(parser) + _t465 = _t466 + else + _t465 = nothing + end + value_bindings73 = _t465 + consume_literal!(parser, "]") + return (bindings72, (!isnothing(value_bindings73) ? value_bindings73 : Proto.Binding[]),) +end + +function parse_binding(parser::Parser)::Proto.Binding + symbol74 = consume_terminal!(parser, "SYMBOL") + consume_literal!(parser, "::") + _t467 = parse_type(parser) + type75 = _t467 + _t468 = Proto.Var(name=symbol74) + _t469 = Proto.Binding(var=_t468, var"#type"=type75) + return _t469 +end + +function parse_type(parser::Parser)::Proto.var"#Type" + + if match_lookahead_literal(parser, "UNKNOWN", 0) + _t470 = 0 + else + + if match_lookahead_literal(parser, "UINT128", 0) + _t471 = 4 + else + + if match_lookahead_literal(parser, "STRING", 0) + _t472 = 1 + else + + if match_lookahead_literal(parser, "MISSING", 0) + _t473 = 8 + else + + if match_lookahead_literal(parser, "INT128", 0) + _t474 = 5 + else + + if match_lookahead_literal(parser, "INT", 0) + _t475 = 2 + else + + if match_lookahead_literal(parser, "FLOAT", 0) + _t476 = 3 + else + + if match_lookahead_literal(parser, "DATETIME", 0) + _t477 = 7 + else + + if match_lookahead_literal(parser, "DATE", 0) + _t478 = 6 + else + + if match_lookahead_literal(parser, "BOOLEAN", 0) + _t479 = 10 + else + + if match_lookahead_literal(parser, "(", 0) + _t480 = 9 + else + _t480 = -1 + end + _t479 = _t480 + end + _t478 = _t479 + end + _t477 = _t478 + end + _t476 = _t477 + end + _t475 = _t476 + end + _t474 = _t475 + end + _t473 = _t474 + end + _t472 = _t473 + end + _t471 = _t472 + end + _t470 = _t471 + end + prediction76 = _t470 + + if prediction76 == 10 + _t482 = parse_boolean_type(parser) + boolean_type87 = _t482 + _t483 = Proto.var"#Type"(var"#type"=OneOf(:boolean_type, boolean_type87)) + _t481 = _t483 + else + + if prediction76 == 9 + _t485 = parse_decimal_type(parser) + decimal_type86 = _t485 + _t486 = Proto.var"#Type"(var"#type"=OneOf(:decimal_type, decimal_type86)) + _t484 = _t486 + else + + if prediction76 == 8 + _t488 = parse_missing_type(parser) + missing_type85 = _t488 + _t489 = Proto.var"#Type"(var"#type"=OneOf(:missing_type, missing_type85)) + _t487 = _t489 + else + + if prediction76 == 7 + _t491 = parse_datetime_type(parser) + datetime_type84 = _t491 + _t492 = Proto.var"#Type"(var"#type"=OneOf(:datetime_type, datetime_type84)) + _t490 = _t492 + else + + if prediction76 == 6 + _t494 = parse_date_type(parser) + date_type83 = _t494 + _t495 = Proto.var"#Type"(var"#type"=OneOf(:date_type, date_type83)) + _t493 = _t495 + else + + if prediction76 == 5 + _t497 = parse_int128_type(parser) + int128_type82 = _t497 + _t498 = Proto.var"#Type"(var"#type"=OneOf(:int128_type, int128_type82)) + _t496 = _t498 + else + + if prediction76 == 4 + _t500 = parse_uint128_type(parser) + uint128_type81 = _t500 + _t501 = Proto.var"#Type"(var"#type"=OneOf(:uint128_type, uint128_type81)) + _t499 = _t501 + else + + if prediction76 == 3 + _t503 = parse_float_type(parser) + float_type80 = _t503 + _t504 = Proto.var"#Type"(var"#type"=OneOf(:float_type, float_type80)) + _t502 = _t504 + else + + if prediction76 == 2 + _t506 = parse_int_type(parser) + int_type79 = _t506 + _t507 = Proto.var"#Type"(var"#type"=OneOf(:int_type, int_type79)) + _t505 = _t507 + else + + if prediction76 == 1 + _t509 = parse_string_type(parser) + string_type78 = _t509 + _t510 = Proto.var"#Type"(var"#type"=OneOf(:string_type, string_type78)) + _t508 = _t510 + else + + if prediction76 == 0 + _t512 = parse_unspecified_type(parser) + unspecified_type77 = _t512 + _t513 = Proto.var"#Type"(var"#type"=OneOf(:unspecified_type, unspecified_type77)) + _t511 = _t513 + else + throw(ParseError("Unexpected token in type" * ": " * string(lookahead(parser, 0)))) + end + _t508 = _t511 + end + _t505 = _t508 + end + _t502 = _t505 + end + _t499 = _t502 + end + _t496 = _t499 + end + _t493 = _t496 + end + _t490 = _t493 + end + _t487 = _t490 + end + _t484 = _t487 + end + _t481 = _t484 + end + return _t481 +end + +function parse_unspecified_type(parser::Parser)::Proto.UnspecifiedType + consume_literal!(parser, "UNKNOWN") + _t514 = Proto.UnspecifiedType() + return _t514 +end + +function parse_string_type(parser::Parser)::Proto.StringType + consume_literal!(parser, "STRING") + _t515 = Proto.StringType() + return _t515 +end + +function parse_int_type(parser::Parser)::Proto.IntType + consume_literal!(parser, "INT") + _t516 = Proto.IntType() + return _t516 +end + +function parse_float_type(parser::Parser)::Proto.FloatType + consume_literal!(parser, "FLOAT") + _t517 = Proto.FloatType() + return _t517 +end + +function parse_uint128_type(parser::Parser)::Proto.UInt128Type + consume_literal!(parser, "UINT128") + _t518 = Proto.UInt128Type() + return _t518 +end + +function parse_int128_type(parser::Parser)::Proto.Int128Type + consume_literal!(parser, "INT128") + _t519 = Proto.Int128Type() + return _t519 +end + +function parse_date_type(parser::Parser)::Proto.DateType + consume_literal!(parser, "DATE") + _t520 = Proto.DateType() + return _t520 +end + +function parse_datetime_type(parser::Parser)::Proto.DateTimeType + consume_literal!(parser, "DATETIME") + _t521 = Proto.DateTimeType() + return _t521 +end + +function parse_missing_type(parser::Parser)::Proto.MissingType + consume_literal!(parser, "MISSING") + _t522 = Proto.MissingType() + return _t522 +end + +function parse_decimal_type(parser::Parser)::Proto.DecimalType + consume_literal!(parser, "(") + consume_literal!(parser, "DECIMAL") + int88 = consume_terminal!(parser, "INT") + int_389 = consume_terminal!(parser, "INT") + consume_literal!(parser, ")") + _t523 = Proto.DecimalType(precision=Int32(int88), scale=Int32(int_389)) + return _t523 +end + +function parse_boolean_type(parser::Parser)::Proto.BooleanType + consume_literal!(parser, "BOOLEAN") + _t524 = Proto.BooleanType() + return _t524 +end + +function parse_value_bindings(parser::Parser)::Vector{Proto.Binding} + consume_literal!(parser, "|") + xs90 = Proto.Binding[] + cond91 = match_lookahead_terminal(parser, "SYMBOL", 0) + while cond91 + _t525 = parse_binding(parser) + item92 = _t525 + push!(xs90, item92) + cond91 = match_lookahead_terminal(parser, "SYMBOL", 0) + end + bindings93 = xs90 + return bindings93 +end + +function parse_formula(parser::Parser)::Proto.Formula + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "true", 1) + _t527 = 0 + else + + if match_lookahead_literal(parser, "relatom", 1) + _t528 = 11 + else + + if match_lookahead_literal(parser, "reduce", 1) + _t529 = 3 + else + + if match_lookahead_literal(parser, "primitive", 1) + _t530 = 10 + else + + if match_lookahead_literal(parser, "pragma", 1) + _t531 = 9 + else + + if match_lookahead_literal(parser, "or", 1) + _t532 = 5 + else + + if match_lookahead_literal(parser, "not", 1) + _t533 = 6 + else + + if match_lookahead_literal(parser, "ffi", 1) + _t534 = 7 + else + + if match_lookahead_literal(parser, "false", 1) + _t535 = 1 + else + + if match_lookahead_literal(parser, "exists", 1) + _t536 = 2 + else + + if match_lookahead_literal(parser, "cast", 1) + _t537 = 12 + else + + if match_lookahead_literal(parser, "atom", 1) + _t538 = 8 + else + + if match_lookahead_literal(parser, "and", 1) + _t539 = 4 + else + + if match_lookahead_literal(parser, ">=", 1) + _t540 = 10 + else + + if match_lookahead_literal(parser, ">", 1) + _t541 = 10 + else + + if match_lookahead_literal(parser, "=", 1) + _t542 = 10 + else + + if match_lookahead_literal(parser, "<=", 1) + _t543 = 10 + else + + if match_lookahead_literal(parser, "<", 1) + _t544 = 10 + else + + if match_lookahead_literal(parser, "/", 1) + _t545 = 10 + else + + if match_lookahead_literal(parser, "-", 1) + _t546 = 10 + else + + if match_lookahead_literal(parser, "+", 1) + _t547 = 10 + else + + if match_lookahead_literal(parser, "*", 1) + _t548 = 10 + else + _t548 = -1 + end + _t547 = _t548 + end + _t546 = _t547 + end + _t545 = _t546 + end + _t544 = _t545 + end + _t543 = _t544 + end + _t542 = _t543 + end + _t541 = _t542 + end + _t540 = _t541 + end + _t539 = _t540 + end + _t538 = _t539 + end + _t537 = _t538 + end + _t536 = _t537 + end + _t535 = _t536 + end + _t534 = _t535 + end + _t533 = _t534 + end + _t532 = _t533 + end + _t531 = _t532 + end + _t530 = _t531 + end + _t529 = _t530 + end + _t528 = _t529 + end + _t527 = _t528 + end + _t526 = _t527 + else + _t526 = -1 + end + prediction94 = _t526 + + if prediction94 == 12 + _t550 = parse_cast(parser) + cast107 = _t550 + _t551 = Proto.Formula(formula_type=OneOf(:cast, cast107)) + _t549 = _t551 + else + + if prediction94 == 11 + _t553 = parse_rel_atom(parser) + rel_atom106 = _t553 + _t554 = Proto.Formula(formula_type=OneOf(:rel_atom, rel_atom106)) + _t552 = _t554 + else + + if prediction94 == 10 + _t556 = parse_primitive(parser) + primitive105 = _t556 + _t557 = Proto.Formula(formula_type=OneOf(:primitive, primitive105)) + _t555 = _t557 + else + + if prediction94 == 9 + _t559 = parse_pragma(parser) + pragma104 = _t559 + _t560 = Proto.Formula(formula_type=OneOf(:pragma, pragma104)) + _t558 = _t560 + else + + if prediction94 == 8 + _t562 = parse_atom(parser) + atom103 = _t562 + _t563 = Proto.Formula(formula_type=OneOf(:atom, atom103)) + _t561 = _t563 + else + + if prediction94 == 7 + _t565 = parse_ffi(parser) + ffi102 = _t565 + _t566 = Proto.Formula(formula_type=OneOf(:ffi, ffi102)) + _t564 = _t566 + else + + if prediction94 == 6 + _t568 = parse_not(parser) + not101 = _t568 + _t569 = Proto.Formula(formula_type=OneOf(:not, not101)) + _t567 = _t569 + else + + if prediction94 == 5 + _t571 = parse_disjunction(parser) + disjunction100 = _t571 + _t572 = Proto.Formula(formula_type=OneOf(:disjunction, disjunction100)) + _t570 = _t572 + else + + if prediction94 == 4 + _t574 = parse_conjunction(parser) + conjunction99 = _t574 + _t575 = Proto.Formula(formula_type=OneOf(:conjunction, conjunction99)) + _t573 = _t575 + else + + if prediction94 == 3 + _t577 = parse_reduce(parser) + reduce98 = _t577 + _t578 = Proto.Formula(formula_type=OneOf(:reduce, reduce98)) + _t576 = _t578 + else + + if prediction94 == 2 + _t580 = parse_exists(parser) + exists97 = _t580 + _t581 = Proto.Formula(formula_type=OneOf(:exists, exists97)) + _t579 = _t581 + else + + if prediction94 == 1 + _t583 = parse_false(parser) + false96 = _t583 + _t584 = Proto.Formula(formula_type=OneOf(:disjunction, false96)) + _t582 = _t584 + else + + if prediction94 == 0 + _t586 = parse_true(parser) + true95 = _t586 + _t587 = Proto.Formula(formula_type=OneOf(:conjunction, true95)) + _t585 = _t587 + else + throw(ParseError("Unexpected token in formula" * ": " * string(lookahead(parser, 0)))) + end + _t582 = _t585 + end + _t579 = _t582 + end + _t576 = _t579 + end + _t573 = _t576 + end + _t570 = _t573 + end + _t567 = _t570 + end + _t564 = _t567 + end + _t561 = _t564 + end + _t558 = _t561 + end + _t555 = _t558 + end + _t552 = _t555 + end + _t549 = _t552 + end + return _t549 +end + +function parse_true(parser::Parser)::Proto.Conjunction + consume_literal!(parser, "(") + consume_literal!(parser, "true") + consume_literal!(parser, ")") + _t588 = Proto.Conjunction(args=Proto.Formula[]) + return _t588 +end + +function parse_false(parser::Parser)::Proto.Disjunction + consume_literal!(parser, "(") + consume_literal!(parser, "false") + consume_literal!(parser, ")") + _t589 = Proto.Disjunction(args=Proto.Formula[]) + return _t589 +end + +function parse_exists(parser::Parser)::Proto.Exists + consume_literal!(parser, "(") + consume_literal!(parser, "exists") + _t590 = parse_bindings(parser) + bindings108 = _t590 + _t591 = parse_formula(parser) + formula109 = _t591 + consume_literal!(parser, ")") + _t592 = Proto.Abstraction(vars=vcat(bindings108[1], !isnothing(bindings108[2]) ? bindings108[2] : []), value=formula109) + _t593 = Proto.Exists(body=_t592) + return _t593 +end + +function parse_reduce(parser::Parser)::Proto.Reduce + consume_literal!(parser, "(") + consume_literal!(parser, "reduce") + _t594 = parse_abstraction(parser) + abstraction110 = _t594 + _t595 = parse_abstraction(parser) + abstraction_3111 = _t595 + _t596 = parse_terms(parser) + terms112 = _t596 + consume_literal!(parser, ")") + _t597 = Proto.Reduce(op=abstraction110, body=abstraction_3111, terms=terms112) + return _t597 +end + +function parse_terms(parser::Parser)::Vector{Proto.Term} + consume_literal!(parser, "(") + consume_literal!(parser, "terms") + xs113 = Proto.Term[] + cond114 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond114 + _t598 = parse_term(parser) + item115 = _t598 + push!(xs113, item115) + cond114 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + terms116 = xs113 + consume_literal!(parser, ")") + return terms116 +end + +function parse_term(parser::Parser)::Proto.Term + + if match_lookahead_literal(parser, "true", 0) + _t599 = 1 + else + + if match_lookahead_literal(parser, "missing", 0) + _t600 = 1 + else + + if match_lookahead_literal(parser, "false", 0) + _t601 = 1 + else + + if match_lookahead_literal(parser, "(", 0) + _t602 = 1 + else + + if match_lookahead_terminal(parser, "UINT128", 0) + _t603 = 1 + else + + if match_lookahead_terminal(parser, "SYMBOL", 0) + _t604 = 0 + else + + if match_lookahead_terminal(parser, "STRING", 0) + _t605 = 1 + else + + if match_lookahead_terminal(parser, "INT128", 0) + _t606 = 1 + else + + if match_lookahead_terminal(parser, "INT", 0) + _t607 = 1 + else + + if match_lookahead_terminal(parser, "FLOAT", 0) + _t608 = 1 + else + + if match_lookahead_terminal(parser, "DECIMAL", 0) + _t609 = 1 + else + _t609 = -1 + end + _t608 = _t609 + end + _t607 = _t608 + end + _t606 = _t607 + end + _t605 = _t606 + end + _t604 = _t605 + end + _t603 = _t604 + end + _t602 = _t603 + end + _t601 = _t602 + end + _t600 = _t601 + end + _t599 = _t600 + end + prediction117 = _t599 + + if prediction117 == 1 + _t611 = parse_constant(parser) + constant119 = _t611 + _t612 = Proto.Term(term_type=OneOf(:constant, constant119)) + _t610 = _t612 + else + + if prediction117 == 0 + _t614 = parse_var(parser) + var118 = _t614 + _t615 = Proto.Term(term_type=OneOf(:var, var118)) + _t613 = _t615 + else + throw(ParseError("Unexpected token in term" * ": " * string(lookahead(parser, 0)))) + end + _t610 = _t613 + end + return _t610 +end + +function parse_var(parser::Parser)::Proto.Var + symbol120 = consume_terminal!(parser, "SYMBOL") + _t616 = Proto.Var(name=symbol120) + return _t616 +end + +function parse_constant(parser::Parser)::Proto.Value + _t617 = parse_value(parser) + value121 = _t617 + return value121 +end + +function parse_conjunction(parser::Parser)::Proto.Conjunction + consume_literal!(parser, "(") + consume_literal!(parser, "and") + xs122 = Proto.Formula[] + cond123 = match_lookahead_literal(parser, "(", 0) + while cond123 + _t618 = parse_formula(parser) + item124 = _t618 + push!(xs122, item124) + cond123 = match_lookahead_literal(parser, "(", 0) + end + formulas125 = xs122 + consume_literal!(parser, ")") + _t619 = Proto.Conjunction(args=formulas125) + return _t619 +end + +function parse_disjunction(parser::Parser)::Proto.Disjunction + consume_literal!(parser, "(") + consume_literal!(parser, "or") + xs126 = Proto.Formula[] + cond127 = match_lookahead_literal(parser, "(", 0) + while cond127 + _t620 = parse_formula(parser) + item128 = _t620 + push!(xs126, item128) + cond127 = match_lookahead_literal(parser, "(", 0) + end + formulas129 = xs126 + consume_literal!(parser, ")") + _t621 = Proto.Disjunction(args=formulas129) + return _t621 +end + +function parse_not(parser::Parser)::Proto.Not + consume_literal!(parser, "(") + consume_literal!(parser, "not") + _t622 = parse_formula(parser) + formula130 = _t622 + consume_literal!(parser, ")") + _t623 = Proto.Not(arg=formula130) + return _t623 +end + +function parse_ffi(parser::Parser)::Proto.FFI + consume_literal!(parser, "(") + consume_literal!(parser, "ffi") + _t624 = parse_name(parser) + name131 = _t624 + _t625 = parse_ffi_args(parser) + ffi_args132 = _t625 + _t626 = parse_terms(parser) + terms133 = _t626 + consume_literal!(parser, ")") + _t627 = Proto.FFI(name=name131, args=ffi_args132, terms=terms133) + return _t627 +end + +function parse_name(parser::Parser)::String + consume_literal!(parser, ":") + symbol134 = consume_terminal!(parser, "SYMBOL") + return symbol134 +end + +function parse_ffi_args(parser::Parser)::Vector{Proto.Abstraction} + consume_literal!(parser, "(") + consume_literal!(parser, "args") + xs135 = Proto.Abstraction[] + cond136 = match_lookahead_literal(parser, "(", 0) + while cond136 + _t628 = parse_abstraction(parser) + item137 = _t628 + push!(xs135, item137) + cond136 = match_lookahead_literal(parser, "(", 0) + end + abstractions138 = xs135 + consume_literal!(parser, ")") + return abstractions138 +end + +function parse_atom(parser::Parser)::Proto.Atom + consume_literal!(parser, "(") + consume_literal!(parser, "atom") + _t629 = parse_relation_id(parser) + relation_id139 = _t629 + xs140 = Proto.Term[] + cond141 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond141 + _t630 = parse_term(parser) + item142 = _t630 + push!(xs140, item142) + cond141 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + terms143 = xs140 + consume_literal!(parser, ")") + _t631 = Proto.Atom(name=relation_id139, terms=terms143) + return _t631 +end + +function parse_pragma(parser::Parser)::Proto.Pragma + consume_literal!(parser, "(") + consume_literal!(parser, "pragma") + _t632 = parse_name(parser) + name144 = _t632 + xs145 = Proto.Term[] + cond146 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond146 + _t633 = parse_term(parser) + item147 = _t633 + push!(xs145, item147) + cond146 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + terms148 = xs145 + consume_literal!(parser, ")") + _t634 = Proto.Pragma(name=name144, terms=terms148) + return _t634 +end + +function parse_primitive(parser::Parser)::Proto.Primitive + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "primitive", 1) + _t636 = 9 + else + + if match_lookahead_literal(parser, ">=", 1) + _t637 = 4 + else + + if match_lookahead_literal(parser, ">", 1) + _t638 = 3 + else + + if match_lookahead_literal(parser, "=", 1) + _t639 = 0 + else + + if match_lookahead_literal(parser, "<=", 1) + _t640 = 2 + else + + if match_lookahead_literal(parser, "<", 1) + _t641 = 1 + else + + if match_lookahead_literal(parser, "/", 1) + _t642 = 8 + else + + if match_lookahead_literal(parser, "-", 1) + _t643 = 6 + else + + if match_lookahead_literal(parser, "+", 1) + _t644 = 5 + else + + if match_lookahead_literal(parser, "*", 1) + _t645 = 7 + else + _t645 = -1 + end + _t644 = _t645 + end + _t643 = _t644 + end + _t642 = _t643 + end + _t641 = _t642 + end + _t640 = _t641 + end + _t639 = _t640 + end + _t638 = _t639 + end + _t637 = _t638 + end + _t636 = _t637 + end + _t635 = _t636 + else + _t635 = -1 + end + prediction149 = _t635 + + if prediction149 == 9 + consume_literal!(parser, "(") + consume_literal!(parser, "primitive") + _t647 = parse_name(parser) + name159 = _t647 + xs160 = Proto.RelTerm[] + cond161 = (((((((((((match_lookahead_literal(parser, "#", 0) || match_lookahead_literal(parser, "(", 0)) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond161 + _t648 = parse_rel_term(parser) + item162 = _t648 + push!(xs160, item162) + cond161 = (((((((((((match_lookahead_literal(parser, "#", 0) || match_lookahead_literal(parser, "(", 0)) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + rel_terms163 = xs160 + consume_literal!(parser, ")") + _t649 = Proto.Primitive(name=name159, terms=rel_terms163) + _t646 = _t649 + else + + if prediction149 == 8 + _t651 = parse_divide(parser) + divide158 = _t651 + _t650 = divide158 + else + + if prediction149 == 7 + _t653 = parse_multiply(parser) + multiply157 = _t653 + _t652 = multiply157 + else + + if prediction149 == 6 + _t655 = parse_minus(parser) + minus156 = _t655 + _t654 = minus156 + else + + if prediction149 == 5 + _t657 = parse_add(parser) + add155 = _t657 + _t656 = add155 + else + + if prediction149 == 4 + _t659 = parse_gt_eq(parser) + gt_eq154 = _t659 + _t658 = gt_eq154 + else + + if prediction149 == 3 + _t661 = parse_gt(parser) + gt153 = _t661 + _t660 = gt153 + else + + if prediction149 == 2 + _t663 = parse_lt_eq(parser) + lt_eq152 = _t663 + _t662 = lt_eq152 + else + + if prediction149 == 1 + _t665 = parse_lt(parser) + lt151 = _t665 + _t664 = lt151 + else + + if prediction149 == 0 + _t667 = parse_eq(parser) + eq150 = _t667 + _t666 = eq150 + else + throw(ParseError("Unexpected token in primitive" * ": " * string(lookahead(parser, 0)))) + end + _t664 = _t666 + end + _t662 = _t664 + end + _t660 = _t662 + end + _t658 = _t660 + end + _t656 = _t658 + end + _t654 = _t656 + end + _t652 = _t654 + end + _t650 = _t652 + end + _t646 = _t650 + end + return _t646 +end + +function parse_eq(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "=") + _t668 = parse_term(parser) + term164 = _t668 + _t669 = parse_term(parser) + term_3165 = _t669 + consume_literal!(parser, ")") + _t670 = Proto.RelTerm(rel_term_type=OneOf(:term, term164)) + _t671 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3165)) + _t672 = Proto.Primitive(name="rel_primitive_eq", terms=Proto.RelTerm[_t670, _t671]) + return _t672 +end + +function parse_lt(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "<") + _t673 = parse_term(parser) + term166 = _t673 + _t674 = parse_term(parser) + term_3167 = _t674 + consume_literal!(parser, ")") + _t675 = Proto.RelTerm(rel_term_type=OneOf(:term, term166)) + _t676 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3167)) + _t677 = Proto.Primitive(name="rel_primitive_lt_monotype", terms=Proto.RelTerm[_t675, _t676]) + return _t677 +end + +function parse_lt_eq(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "<=") + _t678 = parse_term(parser) + term168 = _t678 + _t679 = parse_term(parser) + term_3169 = _t679 + consume_literal!(parser, ")") + _t680 = Proto.RelTerm(rel_term_type=OneOf(:term, term168)) + _t681 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3169)) + _t682 = Proto.Primitive(name="rel_primitive_lt_eq_monotype", terms=Proto.RelTerm[_t680, _t681]) + return _t682 +end + +function parse_gt(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, ">") + _t683 = parse_term(parser) + term170 = _t683 + _t684 = parse_term(parser) + term_3171 = _t684 + consume_literal!(parser, ")") + _t685 = Proto.RelTerm(rel_term_type=OneOf(:term, term170)) + _t686 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3171)) + _t687 = Proto.Primitive(name="rel_primitive_gt_monotype", terms=Proto.RelTerm[_t685, _t686]) + return _t687 +end + +function parse_gt_eq(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, ">=") + _t688 = parse_term(parser) + term172 = _t688 + _t689 = parse_term(parser) + term_3173 = _t689 + consume_literal!(parser, ")") + _t690 = Proto.RelTerm(rel_term_type=OneOf(:term, term172)) + _t691 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3173)) + _t692 = Proto.Primitive(name="rel_primitive_gt_eq_monotype", terms=Proto.RelTerm[_t690, _t691]) + return _t692 +end + +function parse_add(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "+") + _t693 = parse_term(parser) + term174 = _t693 + _t694 = parse_term(parser) + term_3175 = _t694 + _t695 = parse_term(parser) + term_4176 = _t695 + consume_literal!(parser, ")") + _t696 = Proto.RelTerm(rel_term_type=OneOf(:term, term174)) + _t697 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3175)) + _t698 = Proto.RelTerm(rel_term_type=OneOf(:term, term_4176)) + _t699 = Proto.Primitive(name="rel_primitive_add_monotype", terms=Proto.RelTerm[_t696, _t697, _t698]) + return _t699 +end + +function parse_minus(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "-") + _t700 = parse_term(parser) + term177 = _t700 + _t701 = parse_term(parser) + term_3178 = _t701 + _t702 = parse_term(parser) + term_4179 = _t702 + consume_literal!(parser, ")") + _t703 = Proto.RelTerm(rel_term_type=OneOf(:term, term177)) + _t704 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3178)) + _t705 = Proto.RelTerm(rel_term_type=OneOf(:term, term_4179)) + _t706 = Proto.Primitive(name="rel_primitive_subtract_monotype", terms=Proto.RelTerm[_t703, _t704, _t705]) + return _t706 +end + +function parse_multiply(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "*") + _t707 = parse_term(parser) + term180 = _t707 + _t708 = parse_term(parser) + term_3181 = _t708 + _t709 = parse_term(parser) + term_4182 = _t709 + consume_literal!(parser, ")") + _t710 = Proto.RelTerm(rel_term_type=OneOf(:term, term180)) + _t711 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3181)) + _t712 = Proto.RelTerm(rel_term_type=OneOf(:term, term_4182)) + _t713 = Proto.Primitive(name="rel_primitive_multiply_monotype", terms=Proto.RelTerm[_t710, _t711, _t712]) + return _t713 +end + +function parse_divide(parser::Parser)::Proto.Primitive + consume_literal!(parser, "(") + consume_literal!(parser, "/") + _t714 = parse_term(parser) + term183 = _t714 + _t715 = parse_term(parser) + term_3184 = _t715 + _t716 = parse_term(parser) + term_4185 = _t716 + consume_literal!(parser, ")") + _t717 = Proto.RelTerm(rel_term_type=OneOf(:term, term183)) + _t718 = Proto.RelTerm(rel_term_type=OneOf(:term, term_3184)) + _t719 = Proto.RelTerm(rel_term_type=OneOf(:term, term_4185)) + _t720 = Proto.Primitive(name="rel_primitive_divide_monotype", terms=Proto.RelTerm[_t717, _t718, _t719]) + return _t720 +end + +function parse_rel_term(parser::Parser)::Proto.RelTerm + + if match_lookahead_literal(parser, "true", 0) + _t721 = 1 + else + + if match_lookahead_literal(parser, "missing", 0) + _t722 = 1 + else + + if match_lookahead_literal(parser, "false", 0) + _t723 = 1 + else + + if match_lookahead_literal(parser, "(", 0) + _t724 = 1 + else + + if match_lookahead_literal(parser, "#", 0) + _t725 = 0 + else + + if match_lookahead_terminal(parser, "UINT128", 0) + _t726 = 1 + else + + if match_lookahead_terminal(parser, "SYMBOL", 0) + _t727 = 1 + else + + if match_lookahead_terminal(parser, "STRING", 0) + _t728 = 1 + else + + if match_lookahead_terminal(parser, "INT128", 0) + _t729 = 1 + else + + if match_lookahead_terminal(parser, "INT", 0) + _t730 = 1 + else + + if match_lookahead_terminal(parser, "FLOAT", 0) + _t731 = 1 + else + + if match_lookahead_terminal(parser, "DECIMAL", 0) + _t732 = 1 + else + _t732 = -1 + end + _t731 = _t732 + end + _t730 = _t731 + end + _t729 = _t730 + end + _t728 = _t729 + end + _t727 = _t728 + end + _t726 = _t727 + end + _t725 = _t726 + end + _t724 = _t725 + end + _t723 = _t724 + end + _t722 = _t723 + end + _t721 = _t722 + end + prediction186 = _t721 + + if prediction186 == 1 + _t734 = parse_term(parser) + term188 = _t734 + _t735 = Proto.RelTerm(rel_term_type=OneOf(:term, term188)) + _t733 = _t735 + else + + if prediction186 == 0 + _t737 = parse_specialized_value(parser) + specialized_value187 = _t737 + _t738 = Proto.RelTerm(rel_term_type=OneOf(:specialized_value, specialized_value187)) + _t736 = _t738 + else + throw(ParseError("Unexpected token in rel_term" * ": " * string(lookahead(parser, 0)))) + end + _t733 = _t736 + end + return _t733 +end + +function parse_specialized_value(parser::Parser)::Proto.Value + consume_literal!(parser, "#") + _t739 = parse_value(parser) + value189 = _t739 + return value189 +end + +function parse_rel_atom(parser::Parser)::Proto.RelAtom + consume_literal!(parser, "(") + consume_literal!(parser, "relatom") + _t740 = parse_name(parser) + name190 = _t740 + xs191 = Proto.RelTerm[] + cond192 = (((((((((((match_lookahead_literal(parser, "#", 0) || match_lookahead_literal(parser, "(", 0)) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond192 + _t741 = parse_rel_term(parser) + item193 = _t741 + push!(xs191, item193) + cond192 = (((((((((((match_lookahead_literal(parser, "#", 0) || match_lookahead_literal(parser, "(", 0)) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "SYMBOL", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + rel_terms194 = xs191 + consume_literal!(parser, ")") + _t742 = Proto.RelAtom(name=name190, terms=rel_terms194) + return _t742 +end + +function parse_cast(parser::Parser)::Proto.Cast + consume_literal!(parser, "(") + consume_literal!(parser, "cast") + _t743 = parse_term(parser) + term195 = _t743 + _t744 = parse_term(parser) + term_3196 = _t744 + consume_literal!(parser, ")") + _t745 = Proto.Cast(input=term195, result=term_3196) + return _t745 +end + +function parse_attrs(parser::Parser)::Vector{Proto.Attribute} + consume_literal!(parser, "(") + consume_literal!(parser, "attrs") + xs197 = Proto.Attribute[] + cond198 = match_lookahead_literal(parser, "(", 0) + while cond198 + _t746 = parse_attribute(parser) + item199 = _t746 + push!(xs197, item199) + cond198 = match_lookahead_literal(parser, "(", 0) + end + attributes200 = xs197 + consume_literal!(parser, ")") + return attributes200 +end + +function parse_attribute(parser::Parser)::Proto.Attribute + consume_literal!(parser, "(") + consume_literal!(parser, "attribute") + _t747 = parse_name(parser) + name201 = _t747 + xs202 = Proto.Value[] + cond203 = (((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond203 + _t748 = parse_value(parser) + item204 = _t748 + push!(xs202, item204) + cond203 = (((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "false", 0)) || match_lookahead_literal(parser, "missing", 0)) || match_lookahead_literal(parser, "true", 0)) || match_lookahead_terminal(parser, "DECIMAL", 0)) || match_lookahead_terminal(parser, "FLOAT", 0)) || match_lookahead_terminal(parser, "INT", 0)) || match_lookahead_terminal(parser, "INT128", 0)) || match_lookahead_terminal(parser, "STRING", 0)) || match_lookahead_terminal(parser, "UINT128", 0)) + end + values205 = xs202 + consume_literal!(parser, ")") + _t749 = Proto.Attribute(name=name201, args=values205) + return _t749 +end + +function parse_algorithm(parser::Parser)::Proto.Algorithm + consume_literal!(parser, "(") + consume_literal!(parser, "algorithm") + xs206 = Proto.RelationId[] + cond207 = (match_lookahead_literal(parser, ":", 0) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond207 + _t750 = parse_relation_id(parser) + item208 = _t750 + push!(xs206, item208) + cond207 = (match_lookahead_literal(parser, ":", 0) || match_lookahead_terminal(parser, "UINT128", 0)) + end + relation_ids209 = xs206 + _t751 = parse_script(parser) + script210 = _t751 + consume_literal!(parser, ")") + _t752 = Proto.Algorithm(var"#global"=relation_ids209, body=script210) + return _t752 +end + +function parse_script(parser::Parser)::Proto.Script + consume_literal!(parser, "(") + consume_literal!(parser, "script") + xs211 = Proto.Construct[] + cond212 = match_lookahead_literal(parser, "(", 0) + while cond212 + _t753 = parse_construct(parser) + item213 = _t753 + push!(xs211, item213) + cond212 = match_lookahead_literal(parser, "(", 0) + end + constructs214 = xs211 + consume_literal!(parser, ")") + _t754 = Proto.Script(constructs=constructs214) + return _t754 +end + +function parse_construct(parser::Parser)::Proto.Construct + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "upsert", 1) + _t756 = 1 + else + + if match_lookahead_literal(parser, "monus", 1) + _t757 = 1 + else + + if match_lookahead_literal(parser, "monoid", 1) + _t758 = 1 + else + + if match_lookahead_literal(parser, "loop", 1) + _t759 = 0 + else + + if match_lookahead_literal(parser, "break", 1) + _t760 = 1 + else + + if match_lookahead_literal(parser, "assign", 1) + _t761 = 1 + else + _t761 = -1 + end + _t760 = _t761 + end + _t759 = _t760 + end + _t758 = _t759 + end + _t757 = _t758 + end + _t756 = _t757 + end + _t755 = _t756 + else + _t755 = -1 + end + prediction215 = _t755 + + if prediction215 == 1 + _t763 = parse_instruction(parser) + instruction217 = _t763 + _t764 = Proto.Construct(construct_type=OneOf(:instruction, instruction217)) + _t762 = _t764 + else + + if prediction215 == 0 + _t766 = parse_loop(parser) + loop216 = _t766 + _t767 = Proto.Construct(construct_type=OneOf(:loop, loop216)) + _t765 = _t767 + else + throw(ParseError("Unexpected token in construct" * ": " * string(lookahead(parser, 0)))) + end + _t762 = _t765 + end + return _t762 +end + +function parse_loop(parser::Parser)::Proto.Loop + consume_literal!(parser, "(") + consume_literal!(parser, "loop") + _t768 = parse_init(parser) + init218 = _t768 + _t769 = parse_script(parser) + script219 = _t769 + consume_literal!(parser, ")") + _t770 = Proto.Loop(init=init218, body=script219) + return _t770 +end + +function parse_init(parser::Parser)::Vector{Proto.Instruction} + consume_literal!(parser, "(") + consume_literal!(parser, "init") + xs220 = Proto.Instruction[] + cond221 = match_lookahead_literal(parser, "(", 0) + while cond221 + _t771 = parse_instruction(parser) + item222 = _t771 + push!(xs220, item222) + cond221 = match_lookahead_literal(parser, "(", 0) + end + instructions223 = xs220 + consume_literal!(parser, ")") + return instructions223 +end + +function parse_instruction(parser::Parser)::Proto.Instruction + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "upsert", 1) + _t773 = 1 + else + + if match_lookahead_literal(parser, "monus", 1) + _t774 = 4 + else + + if match_lookahead_literal(parser, "monoid", 1) + _t775 = 3 + else + + if match_lookahead_literal(parser, "break", 1) + _t776 = 2 + else + + if match_lookahead_literal(parser, "assign", 1) + _t777 = 0 + else + _t777 = -1 + end + _t776 = _t777 + end + _t775 = _t776 + end + _t774 = _t775 + end + _t773 = _t774 + end + _t772 = _t773 + else + _t772 = -1 + end + prediction224 = _t772 + + if prediction224 == 4 + _t779 = parse_monus_def(parser) + monus_def229 = _t779 + _t780 = Proto.Instruction(instr_type=OneOf(:monus_def, monus_def229)) + _t778 = _t780 + else + + if prediction224 == 3 + _t782 = parse_monoid_def(parser) + monoid_def228 = _t782 + _t783 = Proto.Instruction(instr_type=OneOf(:monoid_def, monoid_def228)) + _t781 = _t783 + else + + if prediction224 == 2 + _t785 = parse_break(parser) + break227 = _t785 + _t786 = Proto.Instruction(instr_type=OneOf(:var"#break", break227)) + _t784 = _t786 + else + + if prediction224 == 1 + _t788 = parse_upsert(parser) + upsert226 = _t788 + _t789 = Proto.Instruction(instr_type=OneOf(:upsert, upsert226)) + _t787 = _t789 + else + + if prediction224 == 0 + _t791 = parse_assign(parser) + assign225 = _t791 + _t792 = Proto.Instruction(instr_type=OneOf(:assign, assign225)) + _t790 = _t792 + else + throw(ParseError("Unexpected token in instruction" * ": " * string(lookahead(parser, 0)))) + end + _t787 = _t790 + end + _t784 = _t787 + end + _t781 = _t784 + end + _t778 = _t781 + end + return _t778 +end + +function parse_assign(parser::Parser)::Proto.Assign + consume_literal!(parser, "(") + consume_literal!(parser, "assign") + _t793 = parse_relation_id(parser) + relation_id230 = _t793 + _t794 = parse_abstraction(parser) + abstraction231 = _t794 + + if match_lookahead_literal(parser, "(", 0) + _t796 = parse_attrs(parser) + _t795 = _t796 + else + _t795 = nothing + end + attrs232 = _t795 + consume_literal!(parser, ")") + _t797 = Proto.Assign(name=relation_id230, body=abstraction231, attrs=(!isnothing(attrs232) ? attrs232 : Proto.Attribute[])) + return _t797 +end + +function parse_upsert(parser::Parser)::Proto.Upsert + consume_literal!(parser, "(") + consume_literal!(parser, "upsert") + _t798 = parse_relation_id(parser) + relation_id233 = _t798 + _t799 = parse_abstraction_with_arity(parser) + abstraction_with_arity234 = _t799 + + if match_lookahead_literal(parser, "(", 0) + _t801 = parse_attrs(parser) + _t800 = _t801 + else + _t800 = nothing + end + attrs235 = _t800 + consume_literal!(parser, ")") + _t802 = Proto.Upsert(name=relation_id233, body=abstraction_with_arity234[1], attrs=(!isnothing(attrs235) ? attrs235 : Proto.Attribute[]), value_arity=abstraction_with_arity234[2]) + return _t802 +end + +function parse_abstraction_with_arity(parser::Parser)::Tuple{Proto.Abstraction, Int64} + consume_literal!(parser, "(") + _t803 = parse_bindings(parser) + bindings236 = _t803 + _t804 = parse_formula(parser) + formula237 = _t804 + consume_literal!(parser, ")") + _t805 = Proto.Abstraction(vars=vcat(bindings236[1], !isnothing(bindings236[2]) ? bindings236[2] : []), value=formula237) + return (_t805, length(bindings236[2]),) +end + +function parse_break(parser::Parser)::Proto.Break + consume_literal!(parser, "(") + consume_literal!(parser, "break") + _t806 = parse_relation_id(parser) + relation_id238 = _t806 + _t807 = parse_abstraction(parser) + abstraction239 = _t807 + + if match_lookahead_literal(parser, "(", 0) + _t809 = parse_attrs(parser) + _t808 = _t809 + else + _t808 = nothing + end + attrs240 = _t808 + consume_literal!(parser, ")") + _t810 = Proto.Break(name=relation_id238, body=abstraction239, attrs=(!isnothing(attrs240) ? attrs240 : Proto.Attribute[])) + return _t810 +end + +function parse_monoid_def(parser::Parser)::Proto.MonoidDef + consume_literal!(parser, "(") + consume_literal!(parser, "monoid") + _t811 = parse_monoid(parser) + monoid241 = _t811 + _t812 = parse_relation_id(parser) + relation_id242 = _t812 + _t813 = parse_abstraction_with_arity(parser) + abstraction_with_arity243 = _t813 + + if match_lookahead_literal(parser, "(", 0) + _t815 = parse_attrs(parser) + _t814 = _t815 + else + _t814 = nothing + end + attrs244 = _t814 + consume_literal!(parser, ")") + _t816 = Proto.MonoidDef(monoid=monoid241, name=relation_id242, body=abstraction_with_arity243[1], attrs=(!isnothing(attrs244) ? attrs244 : Proto.Attribute[]), value_arity=abstraction_with_arity243[2]) + return _t816 +end + +function parse_monoid(parser::Parser)::Proto.Monoid + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "sum", 1) + _t818 = 3 + else + + if match_lookahead_literal(parser, "or", 1) + _t819 = 0 + else + + if match_lookahead_literal(parser, "min", 1) + _t820 = 1 + else + + if match_lookahead_literal(parser, "max", 1) + _t821 = 2 + else + _t821 = -1 + end + _t820 = _t821 + end + _t819 = _t820 + end + _t818 = _t819 + end + _t817 = _t818 + else + _t817 = -1 + end + prediction245 = _t817 + + if prediction245 == 3 + _t823 = parse_sum_monoid(parser) + sum_monoid249 = _t823 + _t824 = Proto.Monoid(value=OneOf(:sum_monoid, sum_monoid249)) + _t822 = _t824 + else + + if prediction245 == 2 + _t826 = parse_max_monoid(parser) + max_monoid248 = _t826 + _t827 = Proto.Monoid(value=OneOf(:max_monoid, max_monoid248)) + _t825 = _t827 + else + + if prediction245 == 1 + _t829 = parse_min_monoid(parser) + min_monoid247 = _t829 + _t830 = Proto.Monoid(value=OneOf(:min_monoid, min_monoid247)) + _t828 = _t830 + else + + if prediction245 == 0 + _t832 = parse_or_monoid(parser) + or_monoid246 = _t832 + _t833 = Proto.Monoid(value=OneOf(:or_monoid, or_monoid246)) + _t831 = _t833 + else + throw(ParseError("Unexpected token in monoid" * ": " * string(lookahead(parser, 0)))) + end + _t828 = _t831 + end + _t825 = _t828 + end + _t822 = _t825 + end + return _t822 +end + +function parse_or_monoid(parser::Parser)::Proto.OrMonoid + consume_literal!(parser, "(") + consume_literal!(parser, "or") + consume_literal!(parser, ")") + _t834 = Proto.OrMonoid() + return _t834 +end + +function parse_min_monoid(parser::Parser)::Proto.MinMonoid + consume_literal!(parser, "(") + consume_literal!(parser, "min") + _t835 = parse_type(parser) + type250 = _t835 + consume_literal!(parser, ")") + _t836 = Proto.MinMonoid(var"#type"=type250) + return _t836 +end + +function parse_max_monoid(parser::Parser)::Proto.MaxMonoid + consume_literal!(parser, "(") + consume_literal!(parser, "max") + _t837 = parse_type(parser) + type251 = _t837 + consume_literal!(parser, ")") + _t838 = Proto.MaxMonoid(var"#type"=type251) + return _t838 +end + +function parse_sum_monoid(parser::Parser)::Proto.SumMonoid + consume_literal!(parser, "(") + consume_literal!(parser, "sum") + _t839 = parse_type(parser) + type252 = _t839 + consume_literal!(parser, ")") + _t840 = Proto.SumMonoid(var"#type"=type252) + return _t840 +end + +function parse_monus_def(parser::Parser)::Proto.MonusDef + consume_literal!(parser, "(") + consume_literal!(parser, "monus") + _t841 = parse_monoid(parser) + monoid253 = _t841 + _t842 = parse_relation_id(parser) + relation_id254 = _t842 + _t843 = parse_abstraction_with_arity(parser) + abstraction_with_arity255 = _t843 + + if match_lookahead_literal(parser, "(", 0) + _t845 = parse_attrs(parser) + _t844 = _t845 + else + _t844 = nothing + end + attrs256 = _t844 + consume_literal!(parser, ")") + _t846 = Proto.MonusDef(monoid=monoid253, name=relation_id254, body=abstraction_with_arity255[1], attrs=(!isnothing(attrs256) ? attrs256 : Proto.Attribute[]), value_arity=abstraction_with_arity255[2]) + return _t846 +end + +function parse_constraint(parser::Parser)::Proto.Constraint + consume_literal!(parser, "(") + consume_literal!(parser, "functional_dependency") + _t847 = parse_relation_id(parser) + relation_id257 = _t847 + _t848 = parse_abstraction(parser) + abstraction258 = _t848 + _t849 = parse_functional_dependency_keys(parser) + functional_dependency_keys259 = _t849 + _t850 = parse_functional_dependency_values(parser) + functional_dependency_values260 = _t850 + consume_literal!(parser, ")") + _t851 = Proto.FunctionalDependency(abstraction258, functional_dependency_keys259, functional_dependency_values260) + _t852 = Proto.Constraint(relation_id257, OneOf(:functional_dependency, _t851)) + return _t852 +end + +function parse_functional_dependency_keys(parser::Parser)::Vector{Proto.Var} + consume_literal!(parser, "(") + consume_literal!(parser, "keys") + xs261 = Proto.Var[] + cond262 = match_lookahead_terminal(parser, "SYMBOL", 0) + while cond262 + _t853 = parse_var(parser) + item263 = _t853 + push!(xs261, item263) + cond262 = match_lookahead_terminal(parser, "SYMBOL", 0) + end + vars264 = xs261 + consume_literal!(parser, ")") + return vars264 +end + +function parse_functional_dependency_values(parser::Parser)::Vector{Proto.Var} + consume_literal!(parser, "(") + consume_literal!(parser, "values") + xs265 = Proto.Var[] + cond266 = match_lookahead_terminal(parser, "SYMBOL", 0) + while cond266 + _t854 = parse_var(parser) + item267 = _t854 + push!(xs265, item267) + cond266 = match_lookahead_terminal(parser, "SYMBOL", 0) + end + vars268 = xs265 + consume_literal!(parser, ")") + return vars268 +end + +function parse_data(parser::Parser)::Proto.Data + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "rel_edb", 1) + _t856 = 0 + else + + if match_lookahead_literal(parser, "csv_data", 1) + _t857 = 2 + else + + if match_lookahead_literal(parser, "betree_relation", 1) + _t858 = 1 + else + _t858 = -1 + end + _t857 = _t858 + end + _t856 = _t857 + end + _t855 = _t856 + else + _t855 = -1 + end + prediction269 = _t855 + + if prediction269 == 2 + _t860 = parse_csv_data(parser) + csv_data272 = _t860 + _t861 = Proto.Data(data_type=OneOf(:csv_data, csv_data272)) + _t859 = _t861 + else + + if prediction269 == 1 + _t863 = parse_betree_relation(parser) + betree_relation271 = _t863 + _t864 = Proto.Data(data_type=OneOf(:betree_relation, betree_relation271)) + _t862 = _t864 + else + + if prediction269 == 0 + _t866 = parse_rel_edb(parser) + rel_edb270 = _t866 + _t867 = Proto.Data(data_type=OneOf(:rel_edb, rel_edb270)) + _t865 = _t867 + else + throw(ParseError("Unexpected token in data" * ": " * string(lookahead(parser, 0)))) + end + _t862 = _t865 + end + _t859 = _t862 + end + return _t859 +end + +function parse_rel_edb(parser::Parser)::Proto.RelEDB + consume_literal!(parser, "(") + consume_literal!(parser, "rel_edb") + _t868 = parse_relation_id(parser) + relation_id273 = _t868 + _t869 = parse_rel_edb_path(parser) + rel_edb_path274 = _t869 + _t870 = parse_rel_edb_types(parser) + rel_edb_types275 = _t870 + consume_literal!(parser, ")") + _t871 = Proto.RelEDB(target_id=relation_id273, path=rel_edb_path274, types=rel_edb_types275) + return _t871 +end + +function parse_rel_edb_path(parser::Parser)::Vector{String} + consume_literal!(parser, "[") + xs276 = String[] + cond277 = match_lookahead_terminal(parser, "STRING", 0) + while cond277 + item278 = consume_terminal!(parser, "STRING") + push!(xs276, item278) + cond277 = match_lookahead_terminal(parser, "STRING", 0) + end + strings279 = xs276 + consume_literal!(parser, "]") + return strings279 +end + +function parse_rel_edb_types(parser::Parser)::Vector{Proto.var"#Type"} + consume_literal!(parser, "[") + xs280 = Proto.var"#Type"[] + cond281 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + while cond281 + _t872 = parse_type(parser) + item282 = _t872 + push!(xs280, item282) + cond281 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + end + types283 = xs280 + consume_literal!(parser, "]") + return types283 +end + +function parse_betree_relation(parser::Parser)::Proto.BeTreeRelation + consume_literal!(parser, "(") + consume_literal!(parser, "betree_relation") + _t873 = parse_relation_id(parser) + relation_id284 = _t873 + _t874 = parse_betree_info(parser) + betree_info285 = _t874 + consume_literal!(parser, ")") + _t875 = Proto.BeTreeRelation(name=relation_id284, relation_info=betree_info285) + return _t875 +end + +function parse_betree_info(parser::Parser)::Proto.BeTreeInfo + consume_literal!(parser, "(") + consume_literal!(parser, "betree_info") + _t876 = parse_betree_info_key_types(parser) + betree_info_key_types286 = _t876 + _t877 = parse_betree_info_value_types(parser) + betree_info_value_types287 = _t877 + _t878 = parse_config_dict(parser) + config_dict288 = _t878 + consume_literal!(parser, ")") + _t879 = construct_betree_info(parser, betree_info_key_types286, betree_info_value_types287, config_dict288) + return _t879 +end + +function parse_betree_info_key_types(parser::Parser)::Vector{Proto.var"#Type"} + consume_literal!(parser, "(") + consume_literal!(parser, "key_types") + xs289 = Proto.var"#Type"[] + cond290 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + while cond290 + _t880 = parse_type(parser) + item291 = _t880 + push!(xs289, item291) + cond290 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + end + types292 = xs289 + consume_literal!(parser, ")") + return types292 +end + +function parse_betree_info_value_types(parser::Parser)::Vector{Proto.var"#Type"} + consume_literal!(parser, "(") + consume_literal!(parser, "value_types") + xs293 = Proto.var"#Type"[] + cond294 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + while cond294 + _t881 = parse_type(parser) + item295 = _t881 + push!(xs293, item295) + cond294 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + end + types296 = xs293 + consume_literal!(parser, ")") + return types296 +end + +function parse_csv_data(parser::Parser)::Proto.CSVData + consume_literal!(parser, "(") + consume_literal!(parser, "csv_data") + _t882 = parse_csvlocator(parser) + csvlocator297 = _t882 + _t883 = parse_csv_config(parser) + csv_config298 = _t883 + _t884 = parse_csv_columns(parser) + csv_columns299 = _t884 + _t885 = parse_csv_asof(parser) + csv_asof300 = _t885 + consume_literal!(parser, ")") + _t886 = Proto.CSVData(locator=csvlocator297, config=csv_config298, columns=csv_columns299, asof=csv_asof300) + return _t886 +end + +function parse_csvlocator(parser::Parser)::Proto.CSVLocator + consume_literal!(parser, "(") + consume_literal!(parser, "csv_locator") + + if (match_lookahead_literal(parser, "(", 0) && match_lookahead_literal(parser, "paths", 1)) + _t888 = parse_csv_locator_paths(parser) + _t887 = _t888 + else + _t887 = nothing + end + csv_locator_paths301 = _t887 + + if match_lookahead_literal(parser, "(", 0) + _t890 = parse_csv_locator_inline_data(parser) + _t889 = _t890 + else + _t889 = nothing + end + csv_locator_inline_data302 = _t889 + consume_literal!(parser, ")") + _t891 = Proto.CSVLocator(paths=(!isnothing(csv_locator_paths301) ? csv_locator_paths301 : String[]), inline_data=Vector{UInt8}((!isnothing(csv_locator_inline_data302) ? csv_locator_inline_data302 : ""))) + return _t891 +end + +function parse_csv_locator_paths(parser::Parser)::Vector{String} + consume_literal!(parser, "(") + consume_literal!(parser, "paths") + xs303 = String[] + cond304 = match_lookahead_terminal(parser, "STRING", 0) + while cond304 + item305 = consume_terminal!(parser, "STRING") + push!(xs303, item305) + cond304 = match_lookahead_terminal(parser, "STRING", 0) + end + strings306 = xs303 + consume_literal!(parser, ")") + return strings306 +end + +function parse_csv_locator_inline_data(parser::Parser)::String + consume_literal!(parser, "(") + consume_literal!(parser, "inline_data") + string307 = consume_terminal!(parser, "STRING") + consume_literal!(parser, ")") + return string307 +end + +function parse_csv_config(parser::Parser)::Proto.CSVConfig + consume_literal!(parser, "(") + consume_literal!(parser, "csv_config") + _t892 = parse_config_dict(parser) + config_dict308 = _t892 + consume_literal!(parser, ")") + _t893 = construct_csv_config(parser, config_dict308) + return _t893 +end + +function parse_csv_columns(parser::Parser)::Vector{Proto.CSVColumn} + consume_literal!(parser, "(") + consume_literal!(parser, "columns") + xs309 = Proto.CSVColumn[] + cond310 = match_lookahead_literal(parser, "(", 0) + while cond310 + _t894 = parse_csv_column(parser) + item311 = _t894 + push!(xs309, item311) + cond310 = match_lookahead_literal(parser, "(", 0) + end + csv_columns312 = xs309 + consume_literal!(parser, ")") + return csv_columns312 +end + +function parse_csv_column(parser::Parser)::Proto.CSVColumn + consume_literal!(parser, "(") + consume_literal!(parser, "column") + string313 = consume_terminal!(parser, "STRING") + _t895 = parse_relation_id(parser) + relation_id314 = _t895 + consume_literal!(parser, "[") + xs315 = Proto.var"#Type"[] + cond316 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + while cond316 + _t896 = parse_type(parser) + item317 = _t896 + push!(xs315, item317) + cond316 = ((((((((((match_lookahead_literal(parser, "(", 0) || match_lookahead_literal(parser, "BOOLEAN", 0)) || match_lookahead_literal(parser, "DATE", 0)) || match_lookahead_literal(parser, "DATETIME", 0)) || match_lookahead_literal(parser, "FLOAT", 0)) || match_lookahead_literal(parser, "INT", 0)) || match_lookahead_literal(parser, "INT128", 0)) || match_lookahead_literal(parser, "MISSING", 0)) || match_lookahead_literal(parser, "STRING", 0)) || match_lookahead_literal(parser, "UINT128", 0)) || match_lookahead_literal(parser, "UNKNOWN", 0)) + end + types318 = xs315 + consume_literal!(parser, "]") + consume_literal!(parser, ")") + _t897 = Proto.CSVColumn(column_name=string313, target_id=relation_id314, types=types318) + return _t897 +end + +function parse_csv_asof(parser::Parser)::String + consume_literal!(parser, "(") + consume_literal!(parser, "asof") + string319 = consume_terminal!(parser, "STRING") + consume_literal!(parser, ")") + return string319 +end + +function parse_undefine(parser::Parser)::Proto.Undefine + consume_literal!(parser, "(") + consume_literal!(parser, "undefine") + _t898 = parse_fragment_id(parser) + fragment_id320 = _t898 + consume_literal!(parser, ")") + _t899 = Proto.Undefine(fragment_id=fragment_id320) + return _t899 +end + +function parse_context(parser::Parser)::Proto.Context + consume_literal!(parser, "(") + consume_literal!(parser, "context") + xs321 = Proto.RelationId[] + cond322 = (match_lookahead_literal(parser, ":", 0) || match_lookahead_terminal(parser, "UINT128", 0)) + while cond322 + _t900 = parse_relation_id(parser) + item323 = _t900 + push!(xs321, item323) + cond322 = (match_lookahead_literal(parser, ":", 0) || match_lookahead_terminal(parser, "UINT128", 0)) + end + relation_ids324 = xs321 + consume_literal!(parser, ")") + _t901 = Proto.Context(relations=relation_ids324) + return _t901 +end + +function parse_epoch_reads(parser::Parser)::Vector{Proto.Read} + consume_literal!(parser, "(") + consume_literal!(parser, "reads") + xs325 = Proto.Read[] + cond326 = match_lookahead_literal(parser, "(", 0) + while cond326 + _t902 = parse_read(parser) + item327 = _t902 + push!(xs325, item327) + cond326 = match_lookahead_literal(parser, "(", 0) + end + reads328 = xs325 + consume_literal!(parser, ")") + return reads328 +end + +function parse_read(parser::Parser)::Proto.Read + + if match_lookahead_literal(parser, "(", 0) + + if match_lookahead_literal(parser, "what_if", 1) + _t904 = 2 + else + + if match_lookahead_literal(parser, "output", 1) + _t905 = 1 + else + + if match_lookahead_literal(parser, "export", 1) + _t906 = 4 + else + + if match_lookahead_literal(parser, "demand", 1) + _t907 = 0 + else + + if match_lookahead_literal(parser, "abort", 1) + _t908 = 3 + else + _t908 = -1 + end + _t907 = _t908 + end + _t906 = _t907 + end + _t905 = _t906 + end + _t904 = _t905 + end + _t903 = _t904 + else + _t903 = -1 + end + prediction329 = _t903 + + if prediction329 == 4 + _t910 = parse_export(parser) + export334 = _t910 + _t911 = Proto.Read(read_type=OneOf(:var"#export", export334)) + _t909 = _t911 + else + + if prediction329 == 3 + _t913 = parse_abort(parser) + abort333 = _t913 + _t914 = Proto.Read(read_type=OneOf(:abort, abort333)) + _t912 = _t914 + else + + if prediction329 == 2 + _t916 = parse_what_if(parser) + what_if332 = _t916 + _t917 = Proto.Read(read_type=OneOf(:what_if, what_if332)) + _t915 = _t917 + else + + if prediction329 == 1 + _t919 = parse_output(parser) + output331 = _t919 + _t920 = Proto.Read(read_type=OneOf(:output, output331)) + _t918 = _t920 + else + + if prediction329 == 0 + _t922 = parse_demand(parser) + demand330 = _t922 + _t923 = Proto.Read(read_type=OneOf(:demand, demand330)) + _t921 = _t923 + else + throw(ParseError("Unexpected token in read" * ": " * string(lookahead(parser, 0)))) + end + _t918 = _t921 + end + _t915 = _t918 + end + _t912 = _t915 + end + _t909 = _t912 + end + return _t909 +end + +function parse_demand(parser::Parser)::Proto.Demand + consume_literal!(parser, "(") + consume_literal!(parser, "demand") + _t924 = parse_relation_id(parser) + relation_id335 = _t924 + consume_literal!(parser, ")") + _t925 = Proto.Demand(relation_id=relation_id335) + return _t925 +end + +function parse_output(parser::Parser)::Proto.Output + consume_literal!(parser, "(") + consume_literal!(parser, "output") + + if (match_lookahead_literal(parser, ":", 0) && match_lookahead_terminal(parser, "SYMBOL", 1)) + _t927 = parse_name(parser) + _t926 = _t927 + else + _t926 = nothing + end + name336 = _t926 + _t928 = parse_relation_id(parser) + relation_id337 = _t928 + consume_literal!(parser, ")") + _t929 = Proto.Output(name=(!isnothing(name336) ? name336 : "output"), relation_id=relation_id337) + return _t929 +end + +function parse_what_if(parser::Parser)::Proto.WhatIf + consume_literal!(parser, "(") + consume_literal!(parser, "what_if") + _t930 = parse_name(parser) + name338 = _t930 + _t931 = parse_epoch(parser) + epoch339 = _t931 + consume_literal!(parser, ")") + _t932 = Proto.WhatIf(branch=name338, epoch=epoch339) + return _t932 +end + +function parse_abort(parser::Parser)::Proto.Abort + consume_literal!(parser, "(") + consume_literal!(parser, "abort") + + if (match_lookahead_literal(parser, ":", 0) && match_lookahead_terminal(parser, "SYMBOL", 1)) + _t934 = parse_name(parser) + _t933 = _t934 + else + _t933 = nothing + end + name340 = _t933 + _t935 = parse_relation_id(parser) + relation_id341 = _t935 + consume_literal!(parser, ")") + _t936 = Proto.Abort(name=(!isnothing(name340) ? name340 : "abort"), relation_id=relation_id341) + return _t936 +end + +function parse_export(parser::Parser)::Proto.Export + consume_literal!(parser, "(") + consume_literal!(parser, "export") + _t937 = parse_export_csv_config(parser) + export_csv_config342 = _t937 + consume_literal!(parser, ")") + _t938 = Proto.Export(export_config=OneOf(:csv_config, export_csv_config342)) + return _t938 +end + +function parse_export_csv_config(parser::Parser)::Proto.ExportCSVConfig + consume_literal!(parser, "(") + consume_literal!(parser, "export_csv_config") + _t939 = parse_export_csv_path(parser) + export_csv_path343 = _t939 + _t940 = parse_export_csv_columns(parser) + export_csv_columns344 = _t940 + _t941 = parse_config_dict(parser) + config_dict345 = _t941 + consume_literal!(parser, ")") + _t942 = export_csv_config(parser, export_csv_path343, export_csv_columns344, config_dict345) + return _t942 +end + +function parse_export_csv_path(parser::Parser)::String + consume_literal!(parser, "(") + consume_literal!(parser, "path") + string346 = consume_terminal!(parser, "STRING") + consume_literal!(parser, ")") + return string346 +end + +function parse_export_csv_columns(parser::Parser)::Vector{Proto.ExportCSVColumn} + consume_literal!(parser, "(") + consume_literal!(parser, "columns") + xs347 = Proto.ExportCSVColumn[] + cond348 = match_lookahead_literal(parser, "(", 0) + while cond348 + _t943 = parse_export_csv_column(parser) + item349 = _t943 + push!(xs347, item349) + cond348 = match_lookahead_literal(parser, "(", 0) + end + export_csv_columns350 = xs347 + consume_literal!(parser, ")") + return export_csv_columns350 +end + +function parse_export_csv_column(parser::Parser)::Proto.ExportCSVColumn + consume_literal!(parser, "(") + consume_literal!(parser, "column") + string351 = consume_terminal!(parser, "STRING") + _t944 = parse_relation_id(parser) + relation_id352 = _t944 + consume_literal!(parser, ")") + _t945 = Proto.ExportCSVColumn(column_name=string351, column_data=relation_id352) + return _t945 +end + + +function parse(input::String) + lexer = Lexer(input) + parser = Parser(lexer.tokens) + result = parse_transaction(parser) + # Check for unconsumed tokens (except EOF) + if parser.pos <= length(parser.tokens) + remaining_token = lookahead(parser, 0) + if remaining_token.type != "\$" + throw(ParseError("Unexpected token at end of input: $remaining_token")) + end + end + return result +end diff --git a/proto/relationalai/lqp/v1/transactions.proto b/proto/relationalai/lqp/v1/transactions.proto index 6e77b12c..50ac7b07 100644 --- a/proto/relationalai/lqp/v1/transactions.proto +++ b/proto/relationalai/lqp/v1/transactions.proto @@ -16,6 +16,7 @@ message Transaction { message Configure { int64 semantics_version = 1; IVMConfig ivm_config = 2; + OptimizationLevel optimization_level = 3; } message IVMConfig { @@ -29,6 +30,13 @@ enum MaintenanceLevel { MAINTENANCE_LEVEL_ALL = 3; } +enum OptimizationLevel { + OPTIMIZATION_LEVEL_UNSPECIFIED = 0; + OPTIMIZATION_LEVEL_DEFAULT = 1; + OPTIMIZATION_LEVEL_CONSERVATIVE = 2; + OPTIMIZATION_LEVEL_AGGRESSIVE = 3; +} + message Sync { repeated FragmentId fragments = 1; } diff --git a/python-tools/dist/lqp-0.2.3-py3-none-any.whl b/python-tools/dist/lqp-0.2.3-py3-none-any.whl new file mode 100644 index 00000000..02f993c2 Binary files /dev/null and b/python-tools/dist/lqp-0.2.3-py3-none-any.whl differ diff --git a/python-tools/dist/lqp-0.2.3.tar.gz b/python-tools/dist/lqp-0.2.3.tar.gz new file mode 100644 index 00000000..e86e2cc2 Binary files /dev/null and b/python-tools/dist/lqp-0.2.3.tar.gz differ diff --git a/python-tools/src/lqp.egg-info/PKG-INFO b/python-tools/src/lqp.egg-info/PKG-INFO new file mode 100644 index 00000000..9633f17b --- /dev/null +++ b/python-tools/src/lqp.egg-info/PKG-INFO @@ -0,0 +1,172 @@ +Metadata-Version: 2.4 +Name: lqp +Version: 0.2.3 +Summary: Validate and translate Logical Query Protocol (LQP) S-expressions into Protobuf +Author-email: Niko Göbel , David Zhao , Minsung Cho , Martin McGrane , SÅ‚awek Staworko , Nate Nystrom +Description-Content-Type: text/markdown +Requires-Dist: lark>=1.1.9 +Requires-Dist: protobuf<5.0.0,>=3.20.3 +Requires-Dist: colorama +Requires-Dist: more-itertools +Provides-Extra: test +Requires-Dist: pytest>=7.0.0; extra == "test" +Requires-Dist: pytest-snapshot; extra == "test" +Requires-Dist: pyrefly==0.25.1; extra == "test" + +# python-tools + +A command-line tool to parse Logical Query Protocol (LQP) S-expressions into Protobuf binary +and JSON formats. + +## Usage + +``` +usage: lqp [-h] [-v] [--no-validation] [--bin] [--json] [--out] input + +Parse LQP S-expression into Protobuf binary and JSON files. + +positional arguments: + input directory holding .lqp files, or a single .lqp file + +options: + -h, --help show this help message and exit + -v, --version show program's version number and exit + --no-validation don't validate parsed LQP + --bin encode emitted ProtoBuf into binary + --json encode emitted ProtoBuf into JSON + --out write emitted binary or JSON to stdout +``` + +## Examples + +```bash +lqp --no-validation --bin --json foo/bar.lqp +``` +Will create two files in `foo/` named `bar.bin` and `bar.json` containing the binary and JSON encodings of the parsed ProtoBuf. +In this case, the parser will not go through the client-side validations we do to check for well-formed LQP. + +```bash +lqp --bin --json foo +``` +This will look for `.lqp` files both at the top-level and inside an `lqp` subdirectory. +Then it will organize the generated binary and JSON into folders, as well as the original found files. So, for example, if `foo` has this structure: + +``` +foo/ +| bar.lqp +| lqp/ +| | baz.lqp +``` +Then after executing the above command, it should have this structure: + +``` +foo/ +| bin/ +| | bar.bin +| | baz.bin +| json/ +| | bar.json +| | baz.json +| lqp/ +| | bar.lqp +| | baz.lqp +``` + +```bash +lqp --bin --out foo.lqp +``` +Will write the ProtoBuf binary parsed from the `foo.lqp` to stdout. The result can be piped +into the desired output file, e.g., `lqp --bin --out foo.lqp > foo.bin`. + +## Setup +It is recommended to use a Python `virtualenv`. Set one up in the `python-tools` directory +by: +```bash +cd python-tools +python -m venv .venv +``` + +Then activate the virtual environment: +```bash +source .venv/bin/activate +``` + +## Build + +Install preprequisites: +```bash +pip install pip build setuptools wheel +``` + +Then build the module itself: +```bash +python -m build +``` + +Install locally: +```bash +pip install [--user] [--force-reinstall] dist/lqp-0.1.0-py3-none-any.whl +``` + +## Running tests + +Within `python-tools`, + +Setup: +```bash +python -m pip install -e ".[test]" +python -m pip install pyrefly +``` + +Running tests: +```bash +python -m pytest +``` + +To add testcases, add a `.lqp` file to the `tests/test_files/lqp` subdirectory. New +files get picked up automatically. To generate or update the corresponding output files +(binary, debug mode, and pretty-printing snapshots), run `pytest --snapshot-update`. + +Type checking: +```bash +pyrefly check +``` + +## Formatting + +The LQP S-expression syntax was chosen to align with that of [the Clojure programming +language](https://clojure.org/), in order to leverage the existing tools in that ecosystem. +LQP syntax should be formatted via [cljfmt](https://github.com/weavejester/cljfmt) with the +following configuration: + +```clojure +;; .cljfmt.edn +{:indents {#re ".*" [[:inner 0]]} + :remove-surrounding-whitespace? false + :remove-trailing-whitespace? false + :remove-consecutive-blank-lines? false} +``` + +This configuration is explained [here](https://tonsky.me/blog/clojurefmt/) and simply works +better for LQP, which does not have many of the Clojure keywords that are treated as special +cases during formatting by default. + +See the next section for an easy way to integrate `cljfmt` into your VSCode workflow. + +## VSCode + +Editing nested S-expressions by hand can get a little tedious, which is why +[paredit](https://calva.io/paredit/) is an established tool in the Clojure world. To +integrate `paredit` and `cljfmt` into your VSCode workflow, just install [the Calva +extension](https://calva.io/) and [follow the configuration +guide](https://calva.io/formatting/#configuration) to use the `cljfmt` configuration pasted +in the previous section. + +Out-of-the-box, Calva also runs a Clojure linter, which of course does not know what to do +with LQP, resulting in lots of squiggly lines. For that reason, it is also advisable to +create the following config file at `.lsp/config.edn` from the project root: + +```clojure +;; .lsp/config.edn +{:linters {:clj-kondo {:level :off}}} +``` diff --git a/python-tools/src/lqp.egg-info/SOURCES.txt b/python-tools/src/lqp.egg-info/SOURCES.txt new file mode 100644 index 00000000..b08cb1ee --- /dev/null +++ b/python-tools/src/lqp.egg-info/SOURCES.txt @@ -0,0 +1,56 @@ +README.md +pyproject.toml +src/lqp/__init__.py +src/lqp/cli.py +src/lqp/emit.py +src/lqp/generated_parser.py +src/lqp/ir.py +src/lqp/parser.py +src/lqp/print.py +src/lqp/validator.py +src/lqp.egg-info/PKG-INFO +src/lqp.egg-info/SOURCES.txt +src/lqp.egg-info/dependency_links.txt +src/lqp.egg-info/entry_points.txt +src/lqp.egg-info/requires.txt +src/lqp.egg-info/top_level.txt +src/lqp/proto/v1/fragments_pb2.py +src/lqp/proto/v1/fragments_pb2.pyi +src/lqp/proto/v1/logic_pb2.py +src/lqp/proto/v1/logic_pb2.pyi +src/lqp/proto/v1/transactions_pb2.py +src/lqp/proto/v1/transactions_pb2.pyi +src/meta/__init__.py +src/meta/cli.py +src/meta/codegen_base.py +src/meta/codegen_julia.py +src/meta/codegen_python.py +src/meta/codegen_templates.py +src/meta/gensym.py +src/meta/grammar.py +src/meta/grammar.y +src/meta/grammar_analysis.py +src/meta/grammar_utils.py +src/meta/grammar_validator.py +src/meta/parser_gen.py +src/meta/parser_gen_common.py +src/meta/parser_gen_julia.py +src/meta/parser_gen_python.py +src/meta/proto_ast.py +src/meta/proto_parser.py +src/meta/proto_print.py +src/meta/target.py +src/meta/target_builtins.py +src/meta/target_print.py +src/meta/target_utils.py +src/meta/terminal_sequence_set.py +src/meta/type_env.py +src/meta/validation_result.py +src/meta/yacc_action_parser.py +src/meta/yacc_parser.py +tests/test_files.py +tests/test_generated_parser.py +tests/test_ir.py +tests/test_parser.py +tests/test_print.py +tests/test_unit.py \ No newline at end of file diff --git a/python-tools/src/lqp.egg-info/dependency_links.txt b/python-tools/src/lqp.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/python-tools/src/lqp.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/python-tools/src/lqp.egg-info/entry_points.txt b/python-tools/src/lqp.egg-info/entry_points.txt new file mode 100644 index 00000000..4d079120 --- /dev/null +++ b/python-tools/src/lqp.egg-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +lqp = lqp.cli:main +lqp-meta-tool = meta.cli:main diff --git a/python-tools/src/lqp.egg-info/requires.txt b/python-tools/src/lqp.egg-info/requires.txt new file mode 100644 index 00000000..f99e74fe --- /dev/null +++ b/python-tools/src/lqp.egg-info/requires.txt @@ -0,0 +1,9 @@ +lark>=1.1.9 +protobuf<5.0.0,>=3.20.3 +colorama +more-itertools + +[test] +pytest>=7.0.0 +pytest-snapshot +pyrefly==0.25.1 diff --git a/python-tools/src/lqp.egg-info/top_level.txt b/python-tools/src/lqp.egg-info/top_level.txt new file mode 100644 index 00000000..0f978277 --- /dev/null +++ b/python-tools/src/lqp.egg-info/top_level.txt @@ -0,0 +1,2 @@ +lqp +meta diff --git a/python-tools/src/lqp/emit.py b/python-tools/src/lqp/emit.py new file mode 100644 index 00000000..5b0949c5 --- /dev/null +++ b/python-tools/src/lqp/emit.py @@ -0,0 +1,576 @@ +import lqp.ir as ir +from lqp.proto.v1 import logic_pb2, fragments_pb2, transactions_pb2 +from typing import Union, Dict, Any +from functools import reduce + +# Maps ir.TypeNames to the associated Proto message for *non-paremetric types*. Used to generically construct non-parametric types. +# Parametric types should be handled in convert_type +non_parametric_types = { + ir.TypeName.UNSPECIFIED: "UnspecifiedType", + ir.TypeName.STRING: "StringType", + ir.TypeName.INT: "IntType", + ir.TypeName.FLOAT: "FloatType", + ir.TypeName.UINT128: "UInt128Type", + ir.TypeName.INT128: "Int128Type", + ir.TypeName.DATE: "DateType", + ir.TypeName.DATETIME: "DateTimeType", + ir.TypeName.MISSING: "MissingType", + ir.TypeName.BOOLEAN: "BooleanType", +} + +def convert_type(rt: ir.Type) -> logic_pb2.Type: + if rt.type_name == ir.TypeName.DECIMAL : + assert isinstance(rt.parameters[0].value, int) and isinstance(rt.parameters[1].value, int), "DECIMAL parameters are not integers" + assert len(rt.parameters) == 2, f"DECIMAL parameters should have only precision and scale, got {len(rt.parameters)} arguments" + assert rt.parameters[0].value <= 38, f"DECIMAL precision must be less than 38, got {rt.parameters[0]}" + assert rt.parameters[1].value <= rt.parameters[0].value, f"DECIMAL precision ({rt.parameters[0]}) must be at least scale ({rt.parameters[1]})" + return logic_pb2.Type( + decimal_type=logic_pb2.DecimalType( + precision=rt.parameters[0].value, scale=rt.parameters[1].value + ) + ) + else: + cls = getattr(logic_pb2, non_parametric_types[rt.type_name]) + return logic_pb2.Type(**{str(rt.type_name).lower()+"_type": cls()}) + +def convert_uint128(val: ir.UInt128Value) -> logic_pb2.UInt128Value: + low = val.value & 0xFFFFFFFFFFFFFFFF + high = (val.value >> 64) & 0xFFFFFFFFFFFFFFFF + return logic_pb2.UInt128Value(low=low, high=high) + +def convert_int128(val: ir.Int128Value) -> logic_pb2.Int128Value: + low = val.value & 0xFFFFFFFFFFFFFFFF + high = (val.value >> 64) & 0xFFFFFFFFFFFFFFFF + return logic_pb2.Int128Value(low=low, high=high) + +def convert_date(val: ir.DateValue) -> logic_pb2.DateValue: + return logic_pb2.DateValue(year=val.value.year, month=val.value.month, day=val.value.day) + +def convert_datetime(val: ir.DateTimeValue) -> logic_pb2.DateTimeValue: + return logic_pb2.DateTimeValue( + year=val.value.year, + month=val.value.month, + day=val.value.day, + hour=val.value.hour, + minute=val.value.minute, + second=val.value.second, + microsecond=val.value.microsecond + ) + +def convert_decimal(val: ir.DecimalValue) -> logic_pb2.DecimalValue: + sign, digits, exponent = val.value.as_tuple() + value = reduce(lambda rst, d: rst * 10 + d, digits) + + assert isinstance(exponent, int) + assert isinstance(value, int) + + # Adjust value by the exponent. Python's decimal values are (sign, digits, exponent), + # so if we have digits 12300 with exponent -4, but we need `scale` of 6, then we need to + # multiply the digits by 10 ** 2 (i.e., 10 ** (6 + -4)) to get the physical value of + # 1230000. + # Ensure we stay in the integer realm when the exponent outweighs the scale, e.g. + # value = 4.4000000000000003552713678800500929355621337890625 + modifier = val.scale + exponent + if modifier >= 0: + value *= 10 ** modifier + else: + value //= 10 ** (-modifier) + + if sign == 1: + value = -value + + value = ir.Int128Value(value=value, meta=val.meta) + + return logic_pb2.DecimalValue( + precision=val.precision, + scale=val.scale, + value=convert_int128(value), + ) + +def convert_value(pv: ir.Value) -> logic_pb2.Value: + if isinstance(pv.value, str): + return logic_pb2.Value(string_value=pv.value) + elif isinstance(pv.value, ir.MissingValue): + return logic_pb2.Value(missing_value=logic_pb2.MissingValue()) + elif isinstance(pv.value, int): + assert pv.value.bit_length() <= 64, "Integer value exceeds 64 bits" + return logic_pb2.Value(int_value=pv.value) + elif isinstance(pv.value, float): + return logic_pb2.Value(float_value=pv.value) + elif isinstance(pv.value, ir.UInt128Value): + return logic_pb2.Value( + uint128_value=convert_uint128(pv.value) + ) + elif isinstance(pv.value, ir.Int128Value): + return logic_pb2.Value( + int128_value=convert_int128(pv.value) + ) + elif isinstance(pv.value, ir.DateValue): + return logic_pb2.Value( + date_value=convert_date(pv.value) + ) + elif isinstance(pv.value, ir.DateTimeValue): + return logic_pb2.Value( + datetime_value=convert_datetime(pv.value) + ) + elif isinstance(pv.value, ir.DecimalValue): + return logic_pb2.Value( + decimal_value=convert_decimal(pv.value) + ) + elif isinstance(pv.value, ir.BooleanValue): + return logic_pb2.Value(boolean_value=pv.value.value) + else: + raise TypeError(f"Unsupported Value type: {type(pv.value)}") + +def convert_var(v: ir.Var) -> logic_pb2.Var: + return logic_pb2.Var(name=v.name) + +def convert_term(t: ir.Term) -> logic_pb2.Term: + if isinstance(t, ir.Var): + return logic_pb2.Term(var=convert_var(t)) + else: + return logic_pb2.Term(constant=convert_value(t)) + +def convert_relterm(t: ir.RelTerm) -> logic_pb2.RelTerm: + if isinstance(t, ir.SpecializedValue): + return logic_pb2.RelTerm(specialized_value=convert_value(t.value)) + else: + return logic_pb2.RelTerm(term=convert_term(t)) + +def convert_relation_id(rid: ir.RelationId) -> logic_pb2.RelationId: + val = rid.id + id_low = val & 0xFFFFFFFFFFFFFFFF + id_high = (val >> 64) & 0xFFFFFFFFFFFFFFFF + return logic_pb2.RelationId(id_low=id_low, id_high=id_high) + +def convert_fragment_id(fid: ir.FragmentId) -> fragments_pb2.FragmentId: + return fragments_pb2.FragmentId(id=fid.id) + +def convert_attribute(attr: ir.Attribute) -> logic_pb2.Attribute: + return logic_pb2.Attribute( + name=attr.name, + args=[convert_value(arg) for arg in attr.args] +) + +def convert_abstraction(abst: ir.Abstraction) -> logic_pb2.Abstraction: + bindings = [logic_pb2.Binding(var=convert_var(var_tuple[0]), type=convert_type(var_tuple[1])) + for var_tuple in abst.vars] + return logic_pb2.Abstraction( + vars=bindings, + value=convert_formula(abst.value) + ) + +def convert_formula(f: ir.Formula) -> logic_pb2.Formula: + if isinstance(f, ir.Exists): + return logic_pb2.Formula(exists=logic_pb2.Exists(body=convert_abstraction(f.body))) + elif isinstance(f, ir.Reduce): + return logic_pb2.Formula(reduce=logic_pb2.Reduce( + op=convert_abstraction(f.op), + body=convert_abstraction(f.body), + terms=[convert_term(t) for t in f.terms] + )) + elif isinstance(f, ir.Conjunction): + return logic_pb2.Formula(conjunction=logic_pb2.Conjunction(args=[convert_formula(arg) for arg in f.args])) + elif isinstance(f, ir.Disjunction): + return logic_pb2.Formula(disjunction=logic_pb2.Disjunction(args=[convert_formula(arg) for arg in f.args])) + elif isinstance(f, ir.Not): + return logic_pb2.Formula(**{"not": logic_pb2.Not(arg=convert_formula(f.arg))}) # type: ignore + elif isinstance(f, ir.FFI): + return logic_pb2.Formula(ffi=logic_pb2.FFI( + name=f.name, + args=[convert_abstraction(arg) for arg in f.args], + terms=[convert_term(t) for t in f.terms] + )) + elif isinstance(f, ir.Atom): + return logic_pb2.Formula(atom=logic_pb2.Atom( + name=convert_relation_id(f.name), + terms=[convert_term(t) for t in f.terms] + )) + elif isinstance(f, ir.Pragma): + return logic_pb2.Formula(pragma=logic_pb2.Pragma( + name=f.name, + terms=[convert_term(t) for t in f.terms] + )) + elif isinstance(f, ir.Primitive): + primitive_proto = logic_pb2.Primitive(name=f.name, terms=[convert_relterm(t) for t in f.terms]) + return logic_pb2.Formula(primitive=primitive_proto) + elif isinstance(f, ir.RelAtom): + rel_atom_proto = logic_pb2.RelAtom(name=f.name, terms=[convert_relterm(t) for t in f.terms]) + return logic_pb2.Formula(rel_atom=rel_atom_proto) + elif isinstance(f, ir.Cast): + return logic_pb2.Formula(cast=logic_pb2.Cast( + input=convert_term(f.input), + result=convert_term(f.result) + )) + else: + raise TypeError(f"Unsupported Formula type: {type(f)}") + +def convert_betree_config(config: ir.BeTreeConfig) -> logic_pb2.BeTreeConfig: + return logic_pb2.BeTreeConfig( + epsilon=config.epsilon, + max_pivots=config.max_pivots, + max_deltas=config.max_deltas, + max_leaf=config.max_leaf + ) + +def convert_betree_locator(locator: ir.BeTreeLocator) -> logic_pb2.BeTreeLocator: + # Handle oneof: only set the location field that is not None + kwargs: Dict[str, Any] = { + 'element_count': locator.element_count, + 'tree_height': locator.tree_height + } + if locator.root_pageid is not None: + kwargs['root_pageid'] = convert_uint128(locator.root_pageid) + if locator.inline_data is not None: + kwargs['inline_data'] = locator.inline_data + return logic_pb2.BeTreeLocator(**kwargs) + +def convert_betree_info(info: ir.BeTreeInfo) -> logic_pb2.BeTreeInfo: + return logic_pb2.BeTreeInfo( + key_types=[convert_type(kt) for kt in info.key_types], + value_types=[convert_type(vt) for vt in info.value_types], + storage_config=convert_betree_config(info.storage_config), + relation_locator=convert_betree_locator(info.relation_locator) + ) + +def convert_rel_edb(rel: ir.RelEDB) -> logic_pb2.RelEDB: + return logic_pb2.RelEDB( + target_id=convert_relation_id(rel.target_id), + path=rel.path, + types=[convert_type(t) for t in rel.types] + ) + +def convert_betree_relation(rel: ir.BeTreeRelation) -> logic_pb2.BeTreeRelation: + return logic_pb2.BeTreeRelation( + name=convert_relation_id(rel.name), + relation_info=convert_betree_info(rel.relation_info) + ) + +def convert_csv_locator(locator: ir.CSVLocator) -> logic_pb2.CSVLocator: + kwargs: Dict[str, Any] = {} + if locator.paths: + kwargs['paths'] = locator.paths + if locator.inline_data is not None: + kwargs['inline_data'] = locator.inline_data + return logic_pb2.CSVLocator(**kwargs) + +def convert_csv_config(config: ir.CSVConfig) -> logic_pb2.CSVConfig: + return logic_pb2.CSVConfig( + header_row=config.header_row, + skip=config.skip, + new_line=config.new_line, + delimiter=config.delimiter, + quotechar=config.quotechar, + escapechar=config.escapechar, + comment=config.comment, + missing_strings=list(config.missing_strings), + decimal_separator=config.decimal_separator, + encoding=config.encoding, + compression=config.compression + ) + +def convert_csv_column(column: ir.CSVColumn) -> logic_pb2.CSVColumn: + return logic_pb2.CSVColumn( + column_name=column.column_name, + target_id=convert_relation_id(column.target_id), + types=[convert_type(t) for t in column.types] + ) + +def convert_csv_relation(rel: ir.CSVData) -> logic_pb2.CSVData: + return logic_pb2.CSVData( + locator=convert_csv_locator(rel.locator), + config=convert_csv_config(rel.config), + columns=[convert_csv_column(col) for col in rel.columns], + asof=rel.asof + ) + +def convert_data(data: ir.Data) -> logic_pb2.Data: + if isinstance(data, ir.RelEDB): + return logic_pb2.Data(rel_edb=convert_rel_edb(data)) + elif isinstance(data, ir.BeTreeRelation): + return logic_pb2.Data(betree_relation=convert_betree_relation(data)) + elif isinstance(data, ir.CSVData): + return logic_pb2.Data(csv_data=convert_csv_relation(data)) + else: + raise TypeError(f"Unsupported Data type: {type(data)}") + +def convert_def(d: ir.Def) -> logic_pb2.Def: + return logic_pb2.Def( + name=convert_relation_id(d.name), + body=convert_abstraction(d.body), + attrs=[convert_attribute(attr) for attr in d.attrs] + ) + +def convert_loop(l: ir.Loop) -> logic_pb2.Loop: + return logic_pb2.Loop( + init=[convert_instruction(init_def) for init_def in l.init], + body=convert_script(l.body) + ) + +def convert_declaration(decl: ir.Declaration) -> logic_pb2.Declaration: + from typing import Dict, Any + if isinstance(decl, ir.Def): + decl_dict: Dict[str, Any] = {'def': convert_def(decl)} + return logic_pb2.Declaration(**decl_dict) # type: ignore + elif isinstance(decl, ir.Algorithm): + algorithm_dict: Dict[str, Any] = {'algorithm': convert_algorithm(decl)} + return logic_pb2.Declaration(**algorithm_dict) + elif isinstance(decl, ir.Constraint): + constraint_dict: Dict[str, Any] = {'constraint': convert_constraint(decl)} + return logic_pb2.Declaration(**constraint_dict) + elif isinstance(decl, ir.Data): + data_dict: Dict[str, Any] = {'data': convert_data(decl)} + return logic_pb2.Declaration(**data_dict) # type: ignore + else: + raise TypeError(f"Unsupported Declaration type: {type(decl)}") + +def convert_constraint(constraint: ir.Constraint) -> logic_pb2.Constraint: + if isinstance(constraint, ir.FunctionalDependency): + fd_dict: Dict[str, Any] = { + 'guard': convert_abstraction(constraint.guard), + 'keys': [convert_var(v) for v in constraint.keys], + 'values': [convert_var(v) for v in constraint.values], + } + return logic_pb2.Constraint( + name=convert_relation_id(constraint.name), + functional_dependency=logic_pb2.FunctionalDependency(**fd_dict) + ) + else: + raise TypeError(f"Unsupported Constraint type: {type(constraint)}") + +def convert_algorithm(algo: ir.Algorithm)-> logic_pb2.Algorithm: + dict: Dict[str, Any] = { + 'global': [convert_relation_id(id) for id in algo.global_], + 'body':convert_script(algo.body) + } + return logic_pb2.Algorithm(**dict) + +def convert_instruction(instr: ir.Instruction) -> logic_pb2.Instruction: + from typing import Dict, Any + if isinstance(instr, ir.Assign): + dict: Dict[str, Any] = {'assign': convert_assign(instr)} + return logic_pb2.Instruction(**dict) + elif isinstance(instr, ir.Break): + dict: Dict[str, Any] = {'break': convert_break(instr)} + return logic_pb2.Instruction(**dict) + elif isinstance(instr, ir.Upsert): + dict: Dict[str, Any] = {'upsert': convert_upsert(instr)} + return logic_pb2.Instruction(**dict) + elif isinstance(instr, ir.MonoidDef): + dict: Dict[str, Any] = {'monoid_def': convert_monoid_def(instr)} + return logic_pb2.Instruction(**dict) + elif isinstance(instr, ir.MonusDef): + dict: Dict[str, Any] = {'monus_def': convert_monus_def(instr)} + return logic_pb2.Instruction(**dict) + else: + raise TypeError(f"Unsupported Instruction type: {type(instr)}") + +def convert_assign(instr: ir.Assign) -> logic_pb2.Assign: + return logic_pb2.Assign( + name=convert_relation_id(instr.name), + body=convert_abstraction(instr.body), + attrs=[convert_attribute(attr) for attr in instr.attrs] + ) +def convert_break(instr: ir.Break) -> logic_pb2.Break: + return logic_pb2.Break( + name=convert_relation_id(instr.name), + body=convert_abstraction(instr.body), + attrs=[convert_attribute(attr) for attr in instr.attrs] + ) +def convert_upsert(instr: ir.Upsert) -> logic_pb2.Upsert: + return logic_pb2.Upsert( + value_arity=instr.value_arity, + name=convert_relation_id(instr.name), + body=convert_abstraction(instr.body), + attrs=[convert_attribute(attr) for attr in instr.attrs] + ) +def convert_monoid_def(instr: ir.MonoidDef) -> logic_pb2.MonoidDef: + return logic_pb2.MonoidDef( + value_arity=instr.value_arity, + monoid=convert_monoid(instr.monoid), + name=convert_relation_id(instr.name), + body=convert_abstraction(instr.body), + attrs=[convert_attribute(attr) for attr in instr.attrs] + ) +def convert_monus_def(instr: ir.MonusDef) -> logic_pb2.MonusDef: + return logic_pb2.MonusDef( + value_arity=instr.value_arity, + monoid=convert_monoid(instr.monoid), + name=convert_relation_id(instr.name), + body=convert_abstraction(instr.body), + attrs=[convert_attribute(attr) for attr in instr.attrs] + ) +def convert_monoid(monoid: ir.Monoid) -> logic_pb2.Monoid: + from typing import Dict, Any + if isinstance(monoid, ir.OrMonoid): + return logic_pb2.Monoid(**{'or_monoid': logic_pb2.OrMonoid()}) # type: ignore + elif isinstance(monoid, ir.SumMonoid): + type = convert_type(monoid.type) + return logic_pb2.Monoid(**{'sum_monoid': logic_pb2.SumMonoid(type=type)}) # type: ignore + elif isinstance(monoid, ir.MinMonoid): + type = convert_type(monoid.type) + return logic_pb2.Monoid(**{'min_monoid': logic_pb2.MinMonoid(type=type)}) # type: ignore + elif isinstance(monoid, ir.MaxMonoid): + type = convert_type(monoid.type) + return logic_pb2.Monoid(**{'max_monoid': logic_pb2.MaxMonoid(type=type)}) # type: ignore + else: + raise TypeError(f"Unsupported Monoid: {monoid}") + + +def convert_script(script: ir.Script) -> logic_pb2.Script: + return logic_pb2.Script(constructs=[convert_construct(c) for c in script.constructs]) + +def convert_construct(construct: ir.Construct) -> logic_pb2.Construct: + from typing import Dict, Any + if isinstance(construct, ir.Loop): + loop_dict: Dict[str, Any] = {'loop': convert_loop(construct)} + return logic_pb2.Construct(**loop_dict) # type: ignore + elif isinstance(construct, ir.Instruction): + instruction_dict: Dict[str, Any] = {'instruction': convert_instruction(construct)} + return logic_pb2.Construct(**instruction_dict) + else: + raise TypeError(f"Unsupported Construct type: {type(construct)}") + +def convert_fragment(frag: ir.Fragment) -> fragments_pb2.Fragment: + return fragments_pb2.Fragment( + id=convert_fragment_id(frag.id), + declarations=[convert_declaration(decl) for decl in frag.declarations], + debug_info=convert_debug_info(frag.debug_info) + ) + +def convert_debug_info(info: ir.DebugInfo) -> fragments_pb2.DebugInfo: + return fragments_pb2.DebugInfo( + ids=[convert_relation_id(key) for key in info.id_to_orig_name.keys()], + orig_names=info.id_to_orig_name.values() + ) + +def convert_define(d: ir.Define) -> transactions_pb2.Define: + return transactions_pb2.Define(fragment=convert_fragment(d.fragment)) + +def convert_undefine(u: ir.Undefine) -> transactions_pb2.Undefine: + return transactions_pb2.Undefine(fragment_id=convert_fragment_id(u.fragment_id)) + +def convert_context(c: ir.Context) -> transactions_pb2.Context: + return transactions_pb2.Context(relations=[convert_relation_id(rid) for rid in c.relations]) + +def convert_write(w: ir.Write) -> transactions_pb2.Write: + wt = w.write_type + if isinstance(wt, ir.Define): + return transactions_pb2.Write(define=convert_define(wt)) + elif isinstance(wt, ir.Undefine): + return transactions_pb2.Write(undefine=convert_undefine(wt)) + elif isinstance(wt, ir.Context): + return transactions_pb2.Write(context=convert_context(wt)) + else: + raise TypeError(f"Unsupported Write type: {type(wt)}") + +def convert_demand(d: ir.Demand) -> transactions_pb2.Demand: + return transactions_pb2.Demand(relation_id=convert_relation_id(d.relation_id)) + +def convert_output(o: ir.Output) -> transactions_pb2.Output: + kwargs: Dict[str, Any] = {'relation_id': convert_relation_id(o.relation_id)} + if o.name is not None: + kwargs['name'] = o.name + return transactions_pb2.Output(**kwargs) # type: ignore + +def convert_export(e: ir.Export) -> transactions_pb2.Export: + return transactions_pb2.Export(csv_config=convert_export_config(e.config)) # type: ignore + +def convert_export_config(ec: ir.ExportCSVConfig) -> transactions_pb2.ExportCSVConfig: + return transactions_pb2.ExportCSVConfig( + data_columns=[convert_export_csv_column(c) for c in ec.data_columns], + path=ec.path, + partition_size=ec.partition_size if ec.partition_size is not None else 0, + compression=ec.compression if ec.compression is not None else "", + syntax_header_row=ec.syntax_header_row if ec.syntax_header_row is not None else True, # type: ignore + syntax_missing_string=ec.syntax_missing_string if ec.syntax_missing_string is not None else "", + syntax_delim=ec.syntax_delim if ec.syntax_delim is not None else ",", + syntax_quotechar=ec.syntax_quotechar if ec.syntax_quotechar is not None else '"', + syntax_escapechar=ec.syntax_escapechar if ec.syntax_escapechar is not None else '\\' + ) + +def convert_export_csv_column(ec: ir.ExportCSVColumn) -> transactions_pb2.ExportCSVColumn: + return transactions_pb2.ExportCSVColumn( + column_name=ec.column_name, + column_data=convert_relation_id(ec.column_data), + ) + +def convert_abort(a: ir.Abort) -> transactions_pb2.Abort: + kwargs: Dict[str, Any] = {'relation_id': convert_relation_id(a.relation_id)} + if a.name is not None: + kwargs['name'] = a.name + return transactions_pb2.Abort(**kwargs) # type: ignore + +def convert_whatif(wi: ir.WhatIf) -> transactions_pb2.WhatIf: + kwargs: Dict[str, Any] = {'epoch': convert_epoch(wi.epoch)} + if wi.branch is not None: + kwargs['branch'] = wi.branch + return transactions_pb2.WhatIf(**kwargs) # type: ignore + +def convert_read(r: ir.Read) -> transactions_pb2.Read: + rt = r.read_type + if isinstance(rt, ir.Demand): + return transactions_pb2.Read(demand=convert_demand(rt)) + elif isinstance(rt, ir.Output): + return transactions_pb2.Read(output=convert_output(rt)) + elif isinstance(rt, ir.WhatIf): + return transactions_pb2.Read(what_if=convert_whatif(rt)) # Note the underscore + elif isinstance(rt, ir.Abort): + return transactions_pb2.Read(abort=convert_abort(rt)) + elif isinstance(rt, ir.Export): + return transactions_pb2.Read(export=convert_export(rt)) + else: + raise TypeError(f"Unsupported Read type: {type(rt)}") + +def convert_epoch(e: ir.Epoch) -> transactions_pb2.Epoch: + return transactions_pb2.Epoch( + writes=[convert_write(w) for w in e.writes], + reads=[convert_read(r) for r in e.reads] + ) + +def convert_configure(c: ir.Configure) -> transactions_pb2.Configure: + return transactions_pb2.Configure( + semantics_version=c.semantics_version, + ivm_config=convert_ivm_config(c.ivm_config), + optimization_level=convert_optimization_level(c.optimization_level) + ) + +def convert_ivm_config(c: ir.IVMConfig) -> transactions_pb2.IVMConfig: + return transactions_pb2.IVMConfig( + level=convert_maintenance_level(c.level) + ) + +def convert_maintenance_level(l: ir.MaintenanceLevel) -> transactions_pb2.MaintenanceLevel: + return transactions_pb2.MaintenanceLevel.Name(l.value) # type: ignore[missing-attribute] + +def convert_optimization_level(o: ir.OptimizationLevel) -> transactions_pb2.OptimizationLevel: + return transactions_pb2.OptimizationLevel.Name(o.value) # type: ignore[missing-attribute] + +def convert_sync(c: ir.Sync) -> transactions_pb2.Sync: + return transactions_pb2.Sync(fragments=[convert_fragment_id(rid) for rid in c.fragments]) + +def convert_transaction(t: ir.Transaction) -> transactions_pb2.Transaction: + kwargs: Dict[str, Any] = { + 'configure': convert_configure(t.configure), + 'epochs': [convert_epoch(e) for e in t.epochs] + } + if t.sync is not None: + kwargs['sync'] = convert_sync(t.sync) + return transactions_pb2.Transaction(**kwargs) + +def ir_to_proto(node: ir.LqpNode) -> Union[ + transactions_pb2.Transaction, + fragments_pb2.Fragment, + logic_pb2.Declaration, + logic_pb2.Formula +]: + if isinstance(node, ir.Transaction): + return convert_transaction(node) + elif isinstance(node, ir.Fragment): + return convert_fragment(node) + elif isinstance(node, ir.Declaration): + return convert_declaration(node) + elif isinstance(node, ir.Formula): + return convert_formula(node) + else: + raise TypeError(f"Unsupported top-level IR node type for conversion: {type(node)}") diff --git a/python-tools/src/lqp/generated_parser.py b/python-tools/src/lqp/generated_parser.py new file mode 100644 index 00000000..6b89b9c3 --- /dev/null +++ b/python-tools/src/lqp/generated_parser.py @@ -0,0 +1,3014 @@ +""" +Auto-generated LL(k) recursive-descent parser. + +Generated from protobuf specifications. +Do not modify this file! If you need to modify the parser, edit the generator code +in `python-tools/src/meta` or edit the protobuf specification in `proto/v1`. + + +Command: python -m meta.cli ../proto/relationalai/lqp/v1/fragments.proto ../proto/relationalai/lqp/v1/logic.proto ../proto/relationalai/lqp/v1/transactions.proto --grammar src/meta/grammar.y --parser python +""" + +import ast +import hashlib +import re +from typing import List, Optional, Any, Tuple, Callable +from decimal import Decimal + +from lqp.proto.v1 import logic_pb2, fragments_pb2, transactions_pb2 + + +class ParseError(Exception): + """Parse error exception.""" + pass + + +class Token: + """Token representation.""" + def __init__(self, type: str, value: str, pos: int): + self.type = type + self.value = value + self.pos = pos + + def __repr__(self) -> str: + return f"Token({self.type}, {self.value!r}, {self.pos})" + + +class Lexer: + """Tokenizer for the input.""" + def __init__(self, input_str: str): + self.input = input_str + self.pos = 0 + self.tokens: List[Token] = [] + self._tokenize() + + def _tokenize(self) -> None: + """Tokenize the input string.""" + token_specs = [ + ('LITERAL', re.compile(r'::'), lambda x: x), + ('LITERAL', re.compile(r'<='), lambda x: x), + ('LITERAL', re.compile(r'>='), lambda x: x), + ('LITERAL', re.compile(r'\#'), lambda x: x), + ('LITERAL', re.compile(r'\('), lambda x: x), + ('LITERAL', re.compile(r'\)'), lambda x: x), + ('LITERAL', re.compile(r'\*'), lambda x: x), + ('LITERAL', re.compile(r'\+'), lambda x: x), + ('LITERAL', re.compile(r'\-'), lambda x: x), + ('LITERAL', re.compile(r'/'), lambda x: x), + ('LITERAL', re.compile(r':'), lambda x: x), + ('LITERAL', re.compile(r'<'), lambda x: x), + ('LITERAL', re.compile(r'='), lambda x: x), + ('LITERAL', re.compile(r'>'), lambda x: x), + ('LITERAL', re.compile(r'\['), lambda x: x), + ('LITERAL', re.compile(r'\]'), lambda x: x), + ('LITERAL', re.compile(r'\{'), lambda x: x), + ('LITERAL', re.compile(r'\|'), lambda x: x), + ('LITERAL', re.compile(r'\}'), lambda x: x), + ('DECIMAL', re.compile(r'[-]?\d+\.\d+d\d+'), lambda x: Lexer.scan_decimal(x)), + ('FLOAT', re.compile(r'[-]?\d+\.\d+|inf|nan'), lambda x: Lexer.scan_float(x)), + ('INT', re.compile(r'[-]?\d+'), lambda x: Lexer.scan_int(x)), + ('INT128', re.compile(r'[-]?\d+i128'), lambda x: Lexer.scan_int128(x)), + ('STRING', re.compile(r'"(?:[^"\\]|\\.)*"'), lambda x: Lexer.scan_string(x)), + ('SYMBOL', re.compile(r'[a-zA-Z_][a-zA-Z0-9_.-]*'), lambda x: Lexer.scan_symbol(x)), + ('UINT128', re.compile(r'0x[0-9a-fA-F]+'), lambda x: Lexer.scan_uint128(x)), + ] + + whitespace_re = re.compile(r'\s+') + comment_re = re.compile(r';;.*') + + while self.pos < len(self.input): + match = whitespace_re.match(self.input, self.pos) + if match: + self.pos = match.end() + continue + + match = comment_re.match(self.input, self.pos) + if match: + self.pos = match.end() + continue + + # Collect all matching tokens + candidates = [] + + for token_type, regex, action in token_specs: + match = regex.match(self.input, self.pos) + if match: + value = match.group(0) + candidates.append((token_type, value, action, match.end())) + + if not candidates: + raise ParseError(f'Unexpected character at position {self.pos}: {self.input[self.pos]!r}') + + # Pick the longest match + token_type, value, action, end_pos = max(candidates, key=lambda x: x[3]) + self.tokens.append(Token(token_type, action(value), self.pos)) + self.pos = end_pos + + self.tokens.append(Token('$', '', self.pos)) + + @staticmethod + def scan_symbol(s: str) -> str: + """Parse SYMBOL token.""" + return s + + @staticmethod + def scan_colon_symbol(s: str) -> str: + """Parse COLON_SYMBOL token.""" + return s[1:] + + @staticmethod + def scan_string(s: str) -> str: + """Parse STRING token.""" + return ast.literal_eval(s) + + @staticmethod + def scan_int(n: str) -> int: + """Parse INT token.""" + val = int(n) + if val < -(1 << 63) or val >= (1 << 63): + raise ParseError(f'Integer literal out of 64-bit range: {n}') + return val + + @staticmethod + def scan_float(f: str) -> float: + """Parse FLOAT token.""" + if f == 'inf': + return float('inf') + elif f == 'nan': + return float('nan') + return float(f) + + @staticmethod + def scan_uint128(u: str) -> Any: + """Parse UINT128 token.""" + uint128_val = int(u, 16) + if uint128_val < 0 or uint128_val >= (1 << 128): + raise ParseError(f'UInt128 literal out of range: {u}') + low = uint128_val & 0xFFFFFFFFFFFFFFFF + high = (uint128_val >> 64) & 0xFFFFFFFFFFFFFFFF + return logic_pb2.UInt128Value(low=low, high=high) + + @staticmethod + def scan_int128(u: str) -> Any: + """Parse INT128 token.""" + u = u[:-4] # Remove the 'i128' suffix + int128_val = int(u) + if int128_val < -(1 << 127) or int128_val >= (1 << 127): + raise ParseError(f'Int128 literal out of range: {u}') + low = int128_val & 0xFFFFFFFFFFFFFFFF + high = (int128_val >> 64) & 0xFFFFFFFFFFFFFFFF + return logic_pb2.Int128Value(low=low, high=high) + + @staticmethod + def scan_decimal(d: str) -> Any: + """Parse DECIMAL token.""" + # Decimal is a string like '123.456d12' where the last part after `d` is the + # precision, and the scale is the number of digits between the decimal point and `d` + parts = d.split('d') + if len(parts) != 2: + raise ValueError(f'Invalid decimal format: {d}') + scale = len(parts[0].split('.')[1]) + precision = int(parts[1]) + # Parse the integer value directly without calling scan_int128 which strips 'i128' suffix + int_str = parts[0].replace('.', '') + int128_val = int(int_str) + low = int128_val & 0xFFFFFFFFFFFFFFFF + high = (int128_val >> 64) & 0xFFFFFFFFFFFFFFFF + value = logic_pb2.Int128Value(low=low, high=high) + return logic_pb2.DecimalValue(precision=precision, scale=scale, value=value) + + +class Parser: + """LL(k) recursive-descent parser with backtracking.""" + def __init__(self, tokens: List[Token]): + self.tokens = tokens + self.pos = 0 + self.id_to_debuginfo = {} + self._current_fragment_id: bytes | None = None + self._relation_id_to_name = {} + + def lookahead(self, k: int = 0) -> Token: + """Get lookahead token at offset k.""" + idx = self.pos + k + return self.tokens[idx] if idx < len(self.tokens) else Token('$', '', -1) + + def consume_literal(self, expected: str) -> None: + """Consume a literal token.""" + if not self.match_lookahead_literal(expected, 0): + token = self.lookahead(0) + raise ParseError(f'Expected literal {expected!r} but got {token.type}=`{token.value!r}` at position {token.pos}') + self.pos += 1 + + def consume_terminal(self, expected: str) -> Any: + """Consume a terminal token and return parsed value.""" + if not self.match_lookahead_terminal(expected, 0): + token = self.lookahead(0) + raise ParseError(f'Expected terminal {expected} but got {token.type}=`{token.value!r}` at position {token.pos}') + token = self.lookahead(0) + self.pos += 1 + return token.value + + def match_lookahead_literal(self, literal: str, k: int) -> bool: + """Check if lookahead token at position k matches literal. + + Supports soft keywords: alphanumeric literals are lexed as SYMBOL tokens, + so we check both LITERAL and SYMBOL token types. + """ + token = self.lookahead(k) + if token.type == 'LITERAL' and token.value == literal: + return True + if token.type == 'SYMBOL' and token.value == literal: + return True + return False + + def match_lookahead_terminal(self, terminal: str, k: int) -> bool: + """Check if lookahead token at position k matches terminal.""" + token = self.lookahead(k) + return token.type == terminal + + def start_fragment(self, fragment_id: fragments_pb2.FragmentId) -> fragments_pb2.FragmentId: + """Set current fragment ID for debug info tracking.""" + self._current_fragment_id = fragment_id.id + return fragment_id + + def relation_id_from_string(self, name: str) -> Any: + """Create RelationId from string and track mapping for debug info.""" + val = int(hashlib.sha256(name.encode()).hexdigest()[:16], 16) + id_low = val & 0xFFFFFFFFFFFFFFFF + id_high = (val >> 64) & 0xFFFFFFFFFFFFFFFF + relation_id = logic_pb2.RelationId(id_low=id_low, id_high=id_high) + + # Store the mapping for the current fragment if we're inside one + if self._current_fragment_id is not None: + if self._current_fragment_id not in self.id_to_debuginfo: + self.id_to_debuginfo[self._current_fragment_id] = {} + self.id_to_debuginfo[self._current_fragment_id][(relation_id.id_low, relation_id.id_high)] = name + + return relation_id + + def construct_fragment(self, fragment_id: fragments_pb2.FragmentId, declarations: List[logic_pb2.Declaration]) -> fragments_pb2.Fragment: + """Construct Fragment from fragment_id, declarations, and debug info from parser state.""" + # Get the debug info for this fragment + debug_info_dict = self.id_to_debuginfo.get(fragment_id.id, {}) + + # Convert to DebugInfo protobuf + ids = [] + orig_names = [] + for (id_low, id_high), name in debug_info_dict.items(): + ids.append(logic_pb2.RelationId(id_low=id_low, id_high=id_high)) + orig_names.append(name) + + # Create DebugInfo + debug_info = fragments_pb2.DebugInfo(ids=ids, orig_names=orig_names) + + # Clear _current_fragment_id before the return + self._current_fragment_id = None + + # Create and return Fragment + return fragments_pb2.Fragment(id=fragment_id, declarations=declarations, debug_info=debug_info) + + # --- Helper functions --- + + @staticmethod + def _extract_value_int64(value: Optional[logic_pb2.Value], default: int) -> int: + if (value is not None and value.HasField('int_value')): + return value.int_value + return default + + @staticmethod + def _extract_value_float64(value: Optional[logic_pb2.Value], default: float) -> float: + if (value is not None and value.HasField('float_value')): + return value.float_value + return default + + @staticmethod + def _extract_value_string(value: Optional[logic_pb2.Value], default: str) -> str: + if (value is not None and value.HasField('string_value')): + return value.string_value + return default + + @staticmethod + def _extract_value_boolean(value: Optional[logic_pb2.Value], default: bool) -> bool: + if (value is not None and value.HasField('boolean_value')): + return value.boolean_value + return default + + @staticmethod + def _extract_value_bytes(value: Optional[logic_pb2.Value], default: bytes) -> bytes: + if (value is not None and value.HasField('string_value')): + return value.string_value.encode() + return default + + @staticmethod + def _extract_value_uint128(value: Optional[logic_pb2.Value], default: logic_pb2.UInt128Value) -> logic_pb2.UInt128Value: + if (value is not None and value.HasField('uint128_value')): + return value.uint128_value + return default + + @staticmethod + def _extract_value_string_list(value: Optional[logic_pb2.Value], default: list[str]) -> list[str]: + if (value is not None and value.HasField('string_value')): + return [value.string_value] + return default + + @staticmethod + def _try_extract_value_int64(value: Optional[logic_pb2.Value]) -> Optional[int]: + if (value is not None and value.HasField('int_value')): + return value.int_value + return None + + @staticmethod + def _try_extract_value_float64(value: Optional[logic_pb2.Value]) -> Optional[float]: + if (value is not None and value.HasField('float_value')): + return value.float_value + return None + + @staticmethod + def _try_extract_value_string(value: Optional[logic_pb2.Value]) -> Optional[str]: + if (value is not None and value.HasField('string_value')): + return value.string_value + return None + + @staticmethod + def _try_extract_value_bytes(value: Optional[logic_pb2.Value]) -> Optional[bytes]: + if (value is not None and value.HasField('string_value')): + return value.string_value.encode() + return None + + @staticmethod + def _try_extract_value_uint128(value: Optional[logic_pb2.Value]) -> Optional[logic_pb2.UInt128Value]: + if (value is not None and value.HasField('uint128_value')): + return value.uint128_value + return None + + @staticmethod + def _try_extract_value_string_list(value: Optional[logic_pb2.Value]) -> Optional[list[str]]: + if (value is not None and value.HasField('string_value')): + return [value.string_value] + return None + + @staticmethod + def construct_csv_config(config_dict: list[tuple[str, logic_pb2.Value]]) -> logic_pb2.CSVConfig: + config = dict(config_dict) + _t946 = Parser._extract_value_int64(config.get('csv_header_row'), 1) + header_row = _t946 + _t947 = Parser._extract_value_int64(config.get('csv_skip'), 0) + skip = _t947 + _t948 = Parser._extract_value_string(config.get('csv_new_line'), '') + new_line = _t948 + _t949 = Parser._extract_value_string(config.get('csv_delimiter'), ',') + delimiter = _t949 + _t950 = Parser._extract_value_string(config.get('csv_quotechar'), '"') + quotechar = _t950 + _t951 = Parser._extract_value_string(config.get('csv_escapechar'), '"') + escapechar = _t951 + _t952 = Parser._extract_value_string(config.get('csv_comment'), '') + comment = _t952 + _t953 = Parser._extract_value_string_list(config.get('csv_missing_strings'), []) + missing_strings = _t953 + _t954 = Parser._extract_value_string(config.get('csv_decimal_separator'), '.') + decimal_separator = _t954 + _t955 = Parser._extract_value_string(config.get('csv_encoding'), 'utf-8') + encoding = _t955 + _t956 = Parser._extract_value_string(config.get('csv_compression'), 'auto') + compression = _t956 + _t957 = logic_pb2.CSVConfig(header_row=int(header_row), skip=skip, new_line=new_line, delimiter=delimiter, quotechar=quotechar, escapechar=escapechar, comment=comment, missing_strings=missing_strings, decimal_separator=decimal_separator, encoding=encoding, compression=compression) + return _t957 + + @staticmethod + def construct_betree_info(key_types: list[logic_pb2.Type], value_types: list[logic_pb2.Type], config_dict: list[tuple[str, logic_pb2.Value]]) -> logic_pb2.BeTreeInfo: + config = dict(config_dict) + _t958 = Parser._try_extract_value_float64(config.get('betree_config_epsilon')) + epsilon = _t958 + _t959 = Parser._try_extract_value_int64(config.get('betree_config_max_pivots')) + max_pivots = _t959 + _t960 = Parser._try_extract_value_int64(config.get('betree_config_max_deltas')) + max_deltas = _t960 + _t961 = Parser._try_extract_value_int64(config.get('betree_config_max_leaf')) + max_leaf = _t961 + _t962 = logic_pb2.BeTreeConfig(epsilon=epsilon, max_pivots=max_pivots, max_deltas=max_deltas, max_leaf=max_leaf) + storage_config = _t962 + _t963 = Parser._try_extract_value_uint128(config.get('betree_locator_root_pageid')) + root_pageid = _t963 + _t964 = Parser._try_extract_value_bytes(config.get('betree_locator_inline_data')) + inline_data = _t964 + _t965 = Parser._try_extract_value_int64(config.get('betree_locator_element_count')) + element_count = _t965 + _t966 = Parser._try_extract_value_int64(config.get('betree_locator_tree_height')) + tree_height = _t966 + _t967 = logic_pb2.BeTreeLocator(root_pageid=root_pageid, inline_data=inline_data, element_count=element_count, tree_height=tree_height) + relation_locator = _t967 + _t968 = logic_pb2.BeTreeInfo(key_types=key_types, value_types=value_types, storage_config=storage_config, relation_locator=relation_locator) + return _t968 + + @staticmethod + def default_configure() -> transactions_pb2.Configure: + _t969 = transactions_pb2.IVMConfig(level=transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_OFF) + ivm_config = _t969 + _t970 = transactions_pb2.Configure(semantics_version=0, ivm_config=ivm_config, optimization_level=transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT) + return _t970 + + @staticmethod + def construct_configure(config_dict: list[tuple[str, logic_pb2.Value]]) -> transactions_pb2.Configure: + config = dict(config_dict) + maintenance_level_val = config.get('ivm.maintenance_level') + maintenance_level = transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + if (maintenance_level_val is not None and maintenance_level_val.HasField('string_value')): + if maintenance_level_val.string_value == 'off': + maintenance_level = transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + else: + if maintenance_level_val.string_value == 'auto': + maintenance_level = transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_AUTO + else: + if maintenance_level_val.string_value == 'all': + maintenance_level = transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_ALL + else: + maintenance_level = transactions_pb2.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + _t971 = transactions_pb2.IVMConfig(level=maintenance_level) + ivm_config = _t971 + _t972 = Parser._extract_value_int64(config.get('semantics_version'), 0) + semantics_version = _t972 + optimization_level_val = config.get('optimization_level') + optimization_level = transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + if (optimization_level_val is not None and optimization_level_val.HasField('string_value')): + if optimization_level_val.string_value == 'default': + optimization_level = transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + else: + if optimization_level_val.string_value == 'conservative': + optimization_level = transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_CONSERVATIVE + else: + if optimization_level_val.string_value == 'aggressive': + optimization_level = transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_AGGRESSIVE + else: + optimization_level = transactions_pb2.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + _t973 = transactions_pb2.Configure(semantics_version=semantics_version, ivm_config=ivm_config, optimization_level=optimization_level) + return _t973 + + @staticmethod + def export_csv_config(path: str, columns: list[transactions_pb2.ExportCSVColumn], config_dict: list[tuple[str, logic_pb2.Value]]) -> transactions_pb2.ExportCSVConfig: + config = dict(config_dict) + _t974 = Parser._extract_value_int64(config.get('partition_size'), 0) + partition_size = _t974 + _t975 = Parser._extract_value_string(config.get('compression'), '') + compression = _t975 + _t976 = Parser._extract_value_boolean(config.get('syntax_header_row'), True) + syntax_header_row = _t976 + _t977 = Parser._extract_value_string(config.get('syntax_missing_string'), '') + syntax_missing_string = _t977 + _t978 = Parser._extract_value_string(config.get('syntax_delim'), ',') + syntax_delim = _t978 + _t979 = Parser._extract_value_string(config.get('syntax_quotechar'), '"') + syntax_quotechar = _t979 + _t980 = Parser._extract_value_string(config.get('syntax_escapechar'), '\\') + syntax_escapechar = _t980 + _t981 = transactions_pb2.ExportCSVConfig(path=path, data_columns=columns, partition_size=partition_size, compression=compression, syntax_header_row=syntax_header_row, syntax_missing_string=syntax_missing_string, syntax_delim=syntax_delim, syntax_quotechar=syntax_quotechar, syntax_escapechar=syntax_escapechar) + return _t981 + + # --- Parse methods --- + + def parse_transaction(self) -> transactions_pb2.Transaction: + self.consume_literal('(') + self.consume_literal('transaction') + + if (self.match_lookahead_literal('(', 0) and self.match_lookahead_literal('configure', 1)): + _t354 = self.parse_configure() + _t353 = _t354 + else: + _t353 = None + configure0 = _t353 + + if (self.match_lookahead_literal('(', 0) and self.match_lookahead_literal('sync', 1)): + _t356 = self.parse_sync() + _t355 = _t356 + else: + _t355 = None + sync1 = _t355 + xs2 = [] + cond3 = self.match_lookahead_literal('(', 0) + while cond3: + _t357 = self.parse_epoch() + item4 = _t357 + xs2.append(item4) + cond3 = self.match_lookahead_literal('(', 0) + epochs5 = xs2 + self.consume_literal(')') + _t358 = Parser.default_configure() + _t359 = transactions_pb2.Transaction(epochs=epochs5, configure=(configure0 if configure0 is not None else _t358), sync=sync1) + return _t359 + + def parse_configure(self) -> transactions_pb2.Configure: + self.consume_literal('(') + self.consume_literal('configure') + _t360 = self.parse_config_dict() + config_dict6 = _t360 + self.consume_literal(')') + _t361 = Parser.construct_configure(config_dict6) + return _t361 + + def parse_config_dict(self) -> list[tuple[str, logic_pb2.Value]]: + self.consume_literal('{') + xs7 = [] + cond8 = self.match_lookahead_literal(':', 0) + while cond8: + _t362 = self.parse_config_key_value() + item9 = _t362 + xs7.append(item9) + cond8 = self.match_lookahead_literal(':', 0) + config_key_values10 = xs7 + self.consume_literal('}') + return config_key_values10 + + def parse_config_key_value(self) -> tuple[str, logic_pb2.Value]: + self.consume_literal(':') + symbol11 = self.consume_terminal('SYMBOL') + _t363 = self.parse_value() + value12 = _t363 + return (symbol11, value12,) + + def parse_value(self) -> logic_pb2.Value: + + if self.match_lookahead_literal('true', 0): + _t364 = 9 + else: + + if self.match_lookahead_literal('missing', 0): + _t365 = 8 + else: + + if self.match_lookahead_literal('false', 0): + _t366 = 9 + else: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('datetime', 1): + _t368 = 1 + else: + + if self.match_lookahead_literal('date', 1): + _t369 = 0 + else: + _t369 = -1 + _t368 = _t369 + _t367 = _t368 + else: + + if self.match_lookahead_terminal('UINT128', 0): + _t370 = 5 + else: + + if self.match_lookahead_terminal('STRING', 0): + _t371 = 2 + else: + + if self.match_lookahead_terminal('INT128', 0): + _t372 = 6 + else: + + if self.match_lookahead_terminal('INT', 0): + _t373 = 3 + else: + + if self.match_lookahead_terminal('FLOAT', 0): + _t374 = 4 + else: + + if self.match_lookahead_terminal('DECIMAL', 0): + _t375 = 7 + else: + _t375 = -1 + _t374 = _t375 + _t373 = _t374 + _t372 = _t373 + _t371 = _t372 + _t370 = _t371 + _t367 = _t370 + _t366 = _t367 + _t365 = _t366 + _t364 = _t365 + prediction13 = _t364 + + if prediction13 == 9: + _t377 = self.parse_boolean_value() + boolean_value22 = _t377 + _t378 = logic_pb2.Value(boolean_value=boolean_value22) + _t376 = _t378 + else: + + if prediction13 == 8: + self.consume_literal('missing') + _t380 = logic_pb2.MissingValue() + _t381 = logic_pb2.Value(missing_value=_t380) + _t379 = _t381 + else: + + if prediction13 == 7: + decimal21 = self.consume_terminal('DECIMAL') + _t383 = logic_pb2.Value(decimal_value=decimal21) + _t382 = _t383 + else: + + if prediction13 == 6: + int12820 = self.consume_terminal('INT128') + _t385 = logic_pb2.Value(int128_value=int12820) + _t384 = _t385 + else: + + if prediction13 == 5: + uint12819 = self.consume_terminal('UINT128') + _t387 = logic_pb2.Value(uint128_value=uint12819) + _t386 = _t387 + else: + + if prediction13 == 4: + float18 = self.consume_terminal('FLOAT') + _t389 = logic_pb2.Value(float_value=float18) + _t388 = _t389 + else: + + if prediction13 == 3: + int17 = self.consume_terminal('INT') + _t391 = logic_pb2.Value(int_value=int17) + _t390 = _t391 + else: + + if prediction13 == 2: + string16 = self.consume_terminal('STRING') + _t393 = logic_pb2.Value(string_value=string16) + _t392 = _t393 + else: + + if prediction13 == 1: + _t395 = self.parse_datetime() + datetime15 = _t395 + _t396 = logic_pb2.Value(datetime_value=datetime15) + _t394 = _t396 + else: + + if prediction13 == 0: + _t398 = self.parse_date() + date14 = _t398 + _t399 = logic_pb2.Value(date_value=date14) + _t397 = _t399 + else: + raise ParseError(f"{'Unexpected token in value'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t394 = _t397 + _t392 = _t394 + _t390 = _t392 + _t388 = _t390 + _t386 = _t388 + _t384 = _t386 + _t382 = _t384 + _t379 = _t382 + _t376 = _t379 + return _t376 + + def parse_date(self) -> logic_pb2.DateValue: + self.consume_literal('(') + self.consume_literal('date') + int23 = self.consume_terminal('INT') + int_324 = self.consume_terminal('INT') + int_425 = self.consume_terminal('INT') + self.consume_literal(')') + _t400 = logic_pb2.DateValue(year=int(int23), month=int(int_324), day=int(int_425)) + return _t400 + + def parse_datetime(self) -> logic_pb2.DateTimeValue: + self.consume_literal('(') + self.consume_literal('datetime') + int26 = self.consume_terminal('INT') + int_327 = self.consume_terminal('INT') + int_428 = self.consume_terminal('INT') + int_529 = self.consume_terminal('INT') + int_630 = self.consume_terminal('INT') + int_731 = self.consume_terminal('INT') + + if self.match_lookahead_terminal('INT', 0): + _t401 = self.consume_terminal('INT') + else: + _t401 = None + int_832 = _t401 + self.consume_literal(')') + _t402 = logic_pb2.DateTimeValue(year=int(int26), month=int(int_327), day=int(int_428), hour=int(int_529), minute=int(int_630), second=int(int_731), microsecond=int((int_832 if int_832 is not None else 0))) + return _t402 + + def parse_boolean_value(self) -> bool: + + if self.match_lookahead_literal('true', 0): + _t403 = 0 + else: + + if self.match_lookahead_literal('false', 0): + _t404 = 1 + else: + _t404 = -1 + _t403 = _t404 + prediction33 = _t403 + + if prediction33 == 1: + self.consume_literal('false') + _t405 = False + else: + + if prediction33 == 0: + self.consume_literal('true') + _t406 = True + else: + raise ParseError(f"{'Unexpected token in boolean_value'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t405 = _t406 + return _t405 + + def parse_sync(self) -> transactions_pb2.Sync: + self.consume_literal('(') + self.consume_literal('sync') + xs34 = [] + cond35 = self.match_lookahead_literal(':', 0) + while cond35: + _t407 = self.parse_fragment_id() + item36 = _t407 + xs34.append(item36) + cond35 = self.match_lookahead_literal(':', 0) + fragment_ids37 = xs34 + self.consume_literal(')') + _t408 = transactions_pb2.Sync(fragments=fragment_ids37) + return _t408 + + def parse_fragment_id(self) -> fragments_pb2.FragmentId: + self.consume_literal(':') + symbol38 = self.consume_terminal('SYMBOL') + return fragments_pb2.FragmentId(id=symbol38.encode()) + + def parse_epoch(self) -> transactions_pb2.Epoch: + self.consume_literal('(') + self.consume_literal('epoch') + + if (self.match_lookahead_literal('(', 0) and self.match_lookahead_literal('writes', 1)): + _t410 = self.parse_epoch_writes() + _t409 = _t410 + else: + _t409 = None + epoch_writes39 = _t409 + + if self.match_lookahead_literal('(', 0): + _t412 = self.parse_epoch_reads() + _t411 = _t412 + else: + _t411 = None + epoch_reads40 = _t411 + self.consume_literal(')') + _t413 = transactions_pb2.Epoch(writes=(epoch_writes39 if epoch_writes39 is not None else []), reads=(epoch_reads40 if epoch_reads40 is not None else [])) + return _t413 + + def parse_epoch_writes(self) -> list[transactions_pb2.Write]: + self.consume_literal('(') + self.consume_literal('writes') + xs41 = [] + cond42 = self.match_lookahead_literal('(', 0) + while cond42: + _t414 = self.parse_write() + item43 = _t414 + xs41.append(item43) + cond42 = self.match_lookahead_literal('(', 0) + writes44 = xs41 + self.consume_literal(')') + return writes44 + + def parse_write(self) -> transactions_pb2.Write: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('undefine', 1): + _t416 = 1 + else: + + if self.match_lookahead_literal('define', 1): + _t417 = 0 + else: + + if self.match_lookahead_literal('context', 1): + _t418 = 2 + else: + _t418 = -1 + _t417 = _t418 + _t416 = _t417 + _t415 = _t416 + else: + _t415 = -1 + prediction45 = _t415 + + if prediction45 == 2: + _t420 = self.parse_context() + context48 = _t420 + _t421 = transactions_pb2.Write(context=context48) + _t419 = _t421 + else: + + if prediction45 == 1: + _t423 = self.parse_undefine() + undefine47 = _t423 + _t424 = transactions_pb2.Write(undefine=undefine47) + _t422 = _t424 + else: + + if prediction45 == 0: + _t426 = self.parse_define() + define46 = _t426 + _t427 = transactions_pb2.Write(define=define46) + _t425 = _t427 + else: + raise ParseError(f"{'Unexpected token in write'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t422 = _t425 + _t419 = _t422 + return _t419 + + def parse_define(self) -> transactions_pb2.Define: + self.consume_literal('(') + self.consume_literal('define') + _t428 = self.parse_fragment() + fragment49 = _t428 + self.consume_literal(')') + _t429 = transactions_pb2.Define(fragment=fragment49) + return _t429 + + def parse_fragment(self) -> fragments_pb2.Fragment: + self.consume_literal('(') + self.consume_literal('fragment') + _t430 = self.parse_new_fragment_id() + new_fragment_id50 = _t430 + xs51 = [] + cond52 = self.match_lookahead_literal('(', 0) + while cond52: + _t431 = self.parse_declaration() + item53 = _t431 + xs51.append(item53) + cond52 = self.match_lookahead_literal('(', 0) + declarations54 = xs51 + self.consume_literal(')') + return self.construct_fragment(new_fragment_id50, declarations54) + + def parse_new_fragment_id(self) -> fragments_pb2.FragmentId: + _t432 = self.parse_fragment_id() + fragment_id55 = _t432 + self.start_fragment(fragment_id55) + return fragment_id55 + + def parse_declaration(self) -> logic_pb2.Declaration: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('rel_edb', 1): + _t434 = 3 + else: + + if self.match_lookahead_literal('functional_dependency', 1): + _t435 = 2 + else: + + if self.match_lookahead_literal('def', 1): + _t436 = 0 + else: + + if self.match_lookahead_literal('csv_data', 1): + _t437 = 3 + else: + + if self.match_lookahead_literal('betree_relation', 1): + _t438 = 3 + else: + + if self.match_lookahead_literal('algorithm', 1): + _t439 = 1 + else: + _t439 = -1 + _t438 = _t439 + _t437 = _t438 + _t436 = _t437 + _t435 = _t436 + _t434 = _t435 + _t433 = _t434 + else: + _t433 = -1 + prediction56 = _t433 + + if prediction56 == 3: + _t441 = self.parse_data() + data60 = _t441 + _t442 = logic_pb2.Declaration(data=data60) + _t440 = _t442 + else: + + if prediction56 == 2: + _t444 = self.parse_constraint() + constraint59 = _t444 + _t445 = logic_pb2.Declaration(constraint=constraint59) + _t443 = _t445 + else: + + if prediction56 == 1: + _t447 = self.parse_algorithm() + algorithm58 = _t447 + _t448 = logic_pb2.Declaration(algorithm=algorithm58) + _t446 = _t448 + else: + + if prediction56 == 0: + _t450 = self.parse_def() + def57 = _t450 + _t451 = logic_pb2.Declaration() + getattr(_t451, 'def').CopyFrom(def57) + _t449 = _t451 + else: + raise ParseError(f"{'Unexpected token in declaration'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t446 = _t449 + _t443 = _t446 + _t440 = _t443 + return _t440 + + def parse_def(self) -> logic_pb2.Def: + self.consume_literal('(') + self.consume_literal('def') + _t452 = self.parse_relation_id() + relation_id61 = _t452 + _t453 = self.parse_abstraction() + abstraction62 = _t453 + + if self.match_lookahead_literal('(', 0): + _t455 = self.parse_attrs() + _t454 = _t455 + else: + _t454 = None + attrs63 = _t454 + self.consume_literal(')') + _t456 = logic_pb2.Def(name=relation_id61, body=abstraction62, attrs=(attrs63 if attrs63 is not None else [])) + return _t456 + + def parse_relation_id(self) -> logic_pb2.RelationId: + + if self.match_lookahead_literal(':', 0): + _t457 = 0 + else: + + if self.match_lookahead_terminal('UINT128', 0): + _t458 = 1 + else: + _t458 = -1 + _t457 = _t458 + prediction64 = _t457 + + if prediction64 == 1: + uint12866 = self.consume_terminal('UINT128') + _t459 = logic_pb2.RelationId(id_low=uint12866.low, id_high=uint12866.high) + else: + + if prediction64 == 0: + self.consume_literal(':') + symbol65 = self.consume_terminal('SYMBOL') + _t460 = self.relation_id_from_string(symbol65) + else: + raise ParseError(f"{'Unexpected token in relation_id'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t459 = _t460 + return _t459 + + def parse_abstraction(self) -> logic_pb2.Abstraction: + self.consume_literal('(') + _t461 = self.parse_bindings() + bindings67 = _t461 + _t462 = self.parse_formula() + formula68 = _t462 + self.consume_literal(')') + _t463 = logic_pb2.Abstraction(vars=(bindings67[0] + (bindings67[1] if bindings67[1] is not None else [])), value=formula68) + return _t463 + + def parse_bindings(self) -> tuple[list[logic_pb2.Binding], list[logic_pb2.Binding]]: + self.consume_literal('[') + xs69 = [] + cond70 = self.match_lookahead_terminal('SYMBOL', 0) + while cond70: + _t464 = self.parse_binding() + item71 = _t464 + xs69.append(item71) + cond70 = self.match_lookahead_terminal('SYMBOL', 0) + bindings72 = xs69 + + if self.match_lookahead_literal('|', 0): + _t466 = self.parse_value_bindings() + _t465 = _t466 + else: + _t465 = None + value_bindings73 = _t465 + self.consume_literal(']') + return (bindings72, (value_bindings73 if value_bindings73 is not None else []),) + + def parse_binding(self) -> logic_pb2.Binding: + symbol74 = self.consume_terminal('SYMBOL') + self.consume_literal('::') + _t467 = self.parse_type() + type75 = _t467 + _t468 = logic_pb2.Var(name=symbol74) + _t469 = logic_pb2.Binding(var=_t468, type=type75) + return _t469 + + def parse_type(self) -> logic_pb2.Type: + + if self.match_lookahead_literal('UNKNOWN', 0): + _t470 = 0 + else: + + if self.match_lookahead_literal('UINT128', 0): + _t471 = 4 + else: + + if self.match_lookahead_literal('STRING', 0): + _t472 = 1 + else: + + if self.match_lookahead_literal('MISSING', 0): + _t473 = 8 + else: + + if self.match_lookahead_literal('INT128', 0): + _t474 = 5 + else: + + if self.match_lookahead_literal('INT', 0): + _t475 = 2 + else: + + if self.match_lookahead_literal('FLOAT', 0): + _t476 = 3 + else: + + if self.match_lookahead_literal('DATETIME', 0): + _t477 = 7 + else: + + if self.match_lookahead_literal('DATE', 0): + _t478 = 6 + else: + + if self.match_lookahead_literal('BOOLEAN', 0): + _t479 = 10 + else: + + if self.match_lookahead_literal('(', 0): + _t480 = 9 + else: + _t480 = -1 + _t479 = _t480 + _t478 = _t479 + _t477 = _t478 + _t476 = _t477 + _t475 = _t476 + _t474 = _t475 + _t473 = _t474 + _t472 = _t473 + _t471 = _t472 + _t470 = _t471 + prediction76 = _t470 + + if prediction76 == 10: + _t482 = self.parse_boolean_type() + boolean_type87 = _t482 + _t483 = logic_pb2.Type(boolean_type=boolean_type87) + _t481 = _t483 + else: + + if prediction76 == 9: + _t485 = self.parse_decimal_type() + decimal_type86 = _t485 + _t486 = logic_pb2.Type(decimal_type=decimal_type86) + _t484 = _t486 + else: + + if prediction76 == 8: + _t488 = self.parse_missing_type() + missing_type85 = _t488 + _t489 = logic_pb2.Type(missing_type=missing_type85) + _t487 = _t489 + else: + + if prediction76 == 7: + _t491 = self.parse_datetime_type() + datetime_type84 = _t491 + _t492 = logic_pb2.Type(datetime_type=datetime_type84) + _t490 = _t492 + else: + + if prediction76 == 6: + _t494 = self.parse_date_type() + date_type83 = _t494 + _t495 = logic_pb2.Type(date_type=date_type83) + _t493 = _t495 + else: + + if prediction76 == 5: + _t497 = self.parse_int128_type() + int128_type82 = _t497 + _t498 = logic_pb2.Type(int128_type=int128_type82) + _t496 = _t498 + else: + + if prediction76 == 4: + _t500 = self.parse_uint128_type() + uint128_type81 = _t500 + _t501 = logic_pb2.Type(uint128_type=uint128_type81) + _t499 = _t501 + else: + + if prediction76 == 3: + _t503 = self.parse_float_type() + float_type80 = _t503 + _t504 = logic_pb2.Type(float_type=float_type80) + _t502 = _t504 + else: + + if prediction76 == 2: + _t506 = self.parse_int_type() + int_type79 = _t506 + _t507 = logic_pb2.Type(int_type=int_type79) + _t505 = _t507 + else: + + if prediction76 == 1: + _t509 = self.parse_string_type() + string_type78 = _t509 + _t510 = logic_pb2.Type(string_type=string_type78) + _t508 = _t510 + else: + + if prediction76 == 0: + _t512 = self.parse_unspecified_type() + unspecified_type77 = _t512 + _t513 = logic_pb2.Type(unspecified_type=unspecified_type77) + _t511 = _t513 + else: + raise ParseError(f"{'Unexpected token in type'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t508 = _t511 + _t505 = _t508 + _t502 = _t505 + _t499 = _t502 + _t496 = _t499 + _t493 = _t496 + _t490 = _t493 + _t487 = _t490 + _t484 = _t487 + _t481 = _t484 + return _t481 + + def parse_unspecified_type(self) -> logic_pb2.UnspecifiedType: + self.consume_literal('UNKNOWN') + _t514 = logic_pb2.UnspecifiedType() + return _t514 + + def parse_string_type(self) -> logic_pb2.StringType: + self.consume_literal('STRING') + _t515 = logic_pb2.StringType() + return _t515 + + def parse_int_type(self) -> logic_pb2.IntType: + self.consume_literal('INT') + _t516 = logic_pb2.IntType() + return _t516 + + def parse_float_type(self) -> logic_pb2.FloatType: + self.consume_literal('FLOAT') + _t517 = logic_pb2.FloatType() + return _t517 + + def parse_uint128_type(self) -> logic_pb2.UInt128Type: + self.consume_literal('UINT128') + _t518 = logic_pb2.UInt128Type() + return _t518 + + def parse_int128_type(self) -> logic_pb2.Int128Type: + self.consume_literal('INT128') + _t519 = logic_pb2.Int128Type() + return _t519 + + def parse_date_type(self) -> logic_pb2.DateType: + self.consume_literal('DATE') + _t520 = logic_pb2.DateType() + return _t520 + + def parse_datetime_type(self) -> logic_pb2.DateTimeType: + self.consume_literal('DATETIME') + _t521 = logic_pb2.DateTimeType() + return _t521 + + def parse_missing_type(self) -> logic_pb2.MissingType: + self.consume_literal('MISSING') + _t522 = logic_pb2.MissingType() + return _t522 + + def parse_decimal_type(self) -> logic_pb2.DecimalType: + self.consume_literal('(') + self.consume_literal('DECIMAL') + int88 = self.consume_terminal('INT') + int_389 = self.consume_terminal('INT') + self.consume_literal(')') + _t523 = logic_pb2.DecimalType(precision=int(int88), scale=int(int_389)) + return _t523 + + def parse_boolean_type(self) -> logic_pb2.BooleanType: + self.consume_literal('BOOLEAN') + _t524 = logic_pb2.BooleanType() + return _t524 + + def parse_value_bindings(self) -> list[logic_pb2.Binding]: + self.consume_literal('|') + xs90 = [] + cond91 = self.match_lookahead_terminal('SYMBOL', 0) + while cond91: + _t525 = self.parse_binding() + item92 = _t525 + xs90.append(item92) + cond91 = self.match_lookahead_terminal('SYMBOL', 0) + bindings93 = xs90 + return bindings93 + + def parse_formula(self) -> logic_pb2.Formula: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('true', 1): + _t527 = 0 + else: + + if self.match_lookahead_literal('relatom', 1): + _t528 = 11 + else: + + if self.match_lookahead_literal('reduce', 1): + _t529 = 3 + else: + + if self.match_lookahead_literal('primitive', 1): + _t530 = 10 + else: + + if self.match_lookahead_literal('pragma', 1): + _t531 = 9 + else: + + if self.match_lookahead_literal('or', 1): + _t532 = 5 + else: + + if self.match_lookahead_literal('not', 1): + _t533 = 6 + else: + + if self.match_lookahead_literal('ffi', 1): + _t534 = 7 + else: + + if self.match_lookahead_literal('false', 1): + _t535 = 1 + else: + + if self.match_lookahead_literal('exists', 1): + _t536 = 2 + else: + + if self.match_lookahead_literal('cast', 1): + _t537 = 12 + else: + + if self.match_lookahead_literal('atom', 1): + _t538 = 8 + else: + + if self.match_lookahead_literal('and', 1): + _t539 = 4 + else: + + if self.match_lookahead_literal('>=', 1): + _t540 = 10 + else: + + if self.match_lookahead_literal('>', 1): + _t541 = 10 + else: + + if self.match_lookahead_literal('=', 1): + _t542 = 10 + else: + + if self.match_lookahead_literal('<=', 1): + _t543 = 10 + else: + + if self.match_lookahead_literal('<', 1): + _t544 = 10 + else: + + if self.match_lookahead_literal('/', 1): + _t545 = 10 + else: + + if self.match_lookahead_literal('-', 1): + _t546 = 10 + else: + + if self.match_lookahead_literal('+', 1): + _t547 = 10 + else: + + if self.match_lookahead_literal('*', 1): + _t548 = 10 + else: + _t548 = -1 + _t547 = _t548 + _t546 = _t547 + _t545 = _t546 + _t544 = _t545 + _t543 = _t544 + _t542 = _t543 + _t541 = _t542 + _t540 = _t541 + _t539 = _t540 + _t538 = _t539 + _t537 = _t538 + _t536 = _t537 + _t535 = _t536 + _t534 = _t535 + _t533 = _t534 + _t532 = _t533 + _t531 = _t532 + _t530 = _t531 + _t529 = _t530 + _t528 = _t529 + _t527 = _t528 + _t526 = _t527 + else: + _t526 = -1 + prediction94 = _t526 + + if prediction94 == 12: + _t550 = self.parse_cast() + cast107 = _t550 + _t551 = logic_pb2.Formula(cast=cast107) + _t549 = _t551 + else: + + if prediction94 == 11: + _t553 = self.parse_rel_atom() + rel_atom106 = _t553 + _t554 = logic_pb2.Formula(rel_atom=rel_atom106) + _t552 = _t554 + else: + + if prediction94 == 10: + _t556 = self.parse_primitive() + primitive105 = _t556 + _t557 = logic_pb2.Formula(primitive=primitive105) + _t555 = _t557 + else: + + if prediction94 == 9: + _t559 = self.parse_pragma() + pragma104 = _t559 + _t560 = logic_pb2.Formula(pragma=pragma104) + _t558 = _t560 + else: + + if prediction94 == 8: + _t562 = self.parse_atom() + atom103 = _t562 + _t563 = logic_pb2.Formula(atom=atom103) + _t561 = _t563 + else: + + if prediction94 == 7: + _t565 = self.parse_ffi() + ffi102 = _t565 + _t566 = logic_pb2.Formula(ffi=ffi102) + _t564 = _t566 + else: + + if prediction94 == 6: + _t568 = self.parse_not() + not101 = _t568 + _t569 = logic_pb2.Formula() + getattr(_t569, 'not').CopyFrom(not101) + _t567 = _t569 + else: + + if prediction94 == 5: + _t571 = self.parse_disjunction() + disjunction100 = _t571 + _t572 = logic_pb2.Formula(disjunction=disjunction100) + _t570 = _t572 + else: + + if prediction94 == 4: + _t574 = self.parse_conjunction() + conjunction99 = _t574 + _t575 = logic_pb2.Formula(conjunction=conjunction99) + _t573 = _t575 + else: + + if prediction94 == 3: + _t577 = self.parse_reduce() + reduce98 = _t577 + _t578 = logic_pb2.Formula(reduce=reduce98) + _t576 = _t578 + else: + + if prediction94 == 2: + _t580 = self.parse_exists() + exists97 = _t580 + _t581 = logic_pb2.Formula(exists=exists97) + _t579 = _t581 + else: + + if prediction94 == 1: + _t583 = self.parse_false() + false96 = _t583 + _t584 = logic_pb2.Formula(disjunction=false96) + _t582 = _t584 + else: + + if prediction94 == 0: + _t586 = self.parse_true() + true95 = _t586 + _t587 = logic_pb2.Formula(conjunction=true95) + _t585 = _t587 + else: + raise ParseError(f"{'Unexpected token in formula'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t582 = _t585 + _t579 = _t582 + _t576 = _t579 + _t573 = _t576 + _t570 = _t573 + _t567 = _t570 + _t564 = _t567 + _t561 = _t564 + _t558 = _t561 + _t555 = _t558 + _t552 = _t555 + _t549 = _t552 + return _t549 + + def parse_true(self) -> logic_pb2.Conjunction: + self.consume_literal('(') + self.consume_literal('true') + self.consume_literal(')') + _t588 = logic_pb2.Conjunction(args=[]) + return _t588 + + def parse_false(self) -> logic_pb2.Disjunction: + self.consume_literal('(') + self.consume_literal('false') + self.consume_literal(')') + _t589 = logic_pb2.Disjunction(args=[]) + return _t589 + + def parse_exists(self) -> logic_pb2.Exists: + self.consume_literal('(') + self.consume_literal('exists') + _t590 = self.parse_bindings() + bindings108 = _t590 + _t591 = self.parse_formula() + formula109 = _t591 + self.consume_literal(')') + _t592 = logic_pb2.Abstraction(vars=(bindings108[0] + (bindings108[1] if bindings108[1] is not None else [])), value=formula109) + _t593 = logic_pb2.Exists(body=_t592) + return _t593 + + def parse_reduce(self) -> logic_pb2.Reduce: + self.consume_literal('(') + self.consume_literal('reduce') + _t594 = self.parse_abstraction() + abstraction110 = _t594 + _t595 = self.parse_abstraction() + abstraction_3111 = _t595 + _t596 = self.parse_terms() + terms112 = _t596 + self.consume_literal(')') + _t597 = logic_pb2.Reduce(op=abstraction110, body=abstraction_3111, terms=terms112) + return _t597 + + def parse_terms(self) -> list[logic_pb2.Term]: + self.consume_literal('(') + self.consume_literal('terms') + xs113 = [] + cond114 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond114: + _t598 = self.parse_term() + item115 = _t598 + xs113.append(item115) + cond114 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + terms116 = xs113 + self.consume_literal(')') + return terms116 + + def parse_term(self) -> logic_pb2.Term: + + if self.match_lookahead_literal('true', 0): + _t599 = 1 + else: + + if self.match_lookahead_literal('missing', 0): + _t600 = 1 + else: + + if self.match_lookahead_literal('false', 0): + _t601 = 1 + else: + + if self.match_lookahead_literal('(', 0): + _t602 = 1 + else: + + if self.match_lookahead_terminal('UINT128', 0): + _t603 = 1 + else: + + if self.match_lookahead_terminal('SYMBOL', 0): + _t604 = 0 + else: + + if self.match_lookahead_terminal('STRING', 0): + _t605 = 1 + else: + + if self.match_lookahead_terminal('INT128', 0): + _t606 = 1 + else: + + if self.match_lookahead_terminal('INT', 0): + _t607 = 1 + else: + + if self.match_lookahead_terminal('FLOAT', 0): + _t608 = 1 + else: + + if self.match_lookahead_terminal('DECIMAL', 0): + _t609 = 1 + else: + _t609 = -1 + _t608 = _t609 + _t607 = _t608 + _t606 = _t607 + _t605 = _t606 + _t604 = _t605 + _t603 = _t604 + _t602 = _t603 + _t601 = _t602 + _t600 = _t601 + _t599 = _t600 + prediction117 = _t599 + + if prediction117 == 1: + _t611 = self.parse_constant() + constant119 = _t611 + _t612 = logic_pb2.Term(constant=constant119) + _t610 = _t612 + else: + + if prediction117 == 0: + _t614 = self.parse_var() + var118 = _t614 + _t615 = logic_pb2.Term(var=var118) + _t613 = _t615 + else: + raise ParseError(f"{'Unexpected token in term'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t610 = _t613 + return _t610 + + def parse_var(self) -> logic_pb2.Var: + symbol120 = self.consume_terminal('SYMBOL') + _t616 = logic_pb2.Var(name=symbol120) + return _t616 + + def parse_constant(self) -> logic_pb2.Value: + _t617 = self.parse_value() + value121 = _t617 + return value121 + + def parse_conjunction(self) -> logic_pb2.Conjunction: + self.consume_literal('(') + self.consume_literal('and') + xs122 = [] + cond123 = self.match_lookahead_literal('(', 0) + while cond123: + _t618 = self.parse_formula() + item124 = _t618 + xs122.append(item124) + cond123 = self.match_lookahead_literal('(', 0) + formulas125 = xs122 + self.consume_literal(')') + _t619 = logic_pb2.Conjunction(args=formulas125) + return _t619 + + def parse_disjunction(self) -> logic_pb2.Disjunction: + self.consume_literal('(') + self.consume_literal('or') + xs126 = [] + cond127 = self.match_lookahead_literal('(', 0) + while cond127: + _t620 = self.parse_formula() + item128 = _t620 + xs126.append(item128) + cond127 = self.match_lookahead_literal('(', 0) + formulas129 = xs126 + self.consume_literal(')') + _t621 = logic_pb2.Disjunction(args=formulas129) + return _t621 + + def parse_not(self) -> logic_pb2.Not: + self.consume_literal('(') + self.consume_literal('not') + _t622 = self.parse_formula() + formula130 = _t622 + self.consume_literal(')') + _t623 = logic_pb2.Not(arg=formula130) + return _t623 + + def parse_ffi(self) -> logic_pb2.FFI: + self.consume_literal('(') + self.consume_literal('ffi') + _t624 = self.parse_name() + name131 = _t624 + _t625 = self.parse_ffi_args() + ffi_args132 = _t625 + _t626 = self.parse_terms() + terms133 = _t626 + self.consume_literal(')') + _t627 = logic_pb2.FFI(name=name131, args=ffi_args132, terms=terms133) + return _t627 + + def parse_name(self) -> str: + self.consume_literal(':') + symbol134 = self.consume_terminal('SYMBOL') + return symbol134 + + def parse_ffi_args(self) -> list[logic_pb2.Abstraction]: + self.consume_literal('(') + self.consume_literal('args') + xs135 = [] + cond136 = self.match_lookahead_literal('(', 0) + while cond136: + _t628 = self.parse_abstraction() + item137 = _t628 + xs135.append(item137) + cond136 = self.match_lookahead_literal('(', 0) + abstractions138 = xs135 + self.consume_literal(')') + return abstractions138 + + def parse_atom(self) -> logic_pb2.Atom: + self.consume_literal('(') + self.consume_literal('atom') + _t629 = self.parse_relation_id() + relation_id139 = _t629 + xs140 = [] + cond141 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond141: + _t630 = self.parse_term() + item142 = _t630 + xs140.append(item142) + cond141 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + terms143 = xs140 + self.consume_literal(')') + _t631 = logic_pb2.Atom(name=relation_id139, terms=terms143) + return _t631 + + def parse_pragma(self) -> logic_pb2.Pragma: + self.consume_literal('(') + self.consume_literal('pragma') + _t632 = self.parse_name() + name144 = _t632 + xs145 = [] + cond146 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond146: + _t633 = self.parse_term() + item147 = _t633 + xs145.append(item147) + cond146 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + terms148 = xs145 + self.consume_literal(')') + _t634 = logic_pb2.Pragma(name=name144, terms=terms148) + return _t634 + + def parse_primitive(self) -> logic_pb2.Primitive: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('primitive', 1): + _t636 = 9 + else: + + if self.match_lookahead_literal('>=', 1): + _t637 = 4 + else: + + if self.match_lookahead_literal('>', 1): + _t638 = 3 + else: + + if self.match_lookahead_literal('=', 1): + _t639 = 0 + else: + + if self.match_lookahead_literal('<=', 1): + _t640 = 2 + else: + + if self.match_lookahead_literal('<', 1): + _t641 = 1 + else: + + if self.match_lookahead_literal('/', 1): + _t642 = 8 + else: + + if self.match_lookahead_literal('-', 1): + _t643 = 6 + else: + + if self.match_lookahead_literal('+', 1): + _t644 = 5 + else: + + if self.match_lookahead_literal('*', 1): + _t645 = 7 + else: + _t645 = -1 + _t644 = _t645 + _t643 = _t644 + _t642 = _t643 + _t641 = _t642 + _t640 = _t641 + _t639 = _t640 + _t638 = _t639 + _t637 = _t638 + _t636 = _t637 + _t635 = _t636 + else: + _t635 = -1 + prediction149 = _t635 + + if prediction149 == 9: + self.consume_literal('(') + self.consume_literal('primitive') + _t647 = self.parse_name() + name159 = _t647 + xs160 = [] + cond161 = (((((((((((self.match_lookahead_literal('#', 0) or self.match_lookahead_literal('(', 0)) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond161: + _t648 = self.parse_rel_term() + item162 = _t648 + xs160.append(item162) + cond161 = (((((((((((self.match_lookahead_literal('#', 0) or self.match_lookahead_literal('(', 0)) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + rel_terms163 = xs160 + self.consume_literal(')') + _t649 = logic_pb2.Primitive(name=name159, terms=rel_terms163) + _t646 = _t649 + else: + + if prediction149 == 8: + _t651 = self.parse_divide() + divide158 = _t651 + _t650 = divide158 + else: + + if prediction149 == 7: + _t653 = self.parse_multiply() + multiply157 = _t653 + _t652 = multiply157 + else: + + if prediction149 == 6: + _t655 = self.parse_minus() + minus156 = _t655 + _t654 = minus156 + else: + + if prediction149 == 5: + _t657 = self.parse_add() + add155 = _t657 + _t656 = add155 + else: + + if prediction149 == 4: + _t659 = self.parse_gt_eq() + gt_eq154 = _t659 + _t658 = gt_eq154 + else: + + if prediction149 == 3: + _t661 = self.parse_gt() + gt153 = _t661 + _t660 = gt153 + else: + + if prediction149 == 2: + _t663 = self.parse_lt_eq() + lt_eq152 = _t663 + _t662 = lt_eq152 + else: + + if prediction149 == 1: + _t665 = self.parse_lt() + lt151 = _t665 + _t664 = lt151 + else: + + if prediction149 == 0: + _t667 = self.parse_eq() + eq150 = _t667 + _t666 = eq150 + else: + raise ParseError(f"{'Unexpected token in primitive'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t664 = _t666 + _t662 = _t664 + _t660 = _t662 + _t658 = _t660 + _t656 = _t658 + _t654 = _t656 + _t652 = _t654 + _t650 = _t652 + _t646 = _t650 + return _t646 + + def parse_eq(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('=') + _t668 = self.parse_term() + term164 = _t668 + _t669 = self.parse_term() + term_3165 = _t669 + self.consume_literal(')') + _t670 = logic_pb2.RelTerm(term=term164) + _t671 = logic_pb2.RelTerm(term=term_3165) + _t672 = logic_pb2.Primitive(name='rel_primitive_eq', terms=[_t670, _t671]) + return _t672 + + def parse_lt(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('<') + _t673 = self.parse_term() + term166 = _t673 + _t674 = self.parse_term() + term_3167 = _t674 + self.consume_literal(')') + _t675 = logic_pb2.RelTerm(term=term166) + _t676 = logic_pb2.RelTerm(term=term_3167) + _t677 = logic_pb2.Primitive(name='rel_primitive_lt_monotype', terms=[_t675, _t676]) + return _t677 + + def parse_lt_eq(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('<=') + _t678 = self.parse_term() + term168 = _t678 + _t679 = self.parse_term() + term_3169 = _t679 + self.consume_literal(')') + _t680 = logic_pb2.RelTerm(term=term168) + _t681 = logic_pb2.RelTerm(term=term_3169) + _t682 = logic_pb2.Primitive(name='rel_primitive_lt_eq_monotype', terms=[_t680, _t681]) + return _t682 + + def parse_gt(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('>') + _t683 = self.parse_term() + term170 = _t683 + _t684 = self.parse_term() + term_3171 = _t684 + self.consume_literal(')') + _t685 = logic_pb2.RelTerm(term=term170) + _t686 = logic_pb2.RelTerm(term=term_3171) + _t687 = logic_pb2.Primitive(name='rel_primitive_gt_monotype', terms=[_t685, _t686]) + return _t687 + + def parse_gt_eq(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('>=') + _t688 = self.parse_term() + term172 = _t688 + _t689 = self.parse_term() + term_3173 = _t689 + self.consume_literal(')') + _t690 = logic_pb2.RelTerm(term=term172) + _t691 = logic_pb2.RelTerm(term=term_3173) + _t692 = logic_pb2.Primitive(name='rel_primitive_gt_eq_monotype', terms=[_t690, _t691]) + return _t692 + + def parse_add(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('+') + _t693 = self.parse_term() + term174 = _t693 + _t694 = self.parse_term() + term_3175 = _t694 + _t695 = self.parse_term() + term_4176 = _t695 + self.consume_literal(')') + _t696 = logic_pb2.RelTerm(term=term174) + _t697 = logic_pb2.RelTerm(term=term_3175) + _t698 = logic_pb2.RelTerm(term=term_4176) + _t699 = logic_pb2.Primitive(name='rel_primitive_add_monotype', terms=[_t696, _t697, _t698]) + return _t699 + + def parse_minus(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('-') + _t700 = self.parse_term() + term177 = _t700 + _t701 = self.parse_term() + term_3178 = _t701 + _t702 = self.parse_term() + term_4179 = _t702 + self.consume_literal(')') + _t703 = logic_pb2.RelTerm(term=term177) + _t704 = logic_pb2.RelTerm(term=term_3178) + _t705 = logic_pb2.RelTerm(term=term_4179) + _t706 = logic_pb2.Primitive(name='rel_primitive_subtract_monotype', terms=[_t703, _t704, _t705]) + return _t706 + + def parse_multiply(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('*') + _t707 = self.parse_term() + term180 = _t707 + _t708 = self.parse_term() + term_3181 = _t708 + _t709 = self.parse_term() + term_4182 = _t709 + self.consume_literal(')') + _t710 = logic_pb2.RelTerm(term=term180) + _t711 = logic_pb2.RelTerm(term=term_3181) + _t712 = logic_pb2.RelTerm(term=term_4182) + _t713 = logic_pb2.Primitive(name='rel_primitive_multiply_monotype', terms=[_t710, _t711, _t712]) + return _t713 + + def parse_divide(self) -> logic_pb2.Primitive: + self.consume_literal('(') + self.consume_literal('/') + _t714 = self.parse_term() + term183 = _t714 + _t715 = self.parse_term() + term_3184 = _t715 + _t716 = self.parse_term() + term_4185 = _t716 + self.consume_literal(')') + _t717 = logic_pb2.RelTerm(term=term183) + _t718 = logic_pb2.RelTerm(term=term_3184) + _t719 = logic_pb2.RelTerm(term=term_4185) + _t720 = logic_pb2.Primitive(name='rel_primitive_divide_monotype', terms=[_t717, _t718, _t719]) + return _t720 + + def parse_rel_term(self) -> logic_pb2.RelTerm: + + if self.match_lookahead_literal('true', 0): + _t721 = 1 + else: + + if self.match_lookahead_literal('missing', 0): + _t722 = 1 + else: + + if self.match_lookahead_literal('false', 0): + _t723 = 1 + else: + + if self.match_lookahead_literal('(', 0): + _t724 = 1 + else: + + if self.match_lookahead_literal('#', 0): + _t725 = 0 + else: + + if self.match_lookahead_terminal('UINT128', 0): + _t726 = 1 + else: + + if self.match_lookahead_terminal('SYMBOL', 0): + _t727 = 1 + else: + + if self.match_lookahead_terminal('STRING', 0): + _t728 = 1 + else: + + if self.match_lookahead_terminal('INT128', 0): + _t729 = 1 + else: + + if self.match_lookahead_terminal('INT', 0): + _t730 = 1 + else: + + if self.match_lookahead_terminal('FLOAT', 0): + _t731 = 1 + else: + + if self.match_lookahead_terminal('DECIMAL', 0): + _t732 = 1 + else: + _t732 = -1 + _t731 = _t732 + _t730 = _t731 + _t729 = _t730 + _t728 = _t729 + _t727 = _t728 + _t726 = _t727 + _t725 = _t726 + _t724 = _t725 + _t723 = _t724 + _t722 = _t723 + _t721 = _t722 + prediction186 = _t721 + + if prediction186 == 1: + _t734 = self.parse_term() + term188 = _t734 + _t735 = logic_pb2.RelTerm(term=term188) + _t733 = _t735 + else: + + if prediction186 == 0: + _t737 = self.parse_specialized_value() + specialized_value187 = _t737 + _t738 = logic_pb2.RelTerm(specialized_value=specialized_value187) + _t736 = _t738 + else: + raise ParseError(f"{'Unexpected token in rel_term'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t733 = _t736 + return _t733 + + def parse_specialized_value(self) -> logic_pb2.Value: + self.consume_literal('#') + _t739 = self.parse_value() + value189 = _t739 + return value189 + + def parse_rel_atom(self) -> logic_pb2.RelAtom: + self.consume_literal('(') + self.consume_literal('relatom') + _t740 = self.parse_name() + name190 = _t740 + xs191 = [] + cond192 = (((((((((((self.match_lookahead_literal('#', 0) or self.match_lookahead_literal('(', 0)) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond192: + _t741 = self.parse_rel_term() + item193 = _t741 + xs191.append(item193) + cond192 = (((((((((((self.match_lookahead_literal('#', 0) or self.match_lookahead_literal('(', 0)) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('SYMBOL', 0)) or self.match_lookahead_terminal('UINT128', 0)) + rel_terms194 = xs191 + self.consume_literal(')') + _t742 = logic_pb2.RelAtom(name=name190, terms=rel_terms194) + return _t742 + + def parse_cast(self) -> logic_pb2.Cast: + self.consume_literal('(') + self.consume_literal('cast') + _t743 = self.parse_term() + term195 = _t743 + _t744 = self.parse_term() + term_3196 = _t744 + self.consume_literal(')') + _t745 = logic_pb2.Cast(input=term195, result=term_3196) + return _t745 + + def parse_attrs(self) -> list[logic_pb2.Attribute]: + self.consume_literal('(') + self.consume_literal('attrs') + xs197 = [] + cond198 = self.match_lookahead_literal('(', 0) + while cond198: + _t746 = self.parse_attribute() + item199 = _t746 + xs197.append(item199) + cond198 = self.match_lookahead_literal('(', 0) + attributes200 = xs197 + self.consume_literal(')') + return attributes200 + + def parse_attribute(self) -> logic_pb2.Attribute: + self.consume_literal('(') + self.consume_literal('attribute') + _t747 = self.parse_name() + name201 = _t747 + xs202 = [] + cond203 = (((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('UINT128', 0)) + while cond203: + _t748 = self.parse_value() + item204 = _t748 + xs202.append(item204) + cond203 = (((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('false', 0)) or self.match_lookahead_literal('missing', 0)) or self.match_lookahead_literal('true', 0)) or self.match_lookahead_terminal('DECIMAL', 0)) or self.match_lookahead_terminal('FLOAT', 0)) or self.match_lookahead_terminal('INT', 0)) or self.match_lookahead_terminal('INT128', 0)) or self.match_lookahead_terminal('STRING', 0)) or self.match_lookahead_terminal('UINT128', 0)) + values205 = xs202 + self.consume_literal(')') + _t749 = logic_pb2.Attribute(name=name201, args=values205) + return _t749 + + def parse_algorithm(self) -> logic_pb2.Algorithm: + self.consume_literal('(') + self.consume_literal('algorithm') + xs206 = [] + cond207 = (self.match_lookahead_literal(':', 0) or self.match_lookahead_terminal('UINT128', 0)) + while cond207: + _t750 = self.parse_relation_id() + item208 = _t750 + xs206.append(item208) + cond207 = (self.match_lookahead_literal(':', 0) or self.match_lookahead_terminal('UINT128', 0)) + relation_ids209 = xs206 + _t751 = self.parse_script() + script210 = _t751 + self.consume_literal(')') + _t752 = logic_pb2.Algorithm(body=script210) + getattr(_t752, 'global').extend(relation_ids209) + return _t752 + + def parse_script(self) -> logic_pb2.Script: + self.consume_literal('(') + self.consume_literal('script') + xs211 = [] + cond212 = self.match_lookahead_literal('(', 0) + while cond212: + _t753 = self.parse_construct() + item213 = _t753 + xs211.append(item213) + cond212 = self.match_lookahead_literal('(', 0) + constructs214 = xs211 + self.consume_literal(')') + _t754 = logic_pb2.Script(constructs=constructs214) + return _t754 + + def parse_construct(self) -> logic_pb2.Construct: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('upsert', 1): + _t756 = 1 + else: + + if self.match_lookahead_literal('monus', 1): + _t757 = 1 + else: + + if self.match_lookahead_literal('monoid', 1): + _t758 = 1 + else: + + if self.match_lookahead_literal('loop', 1): + _t759 = 0 + else: + + if self.match_lookahead_literal('break', 1): + _t760 = 1 + else: + + if self.match_lookahead_literal('assign', 1): + _t761 = 1 + else: + _t761 = -1 + _t760 = _t761 + _t759 = _t760 + _t758 = _t759 + _t757 = _t758 + _t756 = _t757 + _t755 = _t756 + else: + _t755 = -1 + prediction215 = _t755 + + if prediction215 == 1: + _t763 = self.parse_instruction() + instruction217 = _t763 + _t764 = logic_pb2.Construct(instruction=instruction217) + _t762 = _t764 + else: + + if prediction215 == 0: + _t766 = self.parse_loop() + loop216 = _t766 + _t767 = logic_pb2.Construct(loop=loop216) + _t765 = _t767 + else: + raise ParseError(f"{'Unexpected token in construct'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t762 = _t765 + return _t762 + + def parse_loop(self) -> logic_pb2.Loop: + self.consume_literal('(') + self.consume_literal('loop') + _t768 = self.parse_init() + init218 = _t768 + _t769 = self.parse_script() + script219 = _t769 + self.consume_literal(')') + _t770 = logic_pb2.Loop(init=init218, body=script219) + return _t770 + + def parse_init(self) -> list[logic_pb2.Instruction]: + self.consume_literal('(') + self.consume_literal('init') + xs220 = [] + cond221 = self.match_lookahead_literal('(', 0) + while cond221: + _t771 = self.parse_instruction() + item222 = _t771 + xs220.append(item222) + cond221 = self.match_lookahead_literal('(', 0) + instructions223 = xs220 + self.consume_literal(')') + return instructions223 + + def parse_instruction(self) -> logic_pb2.Instruction: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('upsert', 1): + _t773 = 1 + else: + + if self.match_lookahead_literal('monus', 1): + _t774 = 4 + else: + + if self.match_lookahead_literal('monoid', 1): + _t775 = 3 + else: + + if self.match_lookahead_literal('break', 1): + _t776 = 2 + else: + + if self.match_lookahead_literal('assign', 1): + _t777 = 0 + else: + _t777 = -1 + _t776 = _t777 + _t775 = _t776 + _t774 = _t775 + _t773 = _t774 + _t772 = _t773 + else: + _t772 = -1 + prediction224 = _t772 + + if prediction224 == 4: + _t779 = self.parse_monus_def() + monus_def229 = _t779 + _t780 = logic_pb2.Instruction(monus_def=monus_def229) + _t778 = _t780 + else: + + if prediction224 == 3: + _t782 = self.parse_monoid_def() + monoid_def228 = _t782 + _t783 = logic_pb2.Instruction(monoid_def=monoid_def228) + _t781 = _t783 + else: + + if prediction224 == 2: + _t785 = self.parse_break() + break227 = _t785 + _t786 = logic_pb2.Instruction() + getattr(_t786, 'break').CopyFrom(break227) + _t784 = _t786 + else: + + if prediction224 == 1: + _t788 = self.parse_upsert() + upsert226 = _t788 + _t789 = logic_pb2.Instruction(upsert=upsert226) + _t787 = _t789 + else: + + if prediction224 == 0: + _t791 = self.parse_assign() + assign225 = _t791 + _t792 = logic_pb2.Instruction(assign=assign225) + _t790 = _t792 + else: + raise ParseError(f"{'Unexpected token in instruction'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t787 = _t790 + _t784 = _t787 + _t781 = _t784 + _t778 = _t781 + return _t778 + + def parse_assign(self) -> logic_pb2.Assign: + self.consume_literal('(') + self.consume_literal('assign') + _t793 = self.parse_relation_id() + relation_id230 = _t793 + _t794 = self.parse_abstraction() + abstraction231 = _t794 + + if self.match_lookahead_literal('(', 0): + _t796 = self.parse_attrs() + _t795 = _t796 + else: + _t795 = None + attrs232 = _t795 + self.consume_literal(')') + _t797 = logic_pb2.Assign(name=relation_id230, body=abstraction231, attrs=(attrs232 if attrs232 is not None else [])) + return _t797 + + def parse_upsert(self) -> logic_pb2.Upsert: + self.consume_literal('(') + self.consume_literal('upsert') + _t798 = self.parse_relation_id() + relation_id233 = _t798 + _t799 = self.parse_abstraction_with_arity() + abstraction_with_arity234 = _t799 + + if self.match_lookahead_literal('(', 0): + _t801 = self.parse_attrs() + _t800 = _t801 + else: + _t800 = None + attrs235 = _t800 + self.consume_literal(')') + _t802 = logic_pb2.Upsert(name=relation_id233, body=abstraction_with_arity234[0], attrs=(attrs235 if attrs235 is not None else []), value_arity=abstraction_with_arity234[1]) + return _t802 + + def parse_abstraction_with_arity(self) -> tuple[logic_pb2.Abstraction, int]: + self.consume_literal('(') + _t803 = self.parse_bindings() + bindings236 = _t803 + _t804 = self.parse_formula() + formula237 = _t804 + self.consume_literal(')') + _t805 = logic_pb2.Abstraction(vars=(bindings236[0] + (bindings236[1] if bindings236[1] is not None else [])), value=formula237) + return (_t805, len(bindings236[1]),) + + def parse_break(self) -> logic_pb2.Break: + self.consume_literal('(') + self.consume_literal('break') + _t806 = self.parse_relation_id() + relation_id238 = _t806 + _t807 = self.parse_abstraction() + abstraction239 = _t807 + + if self.match_lookahead_literal('(', 0): + _t809 = self.parse_attrs() + _t808 = _t809 + else: + _t808 = None + attrs240 = _t808 + self.consume_literal(')') + _t810 = logic_pb2.Break(name=relation_id238, body=abstraction239, attrs=(attrs240 if attrs240 is not None else [])) + return _t810 + + def parse_monoid_def(self) -> logic_pb2.MonoidDef: + self.consume_literal('(') + self.consume_literal('monoid') + _t811 = self.parse_monoid() + monoid241 = _t811 + _t812 = self.parse_relation_id() + relation_id242 = _t812 + _t813 = self.parse_abstraction_with_arity() + abstraction_with_arity243 = _t813 + + if self.match_lookahead_literal('(', 0): + _t815 = self.parse_attrs() + _t814 = _t815 + else: + _t814 = None + attrs244 = _t814 + self.consume_literal(')') + _t816 = logic_pb2.MonoidDef(monoid=monoid241, name=relation_id242, body=abstraction_with_arity243[0], attrs=(attrs244 if attrs244 is not None else []), value_arity=abstraction_with_arity243[1]) + return _t816 + + def parse_monoid(self) -> logic_pb2.Monoid: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('sum', 1): + _t818 = 3 + else: + + if self.match_lookahead_literal('or', 1): + _t819 = 0 + else: + + if self.match_lookahead_literal('min', 1): + _t820 = 1 + else: + + if self.match_lookahead_literal('max', 1): + _t821 = 2 + else: + _t821 = -1 + _t820 = _t821 + _t819 = _t820 + _t818 = _t819 + _t817 = _t818 + else: + _t817 = -1 + prediction245 = _t817 + + if prediction245 == 3: + _t823 = self.parse_sum_monoid() + sum_monoid249 = _t823 + _t824 = logic_pb2.Monoid(sum_monoid=sum_monoid249) + _t822 = _t824 + else: + + if prediction245 == 2: + _t826 = self.parse_max_monoid() + max_monoid248 = _t826 + _t827 = logic_pb2.Monoid(max_monoid=max_monoid248) + _t825 = _t827 + else: + + if prediction245 == 1: + _t829 = self.parse_min_monoid() + min_monoid247 = _t829 + _t830 = logic_pb2.Monoid(min_monoid=min_monoid247) + _t828 = _t830 + else: + + if prediction245 == 0: + _t832 = self.parse_or_monoid() + or_monoid246 = _t832 + _t833 = logic_pb2.Monoid(or_monoid=or_monoid246) + _t831 = _t833 + else: + raise ParseError(f"{'Unexpected token in monoid'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t828 = _t831 + _t825 = _t828 + _t822 = _t825 + return _t822 + + def parse_or_monoid(self) -> logic_pb2.OrMonoid: + self.consume_literal('(') + self.consume_literal('or') + self.consume_literal(')') + _t834 = logic_pb2.OrMonoid() + return _t834 + + def parse_min_monoid(self) -> logic_pb2.MinMonoid: + self.consume_literal('(') + self.consume_literal('min') + _t835 = self.parse_type() + type250 = _t835 + self.consume_literal(')') + _t836 = logic_pb2.MinMonoid(type=type250) + return _t836 + + def parse_max_monoid(self) -> logic_pb2.MaxMonoid: + self.consume_literal('(') + self.consume_literal('max') + _t837 = self.parse_type() + type251 = _t837 + self.consume_literal(')') + _t838 = logic_pb2.MaxMonoid(type=type251) + return _t838 + + def parse_sum_monoid(self) -> logic_pb2.SumMonoid: + self.consume_literal('(') + self.consume_literal('sum') + _t839 = self.parse_type() + type252 = _t839 + self.consume_literal(')') + _t840 = logic_pb2.SumMonoid(type=type252) + return _t840 + + def parse_monus_def(self) -> logic_pb2.MonusDef: + self.consume_literal('(') + self.consume_literal('monus') + _t841 = self.parse_monoid() + monoid253 = _t841 + _t842 = self.parse_relation_id() + relation_id254 = _t842 + _t843 = self.parse_abstraction_with_arity() + abstraction_with_arity255 = _t843 + + if self.match_lookahead_literal('(', 0): + _t845 = self.parse_attrs() + _t844 = _t845 + else: + _t844 = None + attrs256 = _t844 + self.consume_literal(')') + _t846 = logic_pb2.MonusDef(monoid=monoid253, name=relation_id254, body=abstraction_with_arity255[0], attrs=(attrs256 if attrs256 is not None else []), value_arity=abstraction_with_arity255[1]) + return _t846 + + def parse_constraint(self) -> logic_pb2.Constraint: + self.consume_literal('(') + self.consume_literal('functional_dependency') + _t847 = self.parse_relation_id() + relation_id257 = _t847 + _t848 = self.parse_abstraction() + abstraction258 = _t848 + _t849 = self.parse_functional_dependency_keys() + functional_dependency_keys259 = _t849 + _t850 = self.parse_functional_dependency_values() + functional_dependency_values260 = _t850 + self.consume_literal(')') + _t851 = logic_pb2.FunctionalDependency(guard=abstraction258, keys=functional_dependency_keys259, values=functional_dependency_values260) + _t852 = logic_pb2.Constraint(name=relation_id257, functional_dependency=_t851) + return _t852 + + def parse_functional_dependency_keys(self) -> list[logic_pb2.Var]: + self.consume_literal('(') + self.consume_literal('keys') + xs261 = [] + cond262 = self.match_lookahead_terminal('SYMBOL', 0) + while cond262: + _t853 = self.parse_var() + item263 = _t853 + xs261.append(item263) + cond262 = self.match_lookahead_terminal('SYMBOL', 0) + vars264 = xs261 + self.consume_literal(')') + return vars264 + + def parse_functional_dependency_values(self) -> list[logic_pb2.Var]: + self.consume_literal('(') + self.consume_literal('values') + xs265 = [] + cond266 = self.match_lookahead_terminal('SYMBOL', 0) + while cond266: + _t854 = self.parse_var() + item267 = _t854 + xs265.append(item267) + cond266 = self.match_lookahead_terminal('SYMBOL', 0) + vars268 = xs265 + self.consume_literal(')') + return vars268 + + def parse_data(self) -> logic_pb2.Data: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('rel_edb', 1): + _t856 = 0 + else: + + if self.match_lookahead_literal('csv_data', 1): + _t857 = 2 + else: + + if self.match_lookahead_literal('betree_relation', 1): + _t858 = 1 + else: + _t858 = -1 + _t857 = _t858 + _t856 = _t857 + _t855 = _t856 + else: + _t855 = -1 + prediction269 = _t855 + + if prediction269 == 2: + _t860 = self.parse_csv_data() + csv_data272 = _t860 + _t861 = logic_pb2.Data(csv_data=csv_data272) + _t859 = _t861 + else: + + if prediction269 == 1: + _t863 = self.parse_betree_relation() + betree_relation271 = _t863 + _t864 = logic_pb2.Data(betree_relation=betree_relation271) + _t862 = _t864 + else: + + if prediction269 == 0: + _t866 = self.parse_rel_edb() + rel_edb270 = _t866 + _t867 = logic_pb2.Data(rel_edb=rel_edb270) + _t865 = _t867 + else: + raise ParseError(f"{'Unexpected token in data'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t862 = _t865 + _t859 = _t862 + return _t859 + + def parse_rel_edb(self) -> logic_pb2.RelEDB: + self.consume_literal('(') + self.consume_literal('rel_edb') + _t868 = self.parse_relation_id() + relation_id273 = _t868 + _t869 = self.parse_rel_edb_path() + rel_edb_path274 = _t869 + _t870 = self.parse_rel_edb_types() + rel_edb_types275 = _t870 + self.consume_literal(')') + _t871 = logic_pb2.RelEDB(target_id=relation_id273, path=rel_edb_path274, types=rel_edb_types275) + return _t871 + + def parse_rel_edb_path(self) -> list[str]: + self.consume_literal('[') + xs276 = [] + cond277 = self.match_lookahead_terminal('STRING', 0) + while cond277: + item278 = self.consume_terminal('STRING') + xs276.append(item278) + cond277 = self.match_lookahead_terminal('STRING', 0) + strings279 = xs276 + self.consume_literal(']') + return strings279 + + def parse_rel_edb_types(self) -> list[logic_pb2.Type]: + self.consume_literal('[') + xs280 = [] + cond281 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + while cond281: + _t872 = self.parse_type() + item282 = _t872 + xs280.append(item282) + cond281 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + types283 = xs280 + self.consume_literal(']') + return types283 + + def parse_betree_relation(self) -> logic_pb2.BeTreeRelation: + self.consume_literal('(') + self.consume_literal('betree_relation') + _t873 = self.parse_relation_id() + relation_id284 = _t873 + _t874 = self.parse_betree_info() + betree_info285 = _t874 + self.consume_literal(')') + _t875 = logic_pb2.BeTreeRelation(name=relation_id284, relation_info=betree_info285) + return _t875 + + def parse_betree_info(self) -> logic_pb2.BeTreeInfo: + self.consume_literal('(') + self.consume_literal('betree_info') + _t876 = self.parse_betree_info_key_types() + betree_info_key_types286 = _t876 + _t877 = self.parse_betree_info_value_types() + betree_info_value_types287 = _t877 + _t878 = self.parse_config_dict() + config_dict288 = _t878 + self.consume_literal(')') + _t879 = Parser.construct_betree_info(betree_info_key_types286, betree_info_value_types287, config_dict288) + return _t879 + + def parse_betree_info_key_types(self) -> list[logic_pb2.Type]: + self.consume_literal('(') + self.consume_literal('key_types') + xs289 = [] + cond290 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + while cond290: + _t880 = self.parse_type() + item291 = _t880 + xs289.append(item291) + cond290 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + types292 = xs289 + self.consume_literal(')') + return types292 + + def parse_betree_info_value_types(self) -> list[logic_pb2.Type]: + self.consume_literal('(') + self.consume_literal('value_types') + xs293 = [] + cond294 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + while cond294: + _t881 = self.parse_type() + item295 = _t881 + xs293.append(item295) + cond294 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + types296 = xs293 + self.consume_literal(')') + return types296 + + def parse_csv_data(self) -> logic_pb2.CSVData: + self.consume_literal('(') + self.consume_literal('csv_data') + _t882 = self.parse_csvlocator() + csvlocator297 = _t882 + _t883 = self.parse_csv_config() + csv_config298 = _t883 + _t884 = self.parse_csv_columns() + csv_columns299 = _t884 + _t885 = self.parse_csv_asof() + csv_asof300 = _t885 + self.consume_literal(')') + _t886 = logic_pb2.CSVData(locator=csvlocator297, config=csv_config298, columns=csv_columns299, asof=csv_asof300) + return _t886 + + def parse_csvlocator(self) -> logic_pb2.CSVLocator: + self.consume_literal('(') + self.consume_literal('csv_locator') + + if (self.match_lookahead_literal('(', 0) and self.match_lookahead_literal('paths', 1)): + _t888 = self.parse_csv_locator_paths() + _t887 = _t888 + else: + _t887 = None + csv_locator_paths301 = _t887 + + if self.match_lookahead_literal('(', 0): + _t890 = self.parse_csv_locator_inline_data() + _t889 = _t890 + else: + _t889 = None + csv_locator_inline_data302 = _t889 + self.consume_literal(')') + _t891 = logic_pb2.CSVLocator(paths=(csv_locator_paths301 if csv_locator_paths301 is not None else []), inline_data=(csv_locator_inline_data302 if csv_locator_inline_data302 is not None else '').encode()) + return _t891 + + def parse_csv_locator_paths(self) -> list[str]: + self.consume_literal('(') + self.consume_literal('paths') + xs303 = [] + cond304 = self.match_lookahead_terminal('STRING', 0) + while cond304: + item305 = self.consume_terminal('STRING') + xs303.append(item305) + cond304 = self.match_lookahead_terminal('STRING', 0) + strings306 = xs303 + self.consume_literal(')') + return strings306 + + def parse_csv_locator_inline_data(self) -> str: + self.consume_literal('(') + self.consume_literal('inline_data') + string307 = self.consume_terminal('STRING') + self.consume_literal(')') + return string307 + + def parse_csv_config(self) -> logic_pb2.CSVConfig: + self.consume_literal('(') + self.consume_literal('csv_config') + _t892 = self.parse_config_dict() + config_dict308 = _t892 + self.consume_literal(')') + _t893 = Parser.construct_csv_config(config_dict308) + return _t893 + + def parse_csv_columns(self) -> list[logic_pb2.CSVColumn]: + self.consume_literal('(') + self.consume_literal('columns') + xs309 = [] + cond310 = self.match_lookahead_literal('(', 0) + while cond310: + _t894 = self.parse_csv_column() + item311 = _t894 + xs309.append(item311) + cond310 = self.match_lookahead_literal('(', 0) + csv_columns312 = xs309 + self.consume_literal(')') + return csv_columns312 + + def parse_csv_column(self) -> logic_pb2.CSVColumn: + self.consume_literal('(') + self.consume_literal('column') + string313 = self.consume_terminal('STRING') + _t895 = self.parse_relation_id() + relation_id314 = _t895 + self.consume_literal('[') + xs315 = [] + cond316 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + while cond316: + _t896 = self.parse_type() + item317 = _t896 + xs315.append(item317) + cond316 = ((((((((((self.match_lookahead_literal('(', 0) or self.match_lookahead_literal('BOOLEAN', 0)) or self.match_lookahead_literal('DATE', 0)) or self.match_lookahead_literal('DATETIME', 0)) or self.match_lookahead_literal('FLOAT', 0)) or self.match_lookahead_literal('INT', 0)) or self.match_lookahead_literal('INT128', 0)) or self.match_lookahead_literal('MISSING', 0)) or self.match_lookahead_literal('STRING', 0)) or self.match_lookahead_literal('UINT128', 0)) or self.match_lookahead_literal('UNKNOWN', 0)) + types318 = xs315 + self.consume_literal(']') + self.consume_literal(')') + _t897 = logic_pb2.CSVColumn(column_name=string313, target_id=relation_id314, types=types318) + return _t897 + + def parse_csv_asof(self) -> str: + self.consume_literal('(') + self.consume_literal('asof') + string319 = self.consume_terminal('STRING') + self.consume_literal(')') + return string319 + + def parse_undefine(self) -> transactions_pb2.Undefine: + self.consume_literal('(') + self.consume_literal('undefine') + _t898 = self.parse_fragment_id() + fragment_id320 = _t898 + self.consume_literal(')') + _t899 = transactions_pb2.Undefine(fragment_id=fragment_id320) + return _t899 + + def parse_context(self) -> transactions_pb2.Context: + self.consume_literal('(') + self.consume_literal('context') + xs321 = [] + cond322 = (self.match_lookahead_literal(':', 0) or self.match_lookahead_terminal('UINT128', 0)) + while cond322: + _t900 = self.parse_relation_id() + item323 = _t900 + xs321.append(item323) + cond322 = (self.match_lookahead_literal(':', 0) or self.match_lookahead_terminal('UINT128', 0)) + relation_ids324 = xs321 + self.consume_literal(')') + _t901 = transactions_pb2.Context(relations=relation_ids324) + return _t901 + + def parse_epoch_reads(self) -> list[transactions_pb2.Read]: + self.consume_literal('(') + self.consume_literal('reads') + xs325 = [] + cond326 = self.match_lookahead_literal('(', 0) + while cond326: + _t902 = self.parse_read() + item327 = _t902 + xs325.append(item327) + cond326 = self.match_lookahead_literal('(', 0) + reads328 = xs325 + self.consume_literal(')') + return reads328 + + def parse_read(self) -> transactions_pb2.Read: + + if self.match_lookahead_literal('(', 0): + + if self.match_lookahead_literal('what_if', 1): + _t904 = 2 + else: + + if self.match_lookahead_literal('output', 1): + _t905 = 1 + else: + + if self.match_lookahead_literal('export', 1): + _t906 = 4 + else: + + if self.match_lookahead_literal('demand', 1): + _t907 = 0 + else: + + if self.match_lookahead_literal('abort', 1): + _t908 = 3 + else: + _t908 = -1 + _t907 = _t908 + _t906 = _t907 + _t905 = _t906 + _t904 = _t905 + _t903 = _t904 + else: + _t903 = -1 + prediction329 = _t903 + + if prediction329 == 4: + _t910 = self.parse_export() + export334 = _t910 + _t911 = transactions_pb2.Read(export=export334) + _t909 = _t911 + else: + + if prediction329 == 3: + _t913 = self.parse_abort() + abort333 = _t913 + _t914 = transactions_pb2.Read(abort=abort333) + _t912 = _t914 + else: + + if prediction329 == 2: + _t916 = self.parse_what_if() + what_if332 = _t916 + _t917 = transactions_pb2.Read(what_if=what_if332) + _t915 = _t917 + else: + + if prediction329 == 1: + _t919 = self.parse_output() + output331 = _t919 + _t920 = transactions_pb2.Read(output=output331) + _t918 = _t920 + else: + + if prediction329 == 0: + _t922 = self.parse_demand() + demand330 = _t922 + _t923 = transactions_pb2.Read(demand=demand330) + _t921 = _t923 + else: + raise ParseError(f"{'Unexpected token in read'}: {self.lookahead(0).type}=`{self.lookahead(0).value}`") + _t918 = _t921 + _t915 = _t918 + _t912 = _t915 + _t909 = _t912 + return _t909 + + def parse_demand(self) -> transactions_pb2.Demand: + self.consume_literal('(') + self.consume_literal('demand') + _t924 = self.parse_relation_id() + relation_id335 = _t924 + self.consume_literal(')') + _t925 = transactions_pb2.Demand(relation_id=relation_id335) + return _t925 + + def parse_output(self) -> transactions_pb2.Output: + self.consume_literal('(') + self.consume_literal('output') + + if (self.match_lookahead_literal(':', 0) and self.match_lookahead_terminal('SYMBOL', 1)): + _t927 = self.parse_name() + _t926 = _t927 + else: + _t926 = None + name336 = _t926 + _t928 = self.parse_relation_id() + relation_id337 = _t928 + self.consume_literal(')') + _t929 = transactions_pb2.Output(name=(name336 if name336 is not None else 'output'), relation_id=relation_id337) + return _t929 + + def parse_what_if(self) -> transactions_pb2.WhatIf: + self.consume_literal('(') + self.consume_literal('what_if') + _t930 = self.parse_name() + name338 = _t930 + _t931 = self.parse_epoch() + epoch339 = _t931 + self.consume_literal(')') + _t932 = transactions_pb2.WhatIf(branch=name338, epoch=epoch339) + return _t932 + + def parse_abort(self) -> transactions_pb2.Abort: + self.consume_literal('(') + self.consume_literal('abort') + + if (self.match_lookahead_literal(':', 0) and self.match_lookahead_terminal('SYMBOL', 1)): + _t934 = self.parse_name() + _t933 = _t934 + else: + _t933 = None + name340 = _t933 + _t935 = self.parse_relation_id() + relation_id341 = _t935 + self.consume_literal(')') + _t936 = transactions_pb2.Abort(name=(name340 if name340 is not None else 'abort'), relation_id=relation_id341) + return _t936 + + def parse_export(self) -> transactions_pb2.Export: + self.consume_literal('(') + self.consume_literal('export') + _t937 = self.parse_export_csv_config() + export_csv_config342 = _t937 + self.consume_literal(')') + _t938 = transactions_pb2.Export(csv_config=export_csv_config342) + return _t938 + + def parse_export_csv_config(self) -> transactions_pb2.ExportCSVConfig: + self.consume_literal('(') + self.consume_literal('export_csv_config') + _t939 = self.parse_export_csv_path() + export_csv_path343 = _t939 + _t940 = self.parse_export_csv_columns() + export_csv_columns344 = _t940 + _t941 = self.parse_config_dict() + config_dict345 = _t941 + self.consume_literal(')') + _t942 = Parser.export_csv_config(export_csv_path343, export_csv_columns344, config_dict345) + return _t942 + + def parse_export_csv_path(self) -> str: + self.consume_literal('(') + self.consume_literal('path') + string346 = self.consume_terminal('STRING') + self.consume_literal(')') + return string346 + + def parse_export_csv_columns(self) -> list[transactions_pb2.ExportCSVColumn]: + self.consume_literal('(') + self.consume_literal('columns') + xs347 = [] + cond348 = self.match_lookahead_literal('(', 0) + while cond348: + _t943 = self.parse_export_csv_column() + item349 = _t943 + xs347.append(item349) + cond348 = self.match_lookahead_literal('(', 0) + export_csv_columns350 = xs347 + self.consume_literal(')') + return export_csv_columns350 + + def parse_export_csv_column(self) -> transactions_pb2.ExportCSVColumn: + self.consume_literal('(') + self.consume_literal('column') + string351 = self.consume_terminal('STRING') + _t944 = self.parse_relation_id() + relation_id352 = _t944 + self.consume_literal(')') + _t945 = transactions_pb2.ExportCSVColumn(column_name=string351, column_data=relation_id352) + return _t945 + + +def parse(input_str: str) -> Any: + """Parse input string and return parse tree.""" + lexer = Lexer(input_str) + parser = Parser(lexer.tokens) + result = parser.parse_transaction() + # Check for unconsumed tokens (except EOF) + if parser.pos < len(parser.tokens): + remaining_token = parser.lookahead(0) + if remaining_token.type != '$': + raise ParseError(f"Unexpected token at end of input: {remaining_token}") + return result diff --git a/python-tools/src/lqp/ir.py b/python-tools/src/lqp/ir.py new file mode 100644 index 00000000..3d80de20 --- /dev/null +++ b/python-tools/src/lqp/ir.py @@ -0,0 +1,564 @@ +from __future__ import annotations +from dataclasses import dataclass, field +from enum import Enum +from typing import Union, Tuple, Sequence, Optional, Dict +import datetime as dt +from decimal import Decimal + +# Tree representation of LQP. Each non-terminal (those with more than one +# option) is an "abstract" class and each terminal is its own class. All of +# which are children of LqpNode. Value is an exception -- it is just a value. + +@dataclass(frozen=True) +class SourceInfo: + file: str + line: int + column: int + + def __str__(self) -> str: + return f"{self.file}:{self.line}:{self.column}" + +# --- Logic Types --- + +@dataclass(frozen=True) +class LqpNode: + meta: Optional[SourceInfo] + +# Declaration := Def | Algorithm +@dataclass(frozen=True) +class Declaration(LqpNode): + pass + +# Def(name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class Def(Declaration): + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# Constraint := FunctionalDependency +@dataclass(frozen=True) +class Constraint(Declaration): + name: RelationId + pass + +# FunctionalDependency(guard::Abstraction, x::Var[], y::Var[]) +@dataclass(frozen=True) +class FunctionalDependency(Constraint): + guard: Abstraction + keys: Sequence[Var] + values: Sequence[Var] + +# Algorithm(globals::RelationId[], body::Script) +@dataclass(frozen=True) +class Algorithm(Declaration): + global_: Sequence[RelationId] + body: Script + +# Script := Construct[] +@dataclass(frozen=True) +class Script(LqpNode): + constructs: Sequence[Construct] + +# Construct := Loop | Instruction +@dataclass(frozen=True) +class Construct(LqpNode): + pass + +# Loop(init::Instruction[], body::Algorithm) +@dataclass(frozen=True) +class Loop(Construct): + init: Sequence[Instruction] + body: Script + +# Instruction := Assign | Break | Upsert | MonoidDef | MonusDef +@dataclass(frozen=True) +class Instruction(Construct): + pass + +# Assign(name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class Assign(Instruction): + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# Upsert(arity::int, name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class Upsert(Instruction): + value_arity: int + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# Break(name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class Break(Instruction): + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# MonoidDef(arity::int, monoid::Monoid, name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class MonoidDef(Instruction): + value_arity: int + monoid: Monoid + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# MonusDef(arity::int, monoid::Monoid, name::RelationId, body::Abstraction, attrs::Attribute[]) +@dataclass(frozen=True) +class MonusDef(Instruction): + value_arity: int + monoid: Monoid + name: RelationId + body: Abstraction + attrs: Sequence[Attribute] + +# Monoid := OrMonoid | MinMonoid | MaxMonoid | SumMonoid +@dataclass(frozen=True) +class Monoid(LqpNode): + pass + +# OrMonoid +@dataclass(frozen=True) +class OrMonoid(Monoid): + pass + +# MinMonoid +@dataclass(frozen=True) +class MinMonoid(Monoid): + type: Type + +# MaxMonoid +@dataclass(frozen=True) +class MaxMonoid(Monoid): + type: Type + +# SumMonoid +@dataclass(frozen=True) +class SumMonoid(Monoid): + type: Type + +# Abstraction(vars::Binding[], value::Formula) +@dataclass(frozen=True) +class Abstraction(LqpNode): + vars: Sequence[Tuple[Var, Type]] + value: Formula + +# Formula := Exists | Reduce | Conjunction | Disjunction | Not | FFI | Atom | Pragma | Primitive | TrueVal | FalseVal | RelAtom | Cast +@dataclass(frozen=True) +class Formula(LqpNode): + pass + +# Exists(body::Abstraction) +@dataclass(frozen=True) +class Exists(Formula): + body: Abstraction + +# Reduce(op::Abstraction, body::Abstraction, terms::Term[]) +@dataclass(frozen=True) +class Reduce(Formula): + op: Abstraction + body: Abstraction + terms: Sequence[Term] + +# Conjunction(args::Formula[]) +@dataclass(frozen=True) +class Conjunction(Formula): + args: Sequence[Formula] + +# Disjunction(args::Formula[]) +@dataclass(frozen=True) +class Disjunction(Formula): + args: Sequence[Formula] + +# Not(arg::Formula) +@dataclass(frozen=True) +class Not(Formula): + arg: Formula + +# FFI(name::string, args::Abstraction[], terms::Term[]) +@dataclass(frozen=True) +class FFI(Formula): + name: str + args: Sequence[Abstraction] + terms: Sequence[Term] + +# Atom(name::RelationId, terms::Term[]) +@dataclass(frozen=True) +class Atom(Formula): + name: RelationId + terms: Sequence[Term] + +# Pragma(name::string, terms::Term[]) +@dataclass(frozen=True) +class Pragma(Formula): + name: str + terms: Sequence[Term] + +# Primitive(name::string, terms::RelTerm[]) +@dataclass(frozen=True) +class Primitive(Formula): + name: str + terms: Sequence[RelTerm] + +# RelAtom(name::string, terms::RelTerm[]) +@dataclass(frozen=True) +class RelAtom(Formula): + name: str + terms: Sequence[RelTerm] + +# Cast(input::Term, result::Term) +@dataclass(frozen=True) +class Cast(Formula): + input: Term + result: Term + +# Var(name::string) +@dataclass(frozen=True) +class Var(LqpNode): + name: str + +# UInt128Value(low::fixed64, high::fixed64) +@dataclass(frozen=True) +class UInt128Value(LqpNode): + value: int + +# Int128Value(low::fixed64, high::fixed64) +@dataclass(frozen=True) +class Int128Value(LqpNode): + value: int + +@dataclass(frozen=True) +class MissingValue(LqpNode): + pass + +# DateValue(year: int, month: int, day: int) +@dataclass(frozen=True) +class DateValue(LqpNode): + value: dt.date + +# DatetimeValue(year: int, month: int, day: int, hour: int, minute: int, second: int, microsecond: int) +@dataclass(frozen=True) +class DateTimeValue(LqpNode): + value: dt.datetime + +# DecimalValue(precision: int, scale: int, value: Decimal) +@dataclass(frozen=True) +class DecimalValue(LqpNode): + precision: int + scale: int + value: Decimal + +# BooleanValue(value: bool) +# Note: We need a custom BooleanValue class to distinguish it from Python's `int` type. +# Python's built-in `bool` is a subclass of `int`. +@dataclass(frozen=True) +class BooleanValue(LqpNode): + value: bool + +@dataclass(frozen=True) +class Value(LqpNode): + value: Union[ + str, + int, + float, + UInt128Value, + Int128Value, + MissingValue, + DateValue, + DateTimeValue, + DecimalValue, + BooleanValue + ] + +# SpecializedValue(value::Value) +@dataclass(frozen=True) +class SpecializedValue(LqpNode): + value: Value + +# Term := Var | Value +Term = Union[Var, Value] + +# RelTerm := Term | SpecializedValue +RelTerm = Union[Term, SpecializedValue] + +# Attribute(name::string, args::Constant[]) +@dataclass(frozen=True) +class Attribute(LqpNode): + name: str + args: Sequence[Value] + +# RelationId(id::UInt128) +@dataclass(frozen=True) +class RelationId(LqpNode): + id: int + + def __post_init__(self): + if self.id < 0 or self.id > 0xffffffffffffffffffffffffffffffff: + raise ValueError("RelationId constructed with out of range (UInt128) number: {}".format(self.id)) + + def __str__(self) -> str: + if self.meta: + return f"RelationId(meta={self.meta}, id={self.id})" + return f"RelationId(id={self.id})" + + def __eq__(self, other) -> bool: + return self.id == other.id + + def __hash__(self) -> int: + return hash(self.id) + +class TypeName(Enum): + UNSPECIFIED = 0 + STRING = 1 + INT = 2 + FLOAT = 3 + UINT128 = 4 + INT128 = 5 + DATE = 6 + DATETIME = 7 + MISSING = 8 + DECIMAL = 9 + BOOLEAN = 10 + + def __str__(self) -> str: + return self.name + +@dataclass(frozen=True) +class Type(LqpNode): + type_name: TypeName + parameters: Sequence[Value] + +# --- Data Types (Base Relations, BeTree Config) --- + +# BeTreeConfig(epsilon::float, max_pivots::int, max_deltas::int, max_leaf::int) +@dataclass(frozen=True) +class BeTreeConfig(LqpNode): + epsilon: float + max_pivots: int + max_deltas: int + max_leaf: int + +# BeTreeLocator(root_pageid::UInt128Value?, inline_data::bytes?, element_count::int, tree_height::int) +# Note: Exactly one of root_pageid or inline_data must be set (oneof in protobuf) +@dataclass(frozen=True) +class BeTreeLocator(LqpNode): + root_pageid: Optional[UInt128Value] + inline_data: Optional[bytes] + element_count: int + tree_height: int + +# BeTreeInfo(key_types::Type[], value_types::Type[], storage_config::BeTreeConfig, relation_locator::BeTreeLocator) +@dataclass(frozen=True) +class BeTreeInfo(LqpNode): + key_types: Sequence[Type] + value_types: Sequence[Type] + storage_config: BeTreeConfig + relation_locator: BeTreeLocator + +# Data := RelEDB | BeTreeRelation | CSVData | IcebergRelation +@dataclass(frozen=True) +class Data(Declaration): + pass + +# RelEDB(target_id::RelationId, path::string[], types::Type[]) +@dataclass(frozen=True) +class RelEDB(Data): + target_id: RelationId + path: Sequence[str] + types: Sequence[Type] + +# BeTreeRelation(name::RelationId, relation_info::BeTreeInfo) +@dataclass(frozen=True) +class BeTreeRelation(Data): + name: RelationId + relation_info: BeTreeInfo + +# CSVData(locator::CSVLocator, config::CSVConfig, columns::CSVColumn[], asof::string) +@dataclass(frozen=True) +class CSVData(Data): + locator: 'CSVLocator' + config: 'CSVConfig' + columns: Sequence['CSVColumn'] + asof: str + +# CSVLocator(paths::string[], inline_data::bytes?) +# Note: Exactly one of paths or inline_data should be set (mutually exclusive) +@dataclass(frozen=True) +class CSVLocator(LqpNode): + paths: Sequence[str] + inline_data: Optional[bytes] + +# CSVConfig(header_row::int, skip::int, new_line::string, delimiter::string, quotechar::string, +# escapechar::string, comment::string, missing_strings::string[], decimal_separator::string, +# encoding::string, compression::string) +@dataclass(frozen=True) +class CSVConfig(LqpNode): + header_row: int + skip: int + new_line: str + delimiter: str + quotechar: str + escapechar: str + comment: str + missing_strings: Sequence[str] + decimal_separator: str + encoding: str + compression: str + +# CSVColumn(column_name::string, target_id::RelationId, types::Type[]) +@dataclass(frozen=True) +class CSVColumn(LqpNode): + column_name: str + target_id: RelationId + types: Sequence[Type] + +# --- Fragment Types --- + +# FragmentId(id::bytes) +@dataclass(frozen=True) +class FragmentId(LqpNode): + id: bytes + + def __eq__(self, other) -> bool: + return self.id == other.id + + def __hash__(self) -> int: + return hash(self.id) + +# Fragment(id::FragmentId, declarations::Declaration[], debug_info::DebugInfo) +@dataclass(frozen=True) +class Fragment(LqpNode): + id: FragmentId + declarations: Sequence[Declaration] + debug_info: DebugInfo + +@dataclass(frozen=True) +class DebugInfo(LqpNode): + id_to_orig_name: Dict[RelationId, str] + +# --- Transaction Types --- + +# Define(fragment::Fragment) +@dataclass(frozen=True) +class Define(LqpNode): + fragment: Fragment + +# Undefine(fragment_id::FragmentId) +@dataclass(frozen=True) +class Undefine(LqpNode): + fragment_id: FragmentId + +# Context(relations::RelationId[]) +@dataclass(frozen=True) +class Context(LqpNode): + relations: Sequence[RelationId] + +# Write := Define | Undefine | Context +@dataclass(frozen=True) +class Write(LqpNode): + write_type: Union[Define, Undefine, Context] + +# Demand(relation_id::RelationId) +@dataclass(frozen=True) +class Demand(LqpNode): + relation_id: RelationId + +# Output(name::string?, relation_id::RelationId) +@dataclass(frozen=True) +class Output(LqpNode): + name: Union[str, None] + relation_id: RelationId + +# ExportCSVConfig +@dataclass(frozen=True) +class ExportCSVConfig(LqpNode): + path: str + data_columns: Sequence[ExportCSVColumn] + partition_size: Optional[int] = None + compression: Optional[str] = None + + syntax_header_row: Optional[int] = None + syntax_missing_string: Optional[str] = None + syntax_delim: Optional[str] = None + syntax_quotechar: Optional[str] = None + syntax_escapechar: Optional[str] = None + +@dataclass(frozen=True) +class ExportCSVColumn(LqpNode): + column_name: str + column_data: RelationId + +# Export(name::string, relation_id::RelationId) +@dataclass(frozen=True) +class Export(LqpNode): + # TODO: Once we add a JSON export, this should be union[ExportCSVConfig, ExportJSONConfig] + config: ExportCSVConfig + +# Abort(name::string?, relation_id::RelationId) +@dataclass(frozen=True) +class Abort(LqpNode): + name: Union[str, None] + relation_id: RelationId + +# Read := Demand | Output | Export | WhatIf | Abort +@dataclass(frozen=True) +class Read(LqpNode): + read_type: Union[Demand, Output, Export, WhatIf, Abort] + +# Epoch(writes::Write[], reads::Read[]) +@dataclass(frozen=True) +class Epoch(LqpNode): + writes: Sequence[Write] = field(default_factory=list) + reads: Sequence[Read] = field(default_factory=list) + +# WhatIf(branch::string?, epoch::Epoch) +@dataclass(frozen=True) +class WhatIf(LqpNode): + branch: Union[str, None] + epoch: Epoch + +# Transaction(epochs::Epoch[], configure::Configure) +@dataclass(frozen=True) +class Transaction(LqpNode): + epochs: Sequence[Epoch] + configure: Configure + sync: Optional[Sync] + +# Configure(semantics_version::int, ivm_config::IVMConfig) +@dataclass(frozen=True) +class Configure(LqpNode): + semantics_version: int + ivm_config: IVMConfig + optimization_level: OptimizationLevel + +# Sync(fragments::FragmentId[]) +@dataclass(frozen=True) +class Sync(LqpNode): + fragments: Sequence[FragmentId] + +# IVMConfig(level::MaintenanceLevel) +@dataclass(frozen=True) +class IVMConfig(LqpNode): + level: MaintenanceLevel + +class MaintenanceLevel(Enum): + UNSPECIFIED = 0 + OFF = 1 + AUTO = 2 + ALL = 3 + + def __str__(self) -> str: + return self.name + +class OptimizationLevel(Enum): + UNSPECIFIED = 0 + DEFAULT = 1 + CONSERVATIVE = 2 + AGGRESSIVE = 3 + + def __str__(self) -> str: + return self.name \ No newline at end of file diff --git a/python-tools/src/lqp/parser.py b/python-tools/src/lqp/parser.py new file mode 100644 index 00000000..911262bf --- /dev/null +++ b/python-tools/src/lqp/parser.py @@ -0,0 +1,843 @@ +""" +Lark-based parser for LQP S-expressions. + +This module contains the grammar, parser, and transformer that converts +parse trees to IR nodes. +""" + +import ast +import hashlib +from lark import Lark, Transformer, v_args +import lqp.ir as ir +from decimal import Decimal +from datetime import date, datetime +from typing import Dict, Any + +grammar = """ +start: transaction | fragment + +transaction: "(transaction" configure? sync? epoch* ")" +configure: "(configure" config_dict ")" +sync: "(sync" fragment_id* ")" +epoch: "(epoch" writes? reads? ")" +writes: "(writes" write* ")" +reads: "(reads" read* ")" + +write: define | undefine | context +define: "(define" fragment ")" +undefine: "(undefine" fragment_id ")" +context: "(context" relation_id* ")" + +read: demand | output | export | abort +demand: "(demand" relation_id ")" +output: "(output" name? relation_id ")" +export: "(export" export_csv_config ")" +abort: "(abort" name? relation_id ")" + +export_csv_config: "(export_csv_config" export_path export_columns config_dict ")" + +export_columns: "(columns" export_column* ")" +export_column: "(column" STRING relation_id ")" +export_path: "(path" STRING ")" + +fragment: "(fragment" fragment_id declaration* ")" + +declaration: def_ | algorithm | constraint | data +def_: "(def" relation_id abstraction attrs? ")" + +constraint: functional_dependency +functional_dependency: "(functional_dependency" relation_id abstraction fd_keys fd_values ")" +fd_keys: "(keys" var* ")" +fd_values: "(values" var* ")" + +data: rel_edb | betree_relation | csv_data +rel_edb: "(rel_edb" relation_id "[" STRING* "]" "[" type_* "]" ")" +betree_relation: "(betree_relation" relation_id betree_info ")" +betree_info: "(betree_info" key_types value_types config_dict ")" +key_types: "(key_types" type_* ")" +value_types: "(value_types" type_* ")" + +csv_data: "(csv_data" csv_locator csv_config csv_columns csv_asof ")" +csv_locator: "(csv_locator" csv_paths? csv_inline_data? ")" +csv_paths: "(paths" STRING* ")" +csv_inline_data: "(inline_data" STRING ")" +csv_config: "(csv_config" config_dict ")" +csv_columns: "(columns" csv_column* ")" +csv_column: "(column" STRING relation_id "[" type_* "]" ")" +csv_asof: "(asof" STRING ")" + +algorithm: "(algorithm" relation_id* script ")" +script: "(script" construct* ")" + +construct: loop | instruction +loop: "(loop" init script ")" +init: "(init" instruction* ")" + +instruction: assign | upsert | break_ | monoid_def | monus_def + +assign : "(assign" relation_id abstraction attrs? ")" +upsert : "(upsert" relation_id abstraction attrs? ")" +break_ : "(break" relation_id abstraction attrs? ")" +monoid_def : "(monoid" monoid relation_id abstraction attrs? ")" +monus_def : "(monus" monoid relation_id abstraction attrs? ")" + +monoid : or_monoid | min_monoid | max_monoid | sum_monoid +or_monoid : "(or)" +min_monoid : "(min" type_ ")" +max_monoid : "(max" type_ ")" +sum_monoid : "(sum" type_ ")" + +abstraction: "(" bindings formula ")" +bindings: "[" left_bindings ("|" right_bindings)? "]" +left_bindings: binding* +right_bindings: binding* +binding: SYMBOL "::" type_ + +formula: exists | reduce | conjunction | disjunction | not_ | ffi | atom | pragma | primitive | true | false | relatom | cast +exists: "(exists" bindings formula ")" +reduce: "(reduce" abstraction abstraction terms ")" +conjunction: "(and" formula* ")" +disjunction: "(or" formula* ")" +not_: "(not" formula ")" +ffi: "(ffi" name args terms ")" +atom: "(atom" relation_id term* ")" +relatom: "(relatom" name relterm* ")" +cast: "(cast" term term ")" +pragma: "(pragma" name term* ")" +true: "(true)" +false: "(false)" + +args: "(args" abstraction* ")" +terms: "(terms" term* ")" + +primitive: raw_primitive | eq | lt | lt_eq | gt | gt_eq | add | minus | multiply | divide +raw_primitive: "(primitive" name relterm* ")" +eq: "(=" term term ")" +lt: "(<" term term ")" +lt_eq: "(<=" term term ")" +gt: "(>" term term ")" +gt_eq: "(>=" term term ")" + +add: "(+" term term term ")" +minus: "(-" term term term ")" +multiply: "(*" term term term ")" +divide: "(/" term term term ")" + +relterm: specialized_value | term +term: var | constant +specialized_value: "#" value +var: SYMBOL +constant: value + +attrs: "(attrs" attribute* ")" +attribute: "(attribute" name constant* ")" + +fragment_id: ":" SYMBOL +relation_id: (":" SYMBOL) | UINT128 +name: ":" SYMBOL + +value: STRING | NUMBER | FLOAT | UINT128 | INT128 + | date | datetime | MISSING | DECIMAL | BOOLEAN + +type_ : TYPE_NAME | "(" TYPE_NAME value* ")" + +// The terminal symbols are sometimes ambiguous. We set explicit priorities to resolve them. +// SYMBOL.0 is the lowest priority, which has the effect that other string terminals act +// as keywords. +TYPE_NAME.1: "STRING" | "INT" | "FLOAT" | "UINT128" | "INT128" + | "DATE" | "DATETIME" | "MISSING" | "DECIMAL" | "BOOLEAN" + +SYMBOL.0: /[a-zA-Z_][a-zA-Z0-9_.-]*/ +MISSING.1: "missing" // Set a higher priority so so it's MISSING instead of SYMBOL +STRING: ESCAPED_STRING +NUMBER: /[-]?\\d+/ +INT128: /[-]?\\d+i128/ +UINT128: /0x[0-9a-fA-F]+/ +FLOAT.1: /[-]?\\d+\\.\\d+/ | "inf" | "nan" +DECIMAL.2: /[-]?\\d+\\.\\d+d\\d+/ +BOOLEAN.1: "true" | "false" // Set a higher priority so it's BOOLEAN instead of SYMBOL +date: "(date" NUMBER NUMBER NUMBER ")" +datetime: "(datetime" NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER? ")" + +config_dict: "{" config_key_value* "}" +config_key_value: ":" SYMBOL value + +COMMENT: /;;.*/ // Matches ;; followed by any characters except newline +%ignore /\\s+/ +%ignore COMMENT +%import common.ESCAPED_STRING -> ESCAPED_STRING +""" + +def construct_configure(config_dict, meta): + """Construct a Configure IR node from config dictionary.""" + # Construct IVMConfig + maintenance_level_value = config_dict.get("ivm.maintenance_level") + if maintenance_level_value: + maintenance_level = getattr(ir.MaintenanceLevel, maintenance_level_value.value.upper()) + else: + maintenance_level = ir.MaintenanceLevel.OFF + ivm_config = ir.IVMConfig(level=maintenance_level, meta=meta) + + # Get optimization level + optimization_level_value = config_dict.get("optimization_level") + if optimization_level_value: + optimization_level = getattr(ir.OptimizationLevel, optimization_level_value.value.upper()) + else: + optimization_level = ir.OptimizationLevel.DEFAULT + + # Get semantics_version + semantics_version_value = config_dict.get("semantics_version") + if semantics_version_value: + semantics_version = semantics_version_value.value + else: + semantics_version = 0 + + # Construct & return Configure + return ir.Configure( + semantics_version=semantics_version, + ivm_config=ivm_config, + optimization_level=optimization_level, + meta=meta, + ) + +def desugar_to_raw_primitive(name, terms): + """Convert primitive operators to raw primitive IR nodes.""" + # Convert terms to relterms + return ir.Primitive(name=name, terms=terms, meta=None) + +@v_args(meta=True) +class LQPTransformer(Transformer): + """Transformer that converts Lark parse tree to LQP IR nodes.""" + + def __init__(self, file: str): + self.file = file + self.id_to_debuginfo = {} + self._current_fragment_id = None + + def meta(self, meta): + return ir.SourceInfo(file=self.file, line=meta.line, column=meta.column) + + def start(self, meta, items): + return items[0] + + def TYPE_NAME(self, s): + return getattr(ir.TypeName, s.upper()) + + def type_(self, meta, items): + return ir.Type(type_name=items[0], parameters=items[1:], meta=self.meta(meta)) + + # + # Transactions + # + def transaction(self, meta, items): + if isinstance(items[0], ir.Configure): + configure = items[0] + if isinstance(items[1], ir.Sync): + sync = items[1] + epochs = items[2:] + else: + sync = None + epochs = items[1:] + elif isinstance(items[0], ir.Sync): + configure = construct_configure({}, self.meta(meta)) + sync = items[0] + epochs = items[1:] + else: + configure = construct_configure({}, self.meta(meta)) + sync = None + epochs = items + + return ir.Transaction(configure=configure, epochs=epochs, sync=sync, meta=self.meta(meta)) + + def configure(self, meta, items): + return construct_configure(items[0], self.meta(meta)) + + def epoch(self, meta, items): + kwargs = {k: v for k, v in items if v} # Filter out None values + return ir.Epoch(**kwargs, meta=self.meta(meta)) + + def writes(self, meta, items): + return ("writes", items) + + def reads(self, meta, items): + return ("reads", items) + + def write(self, meta, items): + return ir.Write(write_type=items[0], meta=self.meta(meta)) + + def define(self, meta, items): + return ir.Define(fragment=items[0], meta=self.meta(meta)) + + def undefine(self, meta, items): + return ir.Undefine(fragment_id=items[0], meta=self.meta(meta)) + + def context(self, meta, items): + return ir.Context(relations=items, meta=self.meta(meta)) + + def sync(self, meta, items): + return ir.Sync(fragments=items, meta=self.meta(meta)) + + def read(self, meta, items): + return ir.Read(read_type=items[0], meta=self.meta(meta)) + + def demand(self, meta, items): + return ir.Demand(relation_id=items[0], meta=self.meta(meta)) + + def output(self, meta, items): + if len(items) == 1: + return ir.Output(name=None, relation_id=items[0], meta=self.meta(meta)) + return ir.Output(name=items[0], relation_id=items[1], meta=self.meta(meta)) + + def export(self, meta, items): + return ir.Export(config=items[0], meta=self.meta(meta)) + + def export_csv_config(self, meta, items): + assert len(items) >= 2, "Export config must have at least columns and path" + + export_fields = {} + for i in items[2:]: + assert isinstance(i, dict) + for k, v in i.items(): + export_fields[k] = v.value + + return ir.ExportCSVConfig( + path=items[0], + data_columns=items[1], + **export_fields, + meta=self.meta(meta) + ) + + def export_columns(self, meta, items): + # items is a list of ExportCSVColumn objects + return items + + def export_column(self, meta, items): + return ir.ExportCSVColumn( + column_name=items[0], + column_data=items[1], + meta=self.meta(meta) + ) + + def export_path(self, meta, items): + return items[0] + + def abort(self, meta, items): + if len(items) == 1: + return ir.Abort(name=None, relation_id=items[0], meta=self.meta(meta)) + return ir.Abort(name=items[0], relation_id=items[1], meta=self.meta(meta)) + + # + # Logic + # + def fragment(self, meta, items): + fragment_id = items[0] + debug_info = ir.DebugInfo(id_to_orig_name=dict(self.id_to_debuginfo[fragment_id]), meta=self.meta(meta)) + self._current_fragment_id = None + return ir.Fragment(id=fragment_id, declarations=items[1:], debug_info=debug_info, meta=self.meta(meta)) + + def fragment_id(self, meta, items): + fragment_id = ir.FragmentId(id=items[0].encode(), meta=self.meta(meta)) + self._current_fragment_id = fragment_id # type: ignore + if fragment_id not in self.id_to_debuginfo: + self.id_to_debuginfo[fragment_id] = {} + return fragment_id + + def declaration(self, meta, items): + return items[0] + + def def_(self, meta, items): + name = items[0] + body, value_arity = items[1] + assert value_arity == 0, f"Defs should not have a value arity" + attrs = items[2] if len(items) > 2 else [] + return ir.Def(name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def constraint(self, meta, items): + return items[0] + + def functional_dependency(self, meta, items): + name = items[0] + guard, _ = items[1] + keys = items[2] + values = items[3] + return ir.FunctionalDependency( + name=name, + guard=guard, + keys=keys, + values=values, + meta=self.meta(meta) + ) + + def fd_keys(self, meta, items): + return items + + def fd_values(self, meta, items): + return items + + def data(self, meta, items): + return items[0] + + def rel_edb(self, meta, items): + name = items[0] + # items[1:] contains first the path strings, then the types + # We need to separate them - find where types start (they are ir.Type instances) + path = [] + types = [] + for item in items[1:]: + if isinstance(item, ir.Type): + types.append(item) + else: + path.append(item) + return ir.RelEDB( + target_id=name, + path=path, + types=types, + meta=self.meta(meta) + ) + + def betree_relation(self, meta, items): + name = items[0] + relation_info = items[1] + return ir.BeTreeRelation(name=name, relation_info=relation_info, meta=self.meta(meta)) + + def betree_info(self, meta, items): + key_types = items[0] + value_types = items[1] + + storage_config = {} + relation_locator = {} + for i in items[2:]: + assert isinstance(i, dict) + for k, v in i.items(): + # Extract raw value from ir.Value wrapper + raw_value = v.value if isinstance(v, ir.Value) else v + + if k.startswith("betree_config_"): + key = k.replace("betree_config_", "") + storage_config[key] = raw_value + elif k.startswith("betree_locator_"): + key = k.replace("betree_locator_", "") + # Convert string to bytes for inline_data + if key == "inline_data" and isinstance(raw_value, str): + raw_value = raw_value.encode('utf-8') + relation_locator[key] = raw_value + + storage_config = ir.BeTreeConfig(**storage_config, meta=self.meta(meta)) + + # Handle oneof: set missing location field to None + if 'root_pageid' not in relation_locator: + relation_locator['root_pageid'] = None + if 'inline_data' not in relation_locator: + relation_locator['inline_data'] = None + + relation_locator = ir.BeTreeLocator(**relation_locator, meta=self.meta(meta)) + + return ir.BeTreeInfo( + key_types=key_types, + value_types=value_types, + storage_config=storage_config, + relation_locator=relation_locator, + meta=self.meta(meta) + ) + + def key_types(self, meta, items): + return items + + def value_types(self, meta, items): + return items + + def csv_data(self, meta, items): + locator = items[0] + config = items[1] + columns = items[2] + asof = items[3] + return ir.CSVData( + locator=locator, + config=config, + columns=columns, + asof=asof, + meta=self.meta(meta) + ) + + def csv_locator(self, meta, items): + paths = [] + inline_data = None + + for item in items: + if isinstance(item, list): # paths + paths = item + elif isinstance(item, bytes): # inline_data + inline_data = item + + return ir.CSVLocator( + paths=paths, + inline_data=inline_data, + meta=self.meta(meta) + ) + + def csv_paths(self, meta, items): + return items # Return list of path strings + + def csv_inline_data(self, meta, items): + # Convert string to bytes + return items[0].encode('utf-8') + + def csv_config(self, meta, items): + config_dict = items[0] if items else {} + + # Extract CSV config fields with defaults + csv_config_dict: Dict[str, Any] = { + 'header_row': 1, + 'skip': 0, + 'new_line': '', + 'delimiter': ',', + 'quotechar': '"', + 'escapechar': '"', + 'comment': '', + 'missing_strings': [], + 'decimal_separator': '.', + 'encoding': 'utf-8', + 'compression': 'auto' + } + + for k, v in config_dict.items(): + if k.startswith('csv_'): + key = k.replace('csv_', '') + raw_value = v.value if isinstance(v, ir.Value) else v + + # Handle special cases for types + if key == 'missing_strings': + # If it's a single string, wrap it in a list + if isinstance(raw_value, str): + csv_config_dict[key] = [raw_value] + else: + csv_config_dict[key] = raw_value + else: + csv_config_dict[key] = raw_value + + return ir.CSVConfig(**csv_config_dict, meta=self.meta(meta)) + + def csv_columns(self, meta, items): + return items # Return list of CSVColumn + + def csv_column(self, meta, items): + column_name = items[0] + target_id = items[1] + types = items[2:] + return ir.CSVColumn( + column_name=column_name, + target_id=target_id, + types=types, + meta=self.meta(meta) + ) + + def csv_asof(self, meta, items): + return items[0] # Return the asof string + + def algorithm(self, meta, items): + return ir.Algorithm(global_=items[:-1], body=items[-1], meta=self.meta(meta)) + + def script(self, meta, items): + return ir.Script(constructs=items, meta=self.meta(meta)) + + def construct(self, meta, items): + return items[0] + + def loop(self, meta, items): + init = items[0] + script = items[1] + return ir.Loop(init=init, body=script, meta=self.meta(meta)) + + def init(self, meta, items): + return items + + def instruction(self, meta, items): + return items[0] + + def assign(self, meta, items): + name = items[0] + body, value_arity = items[1] + assert value_arity == 0, f"Assigns should not have a value arity" + attrs = items[2] if len(items) > 2 else [] + return ir.Assign(name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def upsert(self, meta, items): + name = items[0] + body, value_arity = items[1] + attrs = items[2] if len(items) > 2 else [] + return ir.Upsert(value_arity=value_arity, name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def break_(self, meta, items): + name = items[0] + body, value_arity = items[1] + assert value_arity == 0, f"Breaks should not have a value arity" + attrs = items[2] if len(items) > 2 else [] + return ir.Break(name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def monoid_def(self, meta, items): + monoid = items[0] + name = items[1] + body, value_arity = items[2] + attrs = items[3] if len(items) > 3 else [] + return ir.MonoidDef(value_arity=value_arity, monoid=monoid, name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def monus_def(self, meta, items): + monoid = items[0] + name = items[1] + body, value_arity = items[2] + attrs = items[3] if len(items) > 3 else [] + return ir.MonusDef(value_arity=value_arity, monoid=monoid, name=name, body=body, attrs=attrs, meta=self.meta(meta)) + + def monoid(self, meta, items): + return items[0] + + def or_monoid(self, meta, items): + return ir.OrMonoid(meta=meta) + + def min_monoid(self, meta, items): + return ir.MinMonoid(type=items[0], meta=meta) + + def max_monoid(self, meta, items): + return ir.MaxMonoid(type=items[0], meta=meta) + + def sum_monoid(self, meta, items): + return ir.SumMonoid(type=items[0], meta=meta) + + def abstraction(self, meta, items): + vars, arity = items[0] + return ir.Abstraction(vars=vars, value=items[1], meta=self.meta(meta)), arity + + def binding(self, meta, items): + name, rel_t = items + return (ir.Var(name=name, meta=self.meta(meta)), rel_t) + + def vars(self, meta, items): + return items + + def bindings(self, meta, items): + if len(items) == 1 : # Bindings do not indicate a value_arity + return items[0], 0 + else: + left = items[0] + right = items[1] + return left+right, len(right) + + def left_bindings(self, meta, items): + return items + + def right_bindings(self, meta, items): + return items + + def attrs(self, meta, items): + return items + + def formula(self, meta, items): + return items[0] + + def true(self, _, meta): + return ir.Conjunction(args=[], meta=self.meta(meta)) + + def false(self, _, meta): + return ir.Disjunction(args=[], meta=self.meta(meta)) + + def exists(self, meta, items): + vars, arity = items[0] + assert arity == 0, f"Exists should not have a value_arity" + # Create Abstraction for body directly here + body_abstraction = ir.Abstraction(vars=vars, value=items[1], meta=self.meta(meta)) + return ir.Exists(body=body_abstraction, meta=self.meta(meta)) + + def reduce(self, meta, items): + op, x = items[0] + body, y = items[1] + assert x == y == 0, f"Abstractions in Reduce should not have value arities" + return ir.Reduce(op=op, body=body, terms=items[2], meta=self.meta(meta)) + + def conjunction(self, meta, items): + return ir.Conjunction(args=items, meta=self.meta(meta)) + + def disjunction(self, meta, items): + return ir.Disjunction(args=items, meta=self.meta(meta)) + + def not_(self, meta, items): + return ir.Not(arg=items[0], meta=self.meta(meta)) + + def ffi(self, meta, items): + return ir.FFI(name=items[0], args=items[1], terms=items[2], meta=self.meta(meta)) + + def atom(self, meta, items): + return ir.Atom(name=items[0], terms=items[1:], meta=self.meta(meta)) + + def pragma(self, meta, items): + return ir.Pragma(name=items[0], terms=items[1:], meta=self.meta(meta)) + + def relatom(self, meta, items): + return ir.RelAtom(name=items[0], terms=items[1:], meta=self.meta(meta)) + + def cast(self, meta, items): + return ir.Cast(input=items[0], result=items[1], meta=self.meta(meta)) + + # + # Primitives + # + def primitive(self, meta, items): + if isinstance(items[0], ir.Formula): + return items[0] + raise TypeError(f"Unexpected primitive type: {type(items[0])}") + + def raw_primitive(self, meta, items): + return ir.Primitive(name=items[0], terms=items[1:], meta=self.meta(meta)) + + def _make_primitive(self, name_symbol, terms, meta): + # Convert name symbol to string if needed, assuming self.name handles it + name_str = self.name([name_symbol], meta) if isinstance(name_symbol, str) else name_symbol + return ir.Primitive(name=name_str, terms=terms, meta=self.meta(meta)) + + def eq(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_eq"]), items) + + def lt(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_lt_monotype"]), items) + + def lt_eq(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_lt_eq_monotype"]), items) + + def gt(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_gt_monotype"]), items) + + def gt_eq(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_gt_eq_monotype"]), items) + + def add(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_add_monotype"]), items) + + def minus(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_subtract_monotype"]), items) + + def multiply(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_multiply_monotype"]), items) + + def divide(self, meta, items): + return desugar_to_raw_primitive(self.name(meta, ["rel_primitive_divide_monotype"]), items) + + def args(self, meta, items): + return [item[0] for item in items] + + def terms(self, meta, items): + return items + + def relterm(self, meta, items): + return items[0] + + def term(self, meta, items): + return items[0] + + def var(self, meta, items): + return ir.Var(name=items[0], meta=self.meta(meta)) + + def constant(self, meta, items): + return items[0] + + def specialized_value(self, meta, items): + return ir.SpecializedValue(value=items[0], meta=self.meta(meta)) + + def name(self, meta, items): + return items[0] + + def attribute(self, meta, items): + return ir.Attribute(name=items[0], args=items[1:], meta=self.meta(meta)) + + def relation_id(self, meta, items): + ident = items[0] + if isinstance(ident, str): + # First 64 bits of SHA-256 as the id + id_val = int(hashlib.sha256(ident.encode()).hexdigest()[:16], 16) + result = ir.RelationId(id=id_val, meta=self.meta(meta)) + + # Store mapping in the current fragment's debug info + if self._current_fragment_id is not None: + self.id_to_debuginfo[self._current_fragment_id][result] = ident + return result + + elif isinstance(ident, ir.UInt128Value): + return ir.RelationId(id=ident.value, meta=self.meta(meta)) + + # + # Primitive values + # + def value(self, meta, items): + return ir.Value(value=items[0], meta=self.meta(meta)) + + def STRING(self, s): + return ast.literal_eval(s) + + def NUMBER(self, n): + return int(n) + + def FLOAT(self, f): + return float(f) + + def SYMBOL(self, sym): + return str(sym) + + def UINT128(self, u): + uint128_val = int(u, 16) + return ir.UInt128Value(value=uint128_val, meta=None) + + def INT128(self, u): + u = u[:-4] # Remove the 'i128' suffix + int128_val = int(u) + return ir.Int128Value(value=int128_val, meta=None) + + def MISSING(self, m): + return ir.MissingValue(meta=None) + + def DECIMAL(self, d): + # Decimal is a string like "123.456d12" where the last part after `d` is the + # precision, and the scale is the number of digits between the decimal point and `d` + parts = d.split('d') + if len(parts) != 2: + raise ValueError(f"Invalid decimal format: {d}") + scale = len(parts[0].split('.')[1]) + precision = int(parts[1]) + value = Decimal(parts[0]) + + return ir.DecimalValue(precision=precision, scale=scale, value=value, meta=None) + + def BOOLEAN(self, b): + return ir.BooleanValue(value=bool(b == "true"), meta=None) + + def date(self, meta, items): + # Date is in the format (date YYYY MM DD) + date_val = date(*items) + return ir.DateValue(value=date_val, meta=None) + + def datetime(self, meta, items): + # Date is in the format (datetime YYYY MM DD HH MM SS [MS]) + datetime_val = datetime(*items) + return ir.DateTimeValue(value=datetime_val, meta=None) + + def config_dict(self, meta, items): + # items is a list of key-value pairs + config = {} + for (k, v) in items: + config[k] = v + return config + + def config_key_value(self, meta, items): + assert len(items) == 2 + return (items[0], items[1]) + +# LALR(1) is significantly faster than Earley for parsing, especially on larger inputs. It +# uses a precomputed parse table, reducing runtime complexity to O(n) (linear in input +# size), whereas Earley is O(n³) in the worst case (though often O(n²) or better for +# practical grammars). The LQP grammar is relatively complex but unambiguous, making +# LALR(1)'s speed advantage appealing for a CLI tool where quick parsing matters. +lark_parser = Lark(grammar, parser="lalr", propagate_positions=True) + +def parse_lqp(file: str, text: str) -> ir.LqpNode: + """Parse LQP text and return an IR node that can be converted to protocol buffers.""" + tree = lark_parser.parse(text) + transformer = LQPTransformer(file) + result = transformer.transform(tree) + return result diff --git a/python-tools/src/lqp/print.py b/python-tools/src/lqp/print.py new file mode 100644 index 00000000..82905cfc --- /dev/null +++ b/python-tools/src/lqp/print.py @@ -0,0 +1,753 @@ +import dataclasses + +from abc import ABC, abstractmethod +from typing import Union, Sequence, Dict, List, Any + +from colorama import Style, Fore +from enum import Enum + +from . import ir + +class StyleConfig(ABC): + @abstractmethod + def SIND(self, ) -> str: pass + + @abstractmethod + def LPAREN(self, ) -> str: pass + @abstractmethod + def RPAREN(self, ) -> str: pass + + @abstractmethod + def LBRACKET(self, ) -> str: pass + @abstractmethod + def RBRACKET(self, ) -> str: pass + + # String of level indentations for LLQP. + @abstractmethod + def indentation(self, level: int) -> str: pass + + # Styled keyword x. + @abstractmethod + def kw(self, x: str) -> str: pass + + # Styled user provided name, e.g. variables. + @abstractmethod + def uname(self, x: str) -> str: pass + + # Styled type annotation, e.g. ::INT. + @abstractmethod + def type_anno(self, x: str) -> str: pass + +# Some basic components and how they are to be printed. +class Unstyled(StyleConfig): + # Single INDentation. + def SIND(self, ): return " " + + def LPAREN(self, ): return "(" + def RPAREN(self, ): return ")" + + def LBRACKET(self, ): return "[" + def RBRACKET(self, ): return "]" + + # String of level indentations for LLQP. + def indentation(self, level: int) -> str: + return self.SIND() * level + + # Styled keyword x. + def kw(self, x: str) -> str: + return x + + # Styled user provided name, e.g. variables. + def uname(self, x: str) -> str: + return x + + # Styled type annotation, e.g. ::INT. + def type_anno(self, x: str) -> str: + return x + +class Styled(StyleConfig): + def SIND(self, ): return " " + + def LPAREN(self, ): return f"{Style.DIM}({Style.RESET_ALL}" + def RPAREN(self, ): return f"{Style.DIM}){Style.RESET_ALL}" + + def LBRACKET(self, ): return f"{Style.DIM}[{Style.RESET_ALL}" + def RBRACKET(self, ): return f"{Style.DIM}]{Style.RESET_ALL}" + + def indentation(self, level: int) -> str: + return self.SIND() * level + + def kw(self, x: str) -> str: + return f"{Fore.YELLOW}{x}{Style.RESET_ALL}" + + def uname(self, x: str) -> str: + return f"{Fore.WHITE}{x}{Style.RESET_ALL}" + + # Styled type annotation, e.g. ::INT. + def type_anno(self, x: str) -> str: + return f"{Style.DIM}{x}{Style.RESET_ALL}" + +class PrettyOptions(Enum): + STYLED = 1, + PRINT_NAMES = 2, + PRINT_DEBUG = 3, + PRINT_CSV_FILENAME = 4 # Useful for snapshot testing with generated CSV filenames + + def __str__(self): + return option_to_key[self] + +option_to_key = { + PrettyOptions.STYLED: "styled", + PrettyOptions.PRINT_NAMES: "print_names", + PrettyOptions.PRINT_DEBUG: "print_debug", + PrettyOptions.PRINT_CSV_FILENAME: "print_csv_filename" +} + +option_to_default = { + PrettyOptions.STYLED: False, + PrettyOptions.PRINT_NAMES: False, + PrettyOptions.PRINT_DEBUG: True, + PrettyOptions.PRINT_CSV_FILENAME: True +} + +# Used for precise testing +ugly_config = { + str(PrettyOptions.STYLED): False, + str(PrettyOptions.PRINT_NAMES): False, + str(PrettyOptions.PRINT_DEBUG): True, + str(PrettyOptions.PRINT_CSV_FILENAME): True +} + +# Used for humans +pretty_config = { + str(PrettyOptions.STYLED): True, + str(PrettyOptions.PRINT_NAMES): True, + str(PrettyOptions.PRINT_DEBUG): False, + str(PrettyOptions.PRINT_CSV_FILENAME): True +} + +def style_config(options: Dict) -> StyleConfig: + if has_option(options, PrettyOptions.STYLED): + return Styled() + else: + return Unstyled() + +# Call to_str on all nodes, each of which with indent_level, separating them +# by delim. +def list_to_str(nodes: Sequence[Union[ir.LqpNode, ir.Type, ir.Value, ir.SpecializedValue, int, str, float]], indent_level: int, delim: str, options: Dict, debug_info: Dict = {}) -> str: + return delim.join(map(lambda n: to_str(n, indent_level, options, debug_info), nodes)) + +# Produces "(terms term1 term2 ...)" (all on one line) indented at indent_level. +def terms_to_str(terms: Sequence[Union[ir.RelTerm, ir.SpecializedValue]], indent_level: int, options: Dict, debug_info: Dict = {}) -> str: + # Default to true for styled. + conf = style_config(options) + + ind = conf.indentation(indent_level) + + lqp = "" + if len(terms) == 0: + lqp = f"{ind}{conf.LPAREN()}{conf.kw('terms')}{conf.RPAREN()}" + else: + lqp = f"{ind}{conf.LPAREN()}{conf.kw('terms')} {list_to_str(terms, 0, ' ', options, debug_info)}{conf.RPAREN()}" + + return lqp + +# Produces +# { :key1 value1 +# :key2 value2 +# ... } +def config_dict_to_str(config: Dict[str, Any], indent_level: int, options: Dict) -> str: + conf = style_config(options) + ind = conf.indentation(indent_level) + + if len(config) == 0: + return f"{ind}{{}}" + + config_str = ind + "{" + conf.SIND()[1:] + for i, (k, v) in enumerate(sorted(config.items())): + if i > 0: + config_str += f"\n{ind}{conf.SIND()}" + config_str += f":{str(k)} {to_str(v, 0, options)}" + + config_str += "}" + + return config_str + +def program_to_str(node: ir.Transaction, options: Dict = {}) -> str: + conf = style_config(options) + s = conf.indentation(0) + conf.LPAREN() + conf.kw("transaction") + + config_dict: Dict[str, Union[str, int]] = {} + config = node.configure + config_dict["semantics_version"] = config.semantics_version + if config.ivm_config.level != ir.MaintenanceLevel.UNSPECIFIED: + config_dict["ivm.maintenance_level"] = config.ivm_config.level.name.lower() + if config.optimization_level != ir.OptimizationLevel.UNSPECIFIED: + config_dict["optimization_level"] = config.optimization_level.name.lower() + + s += "\n" + conf.indentation(1) + conf.LPAREN() + conf.kw("configure") + "\n" + s += config_dict_to_str(config_dict, 2, options) + s += conf.RPAREN() + + if node.sync is not None: + s += "\n" + conf.indentation(1) + conf.LPAREN() + conf.kw("sync") + if len(node.sync.fragments) != 0: + s += " " + list_to_str(node.sync.fragments, 0, " ", options) + s += conf.RPAREN() + + for epoch in node.epochs: + s += "\n" + conf.indentation(1) + conf.LPAREN() + conf.kw("epoch") + section_strs: List[str] = [] + def build_section(keyword: str, items_list: Sequence[Union[ir.LqpNode, ir.Type, ir.Value, ir.SpecializedValue]], debug_info: Dict = {}) -> Union[str, None]: + if not items_list: + return None + sec_s = "\n" + conf.indentation(2) + conf.LPAREN() + conf.kw(keyword) + "\n" + sec_s += list_to_str(items_list, 3, "\n", options, debug_info) + conf.RPAREN() + return sec_s + writes_s = build_section("writes", epoch.writes) + if writes_s: section_strs.append(writes_s) + reads_s = build_section("reads", epoch.reads, _collect_debug_infos(node)) + if reads_s: section_strs.append(reads_s) + s += "".join(section_strs) + s += conf.RPAREN() + s += conf.RPAREN() + + if has_option(options, PrettyOptions.PRINT_DEBUG): + s += _debug_str(node) + else: + # Debug str already contains a trailing newline, so add one if we don't print debug + s += "\n" + + return s + +def _debug_str(node: ir.LqpNode) -> str: + debug_infos = _collect_debug_infos(node) + if len(debug_infos) != 0: + debug_str: str = "\n\n" + debug_str += ";; Debug information\n" + debug_str += ";; -----------------------\n" + debug_str += ";; Original names\n" + for (rid, name) in debug_infos.items(): + debug_str += f";; \t ID `0x{rid.id:x}` -> `{name}`\n" + return debug_str + else: return "" + +def _collect_debug_infos(node: ir.LqpNode) -> Dict[ir.RelationId, str]: + debug_infos: Dict = {} + if isinstance(node, ir.DebugInfo): + debug_infos = node.id_to_orig_name | debug_infos + else: + if isinstance(node, ir.LqpNode): + for field_info in dataclasses.fields(type(node)): + debug_infos = _collect_debug_infos(getattr(node, field_info.name)) | debug_infos + elif isinstance(node, (list, tuple)): + for elt in node: + debug_infos = _collect_debug_infos(elt) | debug_infos + return debug_infos + +def to_str(node: Union[ir.LqpNode, ir.Type, ir.Value, ir.SpecializedValue, int, str, float], indent_level: int, options: Dict = {}, debug_info: Dict = {}) -> str: + conf = style_config(options) + + ind = conf.indentation(indent_level) + lqp = "" + + if isinstance(node, ir.Def): + lqp += ind + conf.LPAREN() + conf.kw("def") + " " + to_str(node.name, 0, options, debug_info) + "\n" + lqp += to_str(node.body, indent_level + 1, options, debug_info) + if len(node.attrs) == 0: + lqp += f"{conf.RPAREN()}" + else: + lqp += "\n" + lqp += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("attrs") + "\n" + lqp += list_to_str(node.attrs, indent_level + 2, "\n", options, debug_info) + lqp += f"{conf.RPAREN()}{conf.RPAREN()}" + + elif isinstance(node, ir.Constraint): + if isinstance(node, ir.FunctionalDependency): + lqp += ind + conf.LPAREN() + conf.kw("functional_dependency") + " " + lqp += to_str(node.name, 0, options, debug_info) + "\n" + lqp += to_str(node.guard, indent_level + 1, options, debug_info) + "\n" + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("keys") + " " \ + + " ".join([to_str(var, 0, options, debug_info) for var in node.keys]) \ + + conf.RPAREN() + "\n" + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("values") + " " \ + + " ".join([to_str(var, 0, options, debug_info) for var in node.values]) \ + + conf.RPAREN() \ + + conf.RPAREN() + else: + raise NotImplementedError(f"to_str not implemented for constraint type {type(node)}.") + + elif isinstance(node, ir.Algorithm): + lqp += ind + conf.LPAREN() + conf.kw("algorithm") + # Print global_ + if len(node.global_) > 4: + lqp += "\n" + lqp += ind + conf.SIND() + list_to_str(node.global_, indent_level + 2, "\n", options, debug_info) + lqp += "\n" + else: + lqp += " " + lqp += list_to_str(node.global_, 0, " ", options, debug_info) + "\n" + lqp += to_str(node.body, indent_level + 1, options, debug_info) + lqp += conf.RPAREN() + + elif isinstance(node, ir.RelEDB): + lqp += ind + conf.LPAREN() + conf.kw("rel_edb") + " " + to_str(node.target_id, 0, options, debug_info) + lqp += " " + conf.LBRACKET() + if len(node.path) > 0: + lqp += list_to_str(node.path, 0, " ", options, debug_info) + lqp += conf.RBRACKET() + lqp += " " + conf.LBRACKET() + if len(node.types) > 0: + lqp += list_to_str(node.types, 0, " ", options, debug_info) + lqp += conf.RBRACKET() + lqp += conf.RPAREN() + + elif isinstance(node, ir.BeTreeRelation): + lqp += ind + conf.LPAREN() + conf.kw("betree_relation") + " " + to_str(node.name, 0, options, debug_info) + "\n" + lqp += to_str(node.relation_info, indent_level + 1, options, debug_info) + lqp += conf.RPAREN() + + elif isinstance(node, ir.BeTreeInfo): + lqp += ind + conf.LPAREN() + conf.kw("betree_info") + "\n" + # Print key_types + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("key_types") + if len(node.key_types) > 0: + lqp += " " + list_to_str(node.key_types, 0, " ", options, debug_info) + lqp += conf.RPAREN() + "\n" + # Print value_types + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("value_types") + if len(node.value_types) > 0: + lqp += " " + list_to_str(node.value_types, 0, " ", options, debug_info) + lqp += conf.RPAREN() + "\n" + # Print config_dict combining storage_config and relation_locator + config_dict: dict[str, Any] = {} + config_dict['betree_config_epsilon'] = node.storage_config.epsilon + config_dict['betree_config_max_pivots'] = node.storage_config.max_pivots + config_dict['betree_config_max_deltas'] = node.storage_config.max_deltas + config_dict['betree_config_max_leaf'] = node.storage_config.max_leaf + # Handle oneof: only print the location field that is set + if node.relation_locator.root_pageid is not None: + config_dict['betree_locator_root_pageid'] = node.relation_locator.root_pageid + if node.relation_locator.inline_data is not None: + # Convert bytes back to string for printing + inline_data_str = node.relation_locator.inline_data.decode('utf-8') + config_dict['betree_locator_inline_data'] = inline_data_str + config_dict['betree_locator_element_count'] = node.relation_locator.element_count + config_dict['betree_locator_tree_height'] = node.relation_locator.tree_height + lqp += config_dict_to_str(config_dict, indent_level + 1, options) + lqp += conf.RPAREN() + + elif isinstance(node, ir.CSVData): + lqp += ind + conf.LPAREN() + conf.kw("csv_data") + "\n" + lqp += to_str(node.locator, indent_level + 1, options, debug_info) + "\n" + lqp += to_str(node.config, indent_level + 1, options, debug_info) + "\n" + # Print columns + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("columns") + "\n" + lqp += list_to_str(node.columns, indent_level + 2, "\n", options, debug_info) + lqp += conf.RPAREN() + "\n" + # Print asof + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("asof") + " " + to_str(node.asof, 0, options, debug_info) + conf.RPAREN() + lqp += conf.RPAREN() + + elif isinstance(node, ir.CSVLocator): + lqp += ind + conf.LPAREN() + conf.kw("csv_locator") + "\n" + # Print paths or inline_data (mutually exclusive) + if node.paths: + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("paths") + if len(node.paths) > 0: + lqp += " " + list_to_str(node.paths, 0, " ", options, debug_info) + lqp += conf.RPAREN() + elif node.inline_data is not None: + # Convert bytes back to string for printing + inline_data_str = node.inline_data.decode('utf-8') + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("inline_data") + " " + to_str(inline_data_str, 0, options, debug_info) + conf.RPAREN() + lqp += conf.RPAREN() + + elif isinstance(node, ir.CSVConfig): + config_dict: dict[str, Any] = {} + # Always include all config values + config_dict['csv_header_row'] = node.header_row + config_dict['csv_skip'] = node.skip + if node.new_line != '': + config_dict['csv_new_line'] = node.new_line + config_dict['csv_delimiter'] = node.delimiter + config_dict['csv_quotechar'] = node.quotechar + config_dict['csv_escapechar'] = node.escapechar + if node.comment != '': + config_dict['csv_comment'] = node.comment + if node.missing_strings: + # For lists, we only support single string values in config dicts for now + # If there's only one missing string, output it as a single string + # Otherwise, we'll need to output just the first one (this is a limitation) + if len(node.missing_strings) == 1: + config_dict['csv_missing_strings'] = node.missing_strings[0] + else: + # For multiple missing strings, join them or just use first + # This is a temporary workaround - we may need a better solution + config_dict['csv_missing_strings'] = node.missing_strings[0] + config_dict['csv_decimal_separator'] = node.decimal_separator + config_dict['csv_encoding'] = node.encoding + config_dict['csv_compression'] = node.compression + + lqp += ind + conf.LPAREN() + conf.kw("csv_config") + if len(config_dict) > 0: + lqp += "\n" + lqp += config_dict_to_str(config_dict, indent_level + 1, options) + lqp += conf.RPAREN() + + elif isinstance(node, ir.CSVColumn): + lqp += ind + conf.LPAREN() + conf.kw("column") + " " + lqp += to_str(node.column_name, 0, options, debug_info) + " " + lqp += to_str(node.target_id, 0, options, debug_info) + lqp += " " + conf.LBRACKET() + if len(node.types) > 0: + lqp += list_to_str(node.types, 0, " ", options, debug_info) + lqp += conf.RBRACKET() + lqp += conf.RPAREN() + + elif isinstance(node, ir.Script): + lqp += ind + conf.LPAREN() + conf.kw("script") + "\n" + lqp += list_to_str(node.constructs, indent_level + 1, "\n", options, debug_info) + lqp += conf.RPAREN() + + elif isinstance(node, ir.Loop): + lqp += ind + conf.LPAREN() + conf.kw("loop") + "\n" + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("init") + if len(node.init) > 0: + lqp += "\n" + lqp += list_to_str(node.init, indent_level + 2, "\n", options, debug_info) + lqp += conf.RPAREN() + "\n" + lqp += to_str(node.body, indent_level + 1, options, debug_info) + lqp += conf.RPAREN() + + elif isinstance(node, (ir.Assign, ir.Break)): + if isinstance(node, ir.Assign): + s = "assign" + elif isinstance(node, ir.Break): + s = "break" + lqp += ind + conf.LPAREN() + conf.kw(s) + " " + to_str(node.name, 0, options, debug_info) + "\n" + lqp += to_str(node.body, indent_level + 1, options, debug_info) + if len(node.attrs) == 0: + lqp += f"{conf.RPAREN()}" + else: + lqp += "\n" + lqp += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("attrs") + "\n" + lqp += list_to_str(node.attrs, indent_level + 2, "\n", options, debug_info) + lqp += f"{conf.RPAREN()}{conf.RPAREN()}" + + elif isinstance(node, ir.Upsert): + lqp += ind + conf.LPAREN() + conf.kw("upsert") + " " + to_str(node.name, 0, options, debug_info) + "\n" + body = node.body + if node.value_arity == 0: + lqp += to_str(body, indent_level + 1, options, debug_info) + else: # We need a different printing mechanism + partition = len(body.vars)-node.value_arity + lvars, rvars = body.vars[:partition], body.vars[partition:] + lqp += ind + conf.indentation(1) + conf.LPAREN() + conf.LBRACKET() + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 2, options, debug_info), lvars)) + lqp += " | " + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 2, options, debug_info), rvars)) + lqp += conf.RBRACKET() + "\n" + lqp += f"{to_str(body.value, indent_level + 2, options, debug_info)}{conf.RPAREN()}" + if len(node.attrs) == 0: + lqp += f"{conf.RPAREN()}" + else: + lqp += "\n" + lqp += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("attrs") + "\n" + lqp += list_to_str(node.attrs, indent_level + 2, "\n", options, debug_info) + lqp += f"{conf.RPAREN()}{conf.RPAREN()}" + + elif isinstance(node, (ir.MonoidDef, ir.MonusDef)): + s = "monoid" if isinstance(node, ir.MonoidDef) else "monus" + lqp += ind + conf.LPAREN() + conf.kw(s) + " " \ + + to_str(node.monoid, 0, options, debug_info) + " " \ + + to_str(node.name, 0, options, debug_info) + "\n" + body = node.body + if node.value_arity == 0: + lqp += to_str(body, indent_level + 1, options, debug_info) + else: + partition = len(body.vars)-node.value_arity + lvars, rvars = body.vars[:partition], body.vars[partition:] + lqp += ind + conf.indentation(1) + conf.LPAREN() + conf.LBRACKET() + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 2, options, debug_info), lvars)) + lqp += " | " + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 2, options, debug_info), rvars)) + lqp += conf.RBRACKET() + "\n" + lqp += f"{to_str(body.value, indent_level + 2, options, debug_info)}{conf.RPAREN()}" + if len(node.attrs) == 0: + lqp += f"{conf.RPAREN()}" + else: + lqp += "\n" + lqp += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("attrs") + "\n" + lqp += list_to_str(node.attrs, indent_level + 2, "\n", options, debug_info) + lqp += f"{conf.RPAREN()}{conf.RPAREN()}" + + elif isinstance(node, ir.OrMonoid): + lqp += "(or)" + + elif isinstance(node, ir.MinMonoid): + lqp += "(min " + to_str(node.type, 0, options, debug_info) + ")" + + elif isinstance(node, ir.MaxMonoid): + lqp += "(max " + to_str(node.type, 0, options, debug_info) + ")" + + elif isinstance(node, ir.SumMonoid): + lqp += "(sum " + to_str(node.type, 0, options, debug_info) + ")" + + elif isinstance(node, ir.Type): + if len(node.parameters) == 0: + lqp += conf.type_anno(str(node.type_name)) + else: + lqp += conf.LPAREN() + conf.type_anno(str(node.type_name)) + " " + lqp += " ".join([to_str(x, 0, options, debug_info) for x in node.parameters]) + lqp += conf.RPAREN() + elif isinstance(node, ir.Abstraction): + lqp += ind + conf.LPAREN() + conf.LBRACKET() + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 1, options, debug_info), node.vars)) + lqp += conf.RBRACKET() + "\n" + lqp += f"{to_str(node.value, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Exists): + lqp += ind + conf.LPAREN() + conf.kw("exists") + " " + conf.LBRACKET() + lqp += " ".join(map(lambda v: conf.uname(v[0].name) \ + + conf.type_anno("::") + to_str(v[1], indent_level + 1, options, debug_info), node.body.vars)) + lqp += conf.RBRACKET() + "\n" + lqp += to_str(node.body.value, indent_level + 1, options, debug_info) + conf.RPAREN() + + elif isinstance(node, ir.Reduce): + lqp += ind + conf.LPAREN() + conf.kw("reduce") + "\n" + lqp += to_str(node.op, indent_level + 1, options, debug_info) + "\n" + lqp += to_str(node.body, indent_level + 1, options, debug_info) + "\n" + lqp += f"{terms_to_str(node.terms, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Conjunction): + if len(node.args) == 0: + lqp += ind + conf.LPAREN() + conf.kw("and") + conf.RPAREN() + else: + lqp += ind + conf.LPAREN() + conf.kw("and") + "\n" + lqp += list_to_str(node.args, indent_level + 1, "\n", options, debug_info) + conf.RPAREN() + + elif isinstance(node, ir.Disjunction): + if len(node.args) == 0: + lqp += ind + conf.LPAREN() + conf.kw("or") + conf.RPAREN() + else: + lqp += ind + conf.LPAREN() + conf.kw("or") + "\n" + lqp += list_to_str(node.args, indent_level + 1, "\n", options, debug_info) + conf.RPAREN() + + elif isinstance(node, ir.Not): + lqp += ind + conf.LPAREN() + conf.kw("not") + "\n" + lqp += f"{to_str(node.arg, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.FFI): + lqp += ind + conf.LPAREN() + conf.kw("ffi") + " " + ":" + node.name + "\n" + lqp += ind + conf.SIND() + conf.LPAREN() + conf.kw("args") + "\n" + lqp += list_to_str(node.args, indent_level + 2, "\n", options, debug_info) + lqp += conf.RPAREN() + "\n" + lqp += f"{terms_to_str(node.terms, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Atom): + if len(node.terms) > 4: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('atom')} {to_str(node.name, 0, options, debug_info)}\n" + lqp += list_to_str(node.terms, indent_level + 1, "\n", options, debug_info) + conf.RPAREN() + else: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('atom')} {to_str(node.name, 0, options, debug_info)} {list_to_str(node.terms, 0, ' ', options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Pragma): + terms = f"{list_to_str(node.terms, 0, ' ', options, debug_info)}" + lqp += f"{ind}{conf.LPAREN()}{conf.kw('pragma')} :{conf.uname(node.name)} {terms}{conf.RPAREN()}" + + elif isinstance(node, ir.Primitive): + if len(node.terms) > 4: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('primitive')} :{conf.uname(node.name)}\n" + lqp += list_to_str(node.terms, indent_level + 1, "\n", options, debug_info) + conf.RPAREN() + else: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('primitive')} :{conf.uname(node.name)} {list_to_str(node.terms, 0, ' ', options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.RelAtom): + if len(node.terms) > 4: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('relatom')} :{node.name}\n" + lqp += list_to_str(node.terms, indent_level + 1, "\n", options, debug_info) + conf.RPAREN() + else: + lqp += f"{ind}{conf.LPAREN()}{conf.kw('relatom')} :{node.name} {list_to_str(node.terms, 0, ' ', options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Cast): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('cast')} {to_str(node.input, 0, options, debug_info)} {to_str(node.result, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Var): + lqp += f"{ind}{conf.uname(node.name)}" + + elif isinstance(node, ir.Value): + lqp += to_str(node.value, indent_level, options, debug_info) + + elif isinstance(node, str): + # Escape special characters but preserve UTF-8 + escaped = node.replace('\\', '\\\\') + escaped = escaped.replace('"', '\\"') + escaped = escaped.replace('\n', '\\n') + escaped = escaped.replace('\r', '\\r') + escaped = escaped.replace('\t', '\\t') + lqp += ind + '"' + escaped + '"' + elif isinstance(node, ir.UInt128Value): + lqp += f"{ind}{hex(node.value)}" + elif isinstance(node, ir.Int128Value): + lqp += f"{ind}{node.value}i128" + elif isinstance(node, ir.MissingValue): + lqp += f"{ind}missing" + elif isinstance(node, ir.DecimalValue): + _, _, exponent = node.value.as_tuple() + assert isinstance(exponent, int) + # Format the decimal to have the correct scale + lqp += f"{ind}{node.value:.{node.scale}f}d{node.precision}" + elif isinstance(node, ir.DateValue): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('date')} {node.value.year} {node.value.month} {node.value.day}{conf.RPAREN()}" + elif isinstance(node, ir.DateTimeValue): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('datetime')} {node.value.year} {node.value.month} {node.value.day} {node.value.hour} {node.value.minute} {node.value.second} {node.value.microsecond}{conf.RPAREN()}" + + elif isinstance(node, (int, float)): + lqp += f"{ind}{str(node)}" + + elif isinstance(node, ir.BooleanValue): + if node.value: + lqp += f"{ind}true" + else: + lqp += f"{ind}false" + + elif isinstance(node, ir.SpecializedValue): + lqp += "#" + to_str(node.value, 0, {}, {}) + + elif isinstance(node, ir.Attribute): + args_str = list_to_str(node.args, 0, ' ', options, debug_info) + space = " " if args_str else "" + lqp += f"{ind}{conf.LPAREN()}{conf.kw('attribute')} :{node.name}{space}{args_str}{conf.RPAREN()}" + + elif isinstance(node, ir.RelationId): + name = id_to_name(options, debug_info, node) + lqp += f"{ind}{str(conf.uname(name))}" + + elif isinstance(node, ir.Write): + # Delegate to the specific write type + lqp += to_str(node.write_type, indent_level, options, debug_info) + + elif isinstance(node, ir.Define): + lqp += ind + conf.LPAREN() + conf.kw("define") + "\n" + to_str(node.fragment, indent_level + 1, options, debug_info) + conf.RPAREN() + + elif isinstance(node, ir.Undefine): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('undefine')} {to_str(node.fragment_id, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Context): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('context')} {list_to_str(node.relations, 0, ' ', options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.FragmentId): + lqp += f"{ind}:{conf.uname(node.id.decode())}" + + elif isinstance(node, ir.Read): + # Delegate to the specific read type + lqp += to_str(node.read_type, indent_level, options, debug_info) + + elif isinstance(node, ir.Demand): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('demand')} {to_str(node.relation_id, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Output): + name_str = f":{conf.uname(node.name)} " if node.name else "" + lqp += f"{ind}{conf.LPAREN()}{conf.kw('output')} {name_str}{to_str(node.relation_id, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Export): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('export')}\n{to_str(node.config, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.ExportCSVConfig): + def line(kw: str, body: str) -> str: + return f"{ind}{conf.SIND()}{conf.LPAREN()}{conf.kw(kw)} {body}{conf.RPAREN()}" + + def line_conf_f(kw: str, field: Union[int, str]) -> str: + return line(kw, to_str(field, 0, options, debug_info)) + + lqp += f"{ind}{conf.LPAREN()}{conf.kw('export_csv_config')}\n" + + if has_option(options, PrettyOptions.PRINT_CSV_FILENAME): + lqp += line_conf_f('path', node.path) + "\n" + else: + lqp += line_conf_f('path', '') + "\n" + lqp += line('columns', list_to_str(node.data_columns, 0, " ", options, debug_info)) + "\n" + + config_dict: dict[str, Any] = {} + config_dict['partition_size'] = node.partition_size if node.partition_size is not None else 0 + config_dict['compression'] = node.compression if node.compression is not None else "" #type: ignore + config_dict['syntax_header_row'] = node.syntax_header_row if node.syntax_header_row is not None else 1 + config_dict['syntax_missing_string'] = node.syntax_missing_string if node.syntax_missing_string is not None else "" #type: ignore + config_dict['syntax_delim'] = node.syntax_delim if node.syntax_delim is not None else "," #type: ignore + config_dict['syntax_quotechar'] = node.syntax_quotechar if node.syntax_quotechar is not None else '"' #type: ignore + config_dict['syntax_escapechar'] = node.syntax_escapechar if node.syntax_escapechar is not None else '\\' #type: ignore + + lqp += config_dict_to_str(config_dict, indent_level + 1, options) #type: ignore + lqp += f"{conf.RPAREN()}" + + elif isinstance(node, ir.ExportCSVColumn): + lqp += f"{ind}{conf.LPAREN()}{conf.kw('column')} {to_str(node.column_name, 0, options, debug_info)} {to_str(node.column_data, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Abort): + name_str = f":{conf.uname(node.name)} " if node.name else "" + lqp += f"{ind}{conf.LPAREN()}{conf.kw('abort')} {name_str}{to_str(node.relation_id, 0, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.WhatIf): + branch_str = f":{conf.uname(node.branch)} " if node.branch else "" + lqp += f"{ind}{conf.LPAREN()}{conf.kw('what_if')} {branch_str}{to_str(node.epoch, indent_level + 1, options, debug_info)}{conf.RPAREN()}" + + elif isinstance(node, ir.Epoch): + # Epoch is handled within program_to_str, but might be called directly for WhatIf + # This case should ideally not be hit directly by list_to_str for epoch.local_writes etc. + # But if it is, it should print its contents. + epoch_content = "" + if len(node.writes) > 0: + epoch_content += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("writes") + "\n" + epoch_content += list_to_str(node.writes, indent_level + 2, "\n", options, debug_info) + epoch_content += conf.RPAREN() + "\n" + if len(node.reads) > 0: + epoch_content += conf.indentation(indent_level + 1) + conf.LPAREN() + conf.kw("reads") + "\n" + epoch_content += list_to_str(node.reads, indent_level + 2, "\n", options, debug_info) + epoch_content += conf.RPAREN() + "\n" + lqp += ind + conf.LPAREN() + conf.kw("epoch") + "\n" + epoch_content + conf.RPAREN() + + elif isinstance(node, ir.Fragment): + lqp += fragment_to_str(node, indent_level, debug_info, options) + + else: + raise NotImplementedError(f"to_str not implemented for {type(node)}.") + + return lqp + +def fragment_to_str(node: ir.Fragment, indent_level: int, debug_info: Dict, options: Dict = {}) -> str: + conf = style_config(options) + ind = conf.indentation(indent_level) + debug_info = node.debug_info.id_to_orig_name | debug_info + declarations_portion = list_to_str(node.declarations, indent_level + 1, "\n", options, debug_info) + return \ + ind + conf.LPAREN() + conf.kw("fragment") + " " + to_str(node.id, 0, options, debug_info) + "\n" + \ + declarations_portion + \ + conf.RPAREN() + +def to_string(node: ir.LqpNode, options: Dict = {}) -> str: + if isinstance(node, ir.Transaction): + return program_to_str(node, options) + elif isinstance(node, ir.Fragment): + return fragment_to_str(node, 0, {}, options) + else: + raise NotImplementedError(f"to_string not implemented for top-level node type {type(node)}.") + +def id_to_name(options: Dict, debug_info: Dict, rid: ir.RelationId) -> str: + if not has_option(options, PrettyOptions.PRINT_NAMES): + return f"0x{rid.id:x}" + if len(debug_info) == 0: + return f"0x{rid.id:x}" + if rid not in debug_info: + # The relation ID may be missing from the debug info if it was never defined. But it + # is still valid and should be treated as empty. + return f"0x{rid.id:x}" + return ":"+debug_info.get(rid, "") + +def has_option(options: Dict, opt: PrettyOptions) -> bool: + return options.get(option_to_key[opt], option_to_default[opt]) diff --git a/python-tools/src/lqp/proto/v1/transactions_pb2.py b/python-tools/src/lqp/proto/v1/transactions_pb2.py new file mode 100644 index 00000000..3f3b0d46 --- /dev/null +++ b/python-tools/src/lqp/proto/v1/transactions_pb2.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: relationalai/lqp/v1/transactions.proto +# Protobuf Python Version: 4.25.6 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from lqp.proto.v1 import fragments_pb2 as relationalai_dot_lqp_dot_v1_dot_fragments__pb2 +from lqp.proto.v1 import logic_pb2 as relationalai_dot_lqp_dot_v1_dot_logic__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&relationalai/lqp/v1/transactions.proto\x12\x13relationalai.lqp.v1\x1a#relationalai/lqp/v1/fragments.proto\x1a\x1frelationalai/lqp/v1/logic.proto\"\xbc\x01\n\x0bTransaction\x12\x32\n\x06\x65pochs\x18\x01 \x03(\x0b\x32\x1a.relationalai.lqp.v1.EpochR\x06\x65pochs\x12<\n\tconfigure\x18\x02 \x01(\x0b\x32\x1e.relationalai.lqp.v1.ConfigureR\tconfigure\x12\x32\n\x04sync\x18\x03 \x01(\x0b\x32\x19.relationalai.lqp.v1.SyncH\x00R\x04sync\x88\x01\x01\x42\x07\n\x05_sync\"\xce\x01\n\tConfigure\x12+\n\x11semantics_version\x18\x01 \x01(\x03R\x10semanticsVersion\x12=\n\nivm_config\x18\x02 \x01(\x0b\x32\x1e.relationalai.lqp.v1.IVMConfigR\tivmConfig\x12U\n\x12optimization_level\x18\x03 \x01(\x0e\x32&.relationalai.lqp.v1.OptimizationLevelR\x11optimizationLevel\"H\n\tIVMConfig\x12;\n\x05level\x18\x01 \x01(\x0e\x32%.relationalai.lqp.v1.MaintenanceLevelR\x05level\"E\n\x04Sync\x12=\n\tfragments\x18\x01 \x03(\x0b\x32\x1f.relationalai.lqp.v1.FragmentIdR\tfragments\"l\n\x05\x45poch\x12\x32\n\x06writes\x18\x01 \x03(\x0b\x32\x1a.relationalai.lqp.v1.WriteR\x06writes\x12/\n\x05reads\x18\x02 \x03(\x0b\x32\x19.relationalai.lqp.v1.ReadR\x05reads\"\xc9\x01\n\x05Write\x12\x35\n\x06\x64\x65\x66ine\x18\x01 \x01(\x0b\x32\x1b.relationalai.lqp.v1.DefineH\x00R\x06\x64\x65\x66ine\x12;\n\x08undefine\x18\x02 \x01(\x0b\x32\x1d.relationalai.lqp.v1.UndefineH\x00R\x08undefine\x12\x38\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x1c.relationalai.lqp.v1.ContextH\x00R\x07\x63ontextB\x0c\n\nwrite_typeJ\x04\x08\x04\x10\x05\"C\n\x06\x44\x65\x66ine\x12\x39\n\x08\x66ragment\x18\x01 \x01(\x0b\x32\x1d.relationalai.lqp.v1.FragmentR\x08\x66ragment\"L\n\x08Undefine\x12@\n\x0b\x66ragment_id\x18\x01 \x01(\x0b\x32\x1f.relationalai.lqp.v1.FragmentIdR\nfragmentId\"H\n\x07\x43ontext\x12=\n\trelations\x18\x01 \x03(\x0b\x32\x1f.relationalai.lqp.v1.RelationIdR\trelations\"\xc4\x04\n\x0f\x45xportCSVConfig\x12\x12\n\x04path\x18\x01 \x01(\tR\x04path\x12G\n\x0c\x64\x61ta_columns\x18\x02 \x03(\x0b\x32$.relationalai.lqp.v1.ExportCSVColumnR\x0b\x64\x61taColumns\x12*\n\x0epartition_size\x18\x03 \x01(\x03H\x00R\rpartitionSize\x88\x01\x01\x12%\n\x0b\x63ompression\x18\x04 \x01(\tH\x01R\x0b\x63ompression\x88\x01\x01\x12/\n\x11syntax_header_row\x18\x05 \x01(\x08H\x02R\x0fsyntaxHeaderRow\x88\x01\x01\x12\x37\n\x15syntax_missing_string\x18\x06 \x01(\tH\x03R\x13syntaxMissingString\x88\x01\x01\x12&\n\x0csyntax_delim\x18\x07 \x01(\tH\x04R\x0bsyntaxDelim\x88\x01\x01\x12.\n\x10syntax_quotechar\x18\x08 \x01(\tH\x05R\x0fsyntaxQuotechar\x88\x01\x01\x12\x30\n\x11syntax_escapechar\x18\t \x01(\tH\x06R\x10syntaxEscapechar\x88\x01\x01\x42\x11\n\x0f_partition_sizeB\x0e\n\x0c_compressionB\x14\n\x12_syntax_header_rowB\x18\n\x16_syntax_missing_stringB\x0f\n\r_syntax_delimB\x13\n\x11_syntax_quotecharB\x14\n\x12_syntax_escapechar\"t\n\x0f\x45xportCSVColumn\x12\x1f\n\x0b\x63olumn_name\x18\x01 \x01(\tR\ncolumnName\x12@\n\x0b\x63olumn_data\x18\x02 \x01(\x0b\x32\x1f.relationalai.lqp.v1.RelationIdR\ncolumnData\"\xa4\x02\n\x04Read\x12\x35\n\x06\x64\x65mand\x18\x01 \x01(\x0b\x32\x1b.relationalai.lqp.v1.DemandH\x00R\x06\x64\x65mand\x12\x35\n\x06output\x18\x02 \x01(\x0b\x32\x1b.relationalai.lqp.v1.OutputH\x00R\x06output\x12\x36\n\x07what_if\x18\x03 \x01(\x0b\x32\x1b.relationalai.lqp.v1.WhatIfH\x00R\x06whatIf\x12\x32\n\x05\x61\x62ort\x18\x04 \x01(\x0b\x32\x1a.relationalai.lqp.v1.AbortH\x00R\x05\x61\x62ort\x12\x35\n\x06\x65xport\x18\x05 \x01(\x0b\x32\x1b.relationalai.lqp.v1.ExportH\x00R\x06\x65xportB\x0b\n\tread_type\"J\n\x06\x44\x65mand\x12@\n\x0brelation_id\x18\x01 \x01(\x0b\x32\x1f.relationalai.lqp.v1.RelationIdR\nrelationId\"^\n\x06Output\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12@\n\x0brelation_id\x18\x02 \x01(\x0b\x32\x1f.relationalai.lqp.v1.RelationIdR\nrelationId\"`\n\x06\x45xport\x12\x45\n\ncsv_config\x18\x01 \x01(\x0b\x32$.relationalai.lqp.v1.ExportCSVConfigH\x00R\tcsvConfigB\x0f\n\rexport_config\"R\n\x06WhatIf\x12\x16\n\x06\x62ranch\x18\x01 \x01(\tR\x06\x62ranch\x12\x30\n\x05\x65poch\x18\x02 \x01(\x0b\x32\x1a.relationalai.lqp.v1.EpochR\x05\x65poch\"]\n\x05\x41\x62ort\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12@\n\x0brelation_id\x18\x02 \x01(\x0b\x32\x1f.relationalai.lqp.v1.RelationIdR\nrelationId*\x87\x01\n\x10MaintenanceLevel\x12!\n\x1dMAINTENANCE_LEVEL_UNSPECIFIED\x10\x00\x12\x19\n\x15MAINTENANCE_LEVEL_OFF\x10\x01\x12\x1a\n\x16MAINTENANCE_LEVEL_AUTO\x10\x02\x12\x19\n\x15MAINTENANCE_LEVEL_ALL\x10\x03*\x9f\x01\n\x11OptimizationLevel\x12\"\n\x1eOPTIMIZATION_LEVEL_UNSPECIFIED\x10\x00\x12\x1e\n\x1aOPTIMIZATION_LEVEL_DEFAULT\x10\x01\x12#\n\x1fOPTIMIZATION_LEVEL_CONSERVATIVE\x10\x02\x12!\n\x1dOPTIMIZATION_LEVEL_AGGRESSIVE\x10\x03\x42\x1fZ\x1dlogical-query-protocol/lqp/v1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'relationalai.lqp.v1.transactions_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + _globals['DESCRIPTOR']._options = None + _globals['DESCRIPTOR']._serialized_options = b'Z\035logical-query-protocol/lqp/v1' + _globals['_MAINTENANCELEVEL']._serialized_start=2659 + _globals['_MAINTENANCELEVEL']._serialized_end=2794 + _globals['_OPTIMIZATIONLEVEL']._serialized_start=2797 + _globals['_OPTIMIZATIONLEVEL']._serialized_end=2956 + _globals['_TRANSACTION']._serialized_start=134 + _globals['_TRANSACTION']._serialized_end=322 + _globals['_CONFIGURE']._serialized_start=325 + _globals['_CONFIGURE']._serialized_end=531 + _globals['_IVMCONFIG']._serialized_start=533 + _globals['_IVMCONFIG']._serialized_end=605 + _globals['_SYNC']._serialized_start=607 + _globals['_SYNC']._serialized_end=676 + _globals['_EPOCH']._serialized_start=678 + _globals['_EPOCH']._serialized_end=786 + _globals['_WRITE']._serialized_start=789 + _globals['_WRITE']._serialized_end=990 + _globals['_DEFINE']._serialized_start=992 + _globals['_DEFINE']._serialized_end=1059 + _globals['_UNDEFINE']._serialized_start=1061 + _globals['_UNDEFINE']._serialized_end=1137 + _globals['_CONTEXT']._serialized_start=1139 + _globals['_CONTEXT']._serialized_end=1211 + _globals['_EXPORTCSVCONFIG']._serialized_start=1214 + _globals['_EXPORTCSVCONFIG']._serialized_end=1794 + _globals['_EXPORTCSVCOLUMN']._serialized_start=1796 + _globals['_EXPORTCSVCOLUMN']._serialized_end=1912 + _globals['_READ']._serialized_start=1915 + _globals['_READ']._serialized_end=2207 + _globals['_DEMAND']._serialized_start=2209 + _globals['_DEMAND']._serialized_end=2283 + _globals['_OUTPUT']._serialized_start=2285 + _globals['_OUTPUT']._serialized_end=2379 + _globals['_EXPORT']._serialized_start=2381 + _globals['_EXPORT']._serialized_end=2477 + _globals['_WHATIF']._serialized_start=2479 + _globals['_WHATIF']._serialized_end=2561 + _globals['_ABORT']._serialized_start=2563 + _globals['_ABORT']._serialized_end=2656 +# @@protoc_insertion_point(module_scope) diff --git a/python-tools/src/meta/grammar.y b/python-tools/src/meta/grammar.y new file mode 100644 index 00000000..948c3e23 --- /dev/null +++ b/python-tools/src/meta/grammar.y @@ -0,0 +1,938 @@ +# The structure of this file is similar to yacc. +# +# +# +# %% +# +# %% +# +# +# Actions and helper functions are written in a restricted Python. +# Type annotations are required. +# Not all expression forms are supported. Indeed, one can only call helper +# functions declared below and builtin functions via `builtin.func(...)`. +# We translate this restricted Python into actual Python, Julia, and Go. + + +# Start symbol +%start transaction + +# Token declarations: %token NAME Type PATTERN +# PATTERN can be r'...' for regex or '...' for fixed string +%token DECIMAL logic.DecimalValue r'[-]?\d+\.\d+d\d+' +%token FLOAT Float64 r'[-]?\d+\.\d+|inf|nan' +%token INT Int64 r'[-]?\d+' +%token INT128 logic.Int128Value r'[-]?\d+i128' +%token STRING String r'"(?:[^"\\]|\\.)*"' +%token SYMBOL String r'[a-zA-Z_][a-zA-Z0-9_.-]*' +%token UINT128 logic.UInt128Value r'0x[0-9a-fA-F]+' + +# Type declarations for rules +%nonterm abstraction logic.Abstraction +%nonterm abstraction_with_arity Tuple[logic.Abstraction, Int64] +%nonterm add logic.Primitive +%nonterm algorithm logic.Algorithm +%nonterm assign logic.Assign +%nonterm atom logic.Atom +%nonterm attribute logic.Attribute +%nonterm attrs List[logic.Attribute] +%nonterm betree_info logic.BeTreeInfo +%nonterm betree_info_key_types List[logic.Type] +%nonterm betree_info_value_types List[logic.Type] +%nonterm betree_relation logic.BeTreeRelation +%nonterm binding logic.Binding +%nonterm bindings Tuple[List[logic.Binding], List[logic.Binding]] +%nonterm boolean_type logic.BooleanType +%nonterm boolean_value Boolean +%nonterm break logic.Break +%nonterm cast logic.Cast +%nonterm config_dict List[Tuple[String, logic.Value]] +%nonterm config_key_value Tuple[String, logic.Value] +%nonterm configure transactions.Configure +%nonterm conjunction logic.Conjunction +%nonterm constant logic.Value +%nonterm constraint logic.Constraint +%nonterm construct logic.Construct +%nonterm context transactions.Context +%nonterm csv_asof String +%nonterm csv_column logic.CSVColumn +%nonterm csv_columns List[logic.CSVColumn] +%nonterm csv_config logic.CSVConfig +%nonterm csv_data logic.CSVData +%nonterm csv_locator_inline_data String +%nonterm csv_locator_paths List[String] +%nonterm csvlocator logic.CSVLocator +%nonterm data logic.Data +%nonterm date logic.DateValue +%nonterm date_type logic.DateType +%nonterm datetime logic.DateTimeValue +%nonterm datetime_type logic.DateTimeType +%nonterm decimal_type logic.DecimalType +%nonterm declaration logic.Declaration +%nonterm def logic.Def +%nonterm define transactions.Define +%nonterm demand transactions.Demand +%nonterm disjunction logic.Disjunction +%nonterm divide logic.Primitive +%nonterm abort transactions.Abort +%nonterm epoch transactions.Epoch +%nonterm epoch_reads List[transactions.Read] +%nonterm epoch_writes List[transactions.Write] +%nonterm eq logic.Primitive +%nonterm exists logic.Exists +%nonterm export transactions.Export +%nonterm export_csv_column transactions.ExportCSVColumn +%nonterm export_csv_columns List[transactions.ExportCSVColumn] +%nonterm export_csv_config transactions.ExportCSVConfig +%nonterm export_csv_path String +%nonterm false logic.Disjunction +%nonterm ffi logic.FFI +%nonterm ffi_args List[logic.Abstraction] +%nonterm float_type logic.FloatType +%nonterm formula logic.Formula +%nonterm fragment fragments.Fragment +%nonterm fragment_id fragments.FragmentId +%nonterm functional_dependency_keys List[logic.Var] +%nonterm functional_dependency_values List[logic.Var] +%nonterm gt logic.Primitive +%nonterm gt_eq logic.Primitive +%nonterm init List[logic.Instruction] +%nonterm instruction logic.Instruction +%nonterm int_type logic.IntType +%nonterm int128_type logic.Int128Type +%nonterm loop logic.Loop +%nonterm lt logic.Primitive +%nonterm lt_eq logic.Primitive +%nonterm max_monoid logic.MaxMonoid +%nonterm min_monoid logic.MinMonoid +%nonterm minus logic.Primitive +%nonterm missing_type logic.MissingType +%nonterm monoid logic.Monoid +%nonterm monoid_def logic.MonoidDef +%nonterm monus_def logic.MonusDef +%nonterm multiply logic.Primitive +%nonterm name String +%nonterm new_fragment_id fragments.FragmentId +%nonterm not logic.Not +%nonterm or_monoid logic.OrMonoid +%nonterm output transactions.Output +%nonterm pragma logic.Pragma +%nonterm primitive logic.Primitive +%nonterm read transactions.Read +%nonterm reduce logic.Reduce +%nonterm rel_atom logic.RelAtom +%nonterm rel_edb logic.RelEDB +%nonterm rel_edb_path List[String] +%nonterm rel_edb_types List[logic.Type] +%nonterm rel_term logic.RelTerm +%nonterm relation_id logic.RelationId +%nonterm script logic.Script +%nonterm specialized_value logic.Value +%nonterm string_type logic.StringType +%nonterm sum_monoid logic.SumMonoid +%nonterm sync transactions.Sync +%nonterm term logic.Term +%nonterm terms List[logic.Term] +%nonterm transaction transactions.Transaction +%nonterm true logic.Conjunction +%nonterm type logic.Type +%nonterm uint128_type logic.UInt128Type +%nonterm undefine transactions.Undefine +%nonterm unspecified_type logic.UnspecifiedType +%nonterm upsert logic.Upsert +%nonterm value logic.Value +%nonterm value_bindings List[logic.Binding] +%nonterm var logic.Var +%nonterm what_if transactions.WhatIf +%nonterm write transactions.Write + +# Messages that are constructed imperatively by the parser, not parsed from grammar rules. +# These protobuf message types are excluded from completeness validation because they are +# built programmatically by builtin functions (like construct_betree_info, construct_csv_config) +# or by parser internals, rather than being directly produced by grammar production rules. +# Without these directives, the validator would report errors that these message types have +# no grammar rules producing them. +%validator_ignore_completeness DebugInfo +%validator_ignore_completeness IVMConfig +%validator_ignore_completeness UInt128Value +%validator_ignore_completeness Int128Value +%validator_ignore_completeness DecimalValue +%validator_ignore_completeness BeTreeLocator +%validator_ignore_completeness BeTreeConfig + +%% + +transaction + : "(" "transaction" configure? sync? epoch* ")" + construct: transactions.Transaction(epochs=$5, configure=builtin.unwrap_option_or($3, default_configure()), sync=$4) + +configure + : "(" "configure" config_dict ")" + construct: construct_configure($3) + +config_dict + : "{" config_key_value* "}" + +config_key_value + : ":" SYMBOL value + construct: builtin.tuple($2, $3) + +value + : date + construct: logic.Value(date_value=$1) + | datetime + construct: logic.Value(datetime_value=$1) + | STRING + construct: logic.Value(string_value=$1) + | INT + construct: logic.Value(int_value=$1) + | FLOAT + construct: logic.Value(float_value=$1) + | UINT128 + construct: logic.Value(uint128_value=$1) + | INT128 + construct: logic.Value(int128_value=$1) + | DECIMAL + construct: logic.Value(decimal_value=$1) + | "missing" + construct: logic.Value(missing_value=logic.MissingValue()) + | boolean_value + construct: logic.Value(boolean_value=$1) + +date + : "(" "date" INT INT INT ")" + construct: logic.DateValue(year=builtin.int64_to_int32($3), month=builtin.int64_to_int32($4), day=builtin.int64_to_int32($5)) + +datetime + : "(" "datetime" INT INT INT INT INT INT INT? ")" + construct: logic.DateTimeValue(year=builtin.int64_to_int32($3), month=builtin.int64_to_int32($4), day=builtin.int64_to_int32($5), hour=builtin.int64_to_int32($6), minute=builtin.int64_to_int32($7), second=builtin.int64_to_int32($8), microsecond=builtin.int64_to_int32(builtin.unwrap_option_or($9, 0))) + +boolean_value + : "true" + construct: True + | "false" + construct: False + +sync + : "(" "sync" fragment_id* ")" + construct: transactions.Sync(fragments=$3) + +fragment_id + : ":" SYMBOL + construct: builtin.fragment_id_from_string($2) + +epoch + : "(" "epoch" epoch_writes? epoch_reads? ")" + construct: transactions.Epoch(writes=builtin.unwrap_option_or($3, list[transactions.Write]()), reads=builtin.unwrap_option_or($4, list[transactions.Read]())) + +epoch_writes + : "(" "writes" write* ")" + +write + : define + construct: transactions.Write(define=$1) + | undefine + construct: transactions.Write(undefine=$1) + | context + construct: transactions.Write(context=$1) + +define + : "(" "define" fragment ")" + construct: transactions.Define(fragment=$3) + +fragment + : "(" "fragment" new_fragment_id declaration* ")" + construct: builtin.construct_fragment($3, $4) + +new_fragment_id + : fragment_id + construct: + builtin.start_fragment($1) + $1 + +declaration + : def + construct: logic.Declaration(def=$1) + | algorithm + construct: logic.Declaration(algorithm=$1) + | constraint + construct: logic.Declaration(constraint=$1) + | data + construct: logic.Declaration(data=$1) + +def + : "(" "def" relation_id abstraction attrs? ")" + construct: logic.Def(name=$3, body=$4, attrs=builtin.unwrap_option_or($5, list[logic.Attribute]())) + +relation_id + : ":" SYMBOL + construct: builtin.relation_id_from_string($2) + | UINT128 + construct: builtin.relation_id_from_uint128($1) + +abstraction + : "(" bindings formula ")" + construct: logic.Abstraction(vars=builtin.list_concat($2[0], $2[1]), value=$3) + +bindings + : "[" binding* value_bindings? "]" + construct: builtin.tuple($2, builtin.unwrap_option_or($3, list[logic.Binding]())) + +binding + : SYMBOL "::" type + construct: logic.Binding(var=logic.Var(name=$1), type=$3) + +type + : unspecified_type + construct: logic.Type(unspecified_type=$1) + | string_type + construct: logic.Type(string_type=$1) + | int_type + construct: logic.Type(int_type=$1) + | float_type + construct: logic.Type(float_type=$1) + | uint128_type + construct: logic.Type(uint128_type=$1) + | int128_type + construct: logic.Type(int128_type=$1) + | date_type + construct: logic.Type(date_type=$1) + | datetime_type + construct: logic.Type(datetime_type=$1) + | missing_type + construct: logic.Type(missing_type=$1) + | decimal_type + construct: logic.Type(decimal_type=$1) + | boolean_type + construct: logic.Type(boolean_type=$1) + +unspecified_type + : "UNKNOWN" + construct: logic.UnspecifiedType() + +string_type + : "STRING" + construct: logic.StringType() + +int_type + : "INT" + construct: logic.IntType() + +float_type + : "FLOAT" + construct: logic.FloatType() + +uint128_type + : "UINT128" + construct: logic.UInt128Type() + +int128_type + : "INT128" + construct: logic.Int128Type() + +date_type + : "DATE" + construct: logic.DateType() + +datetime_type + : "DATETIME" + construct: logic.DateTimeType() + +missing_type + : "MISSING" + construct: logic.MissingType() + +decimal_type + : "(" "DECIMAL" INT INT ")" + construct: logic.DecimalType(precision=builtin.int64_to_int32($3), scale=builtin.int64_to_int32($4)) + +boolean_type + : "BOOLEAN" + construct: logic.BooleanType() + +value_bindings + : "|" binding* + +formula + : true + construct: logic.Formula(conjunction=$1) + | false + construct: logic.Formula(disjunction=$1) + | exists + construct: logic.Formula(exists=$1) + | reduce + construct: logic.Formula(reduce=$1) + | conjunction + construct: logic.Formula(conjunction=$1) + | disjunction + construct: logic.Formula(disjunction=$1) + | not + construct: logic.Formula(not=$1) + | ffi + construct: logic.Formula(ffi=$1) + | atom + construct: logic.Formula(atom=$1) + | pragma + construct: logic.Formula(pragma=$1) + | primitive + construct: logic.Formula(primitive=$1) + | rel_atom + construct: logic.Formula(rel_atom=$1) + | cast + construct: logic.Formula(cast=$1) + +true + : "(" "true" ")" + construct: logic.Conjunction(args=list[logic.Formula]()) + +false + : "(" "false" ")" + construct: logic.Disjunction(args=list[logic.Formula]()) + +exists + : "(" "exists" bindings formula ")" + construct: logic.Exists(body=logic.Abstraction(vars=builtin.list_concat($3[0], $3[1]), value=$4)) + +reduce + : "(" "reduce" abstraction abstraction terms ")" + construct: logic.Reduce(op=$3, body=$4, terms=$5) + +term + : var + construct: logic.Term(var=$1) + | constant + construct: logic.Term(constant=$1) + +var + : SYMBOL + construct: logic.Var(name=$1) + +constant + : value + +conjunction + : "(" "and" formula* ")" + construct: logic.Conjunction(args=$3) + +disjunction + : "(" "or" formula* ")" + construct: logic.Disjunction(args=$3) + +not + : "(" "not" formula ")" + construct: logic.Not(arg=$3) + +ffi + : "(" "ffi" name ffi_args terms ")" + construct: logic.FFI(name=$3, args=$4, terms=$5) + +ffi_args + : "(" "args" abstraction* ")" + +terms + : "(" "terms" term* ")" + +name + : ":" SYMBOL + +atom + : "(" "atom" relation_id term* ")" + construct: logic.Atom(name=$3, terms=$4) + +pragma + : "(" "pragma" name term* ")" + construct: logic.Pragma(name=$3, terms=$4) + +primitive + : eq + | lt + | lt_eq + | gt + | gt_eq + | add + | minus + | multiply + | divide + | "(" "primitive" name rel_term* ")" + construct: logic.Primitive(name=$3, terms=$4) + +eq + : "(" "=" term term ")" + construct: logic.Primitive(name="rel_primitive_eq", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4)]) + +lt + : "(" "<" term term ")" + construct: logic.Primitive(name="rel_primitive_lt_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4)]) + +lt_eq + : "(" "<=" term term ")" + construct: logic.Primitive(name="rel_primitive_lt_eq_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4)]) + +gt + : "(" ">" term term ")" + construct: logic.Primitive(name="rel_primitive_gt_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4)]) + +gt_eq + : "(" ">=" term term ")" + construct: logic.Primitive(name="rel_primitive_gt_eq_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4)]) + +add + : "(" "+" term term term ")" + construct: logic.Primitive(name="rel_primitive_add_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4), logic.RelTerm(term=$5)]) + +minus + : "(" "-" term term term ")" + construct: logic.Primitive(name="rel_primitive_subtract_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4), logic.RelTerm(term=$5)]) + +multiply + : "(" "*" term term term ")" + construct: logic.Primitive(name="rel_primitive_multiply_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4), logic.RelTerm(term=$5)]) + +divide + : "(" "/" term term term ")" + construct: logic.Primitive(name="rel_primitive_divide_monotype", terms=[logic.RelTerm(term=$3), logic.RelTerm(term=$4), logic.RelTerm(term=$5)]) + +rel_term + : specialized_value + construct: logic.RelTerm(specialized_value=$1) + | term + construct: logic.RelTerm(term=$1) + +specialized_value + : "#" value + +rel_atom + : "(" "relatom" name rel_term* ")" + construct: logic.RelAtom(name=$3, terms=$4) + +cast + : "(" "cast" term term ")" + construct: logic.Cast(input=$3, result=$4) + +attrs + : "(" "attrs" attribute* ")" + +attribute + : "(" "attribute" name value* ")" + construct: logic.Attribute(name=$3, args=$4) + +algorithm + : "(" "algorithm" relation_id* script ")" + construct: logic.Algorithm(global=$3, body=$4) + +script + : "(" "script" construct* ")" + construct: logic.Script(constructs=$3) + +construct + : loop + construct: logic.Construct(loop=$1) + | instruction + construct: logic.Construct(instruction=$1) + +loop + : "(" "loop" init script ")" + construct: logic.Loop(init=$3, body=$4) + +init + : "(" "init" instruction* ")" + +instruction + : assign + construct: logic.Instruction(assign=$1) + | upsert + construct: logic.Instruction(upsert=$1) + | break + construct: logic.Instruction(break=$1) + | monoid_def + construct: logic.Instruction(monoid_def=$1) + | monus_def + construct: logic.Instruction(monus_def=$1) + +assign + : "(" "assign" relation_id abstraction attrs? ")" + construct: logic.Assign(name=$3, body=$4, attrs=builtin.unwrap_option_or($5, list[logic.Attribute]())) + +upsert + : "(" "upsert" relation_id abstraction_with_arity attrs? ")" + construct: logic.Upsert(name=$3, body=$4[0], attrs=builtin.unwrap_option_or($5, list[logic.Attribute]()), value_arity=$4[1]) + +abstraction_with_arity + : "(" bindings formula ")" + construct: builtin.tuple(logic.Abstraction(vars=builtin.list_concat($2[0], $2[1]), value=$3), builtin.length($2[1])) + +break + : "(" "break" relation_id abstraction attrs? ")" + construct: logic.Break(name=$3, body=$4, attrs=builtin.unwrap_option_or($5, list[logic.Attribute]())) + +monoid_def + : "(" "monoid" monoid relation_id abstraction_with_arity attrs? ")" + construct: logic.MonoidDef(monoid=$3, name=$4, body=$5[0], attrs=builtin.unwrap_option_or($6, list[logic.Attribute]()), value_arity=$5[1]) + +monoid + : or_monoid + construct: logic.Monoid(or_monoid=$1) + | min_monoid + construct: logic.Monoid(min_monoid=$1) + | max_monoid + construct: logic.Monoid(max_monoid=$1) + | sum_monoid + construct: logic.Monoid(sum_monoid=$1) + +or_monoid + : "(" "or" ")" + construct: logic.OrMonoid() + +min_monoid + : "(" "min" type ")" + construct: logic.MinMonoid(type=$3) +max_monoid + : "(" "max" type ")" + construct: logic.MaxMonoid(type=$3) + +sum_monoid + : "(" "sum" type ")" + construct: logic.SumMonoid(type=$3) + +monus_def + : "(" "monus" monoid relation_id abstraction_with_arity attrs? ")" + construct: logic.MonusDef(monoid=$3, name=$4, body=$5[0], attrs=builtin.unwrap_option_or($6, list[logic.Attribute]()), value_arity=$5[1]) + +constraint + : "(" "functional_dependency" relation_id abstraction functional_dependency_keys functional_dependency_values ")" + construct: logic.Constraint(name=$3, functional_dependency=logic.FunctionalDependency(guard=$4, keys=$5, values=$6)) + +functional_dependency_keys + : "(" "keys" var* ")" + +functional_dependency_values + : "(" "values" var* ")" + +data + : rel_edb + construct: logic.Data(rel_edb=$1) + | betree_relation + construct: logic.Data(betree_relation=$1) + | csv_data + construct: logic.Data(csv_data=$1) + +rel_edb_path + : "[" STRING* "]" + +rel_edb_types + : "[" type* "]" + +rel_edb + : "(" "rel_edb" relation_id rel_edb_path rel_edb_types ")" + construct: logic.RelEDB(target_id=$3, path=$4, types=$5) + +betree_relation + : "(" "betree_relation" relation_id betree_info ")" + construct: logic.BeTreeRelation(name=$3, relation_info=$4) + +betree_info + : "(" "betree_info" betree_info_key_types betree_info_value_types config_dict ")" + construct: construct_betree_info($3, $4, $5) + +betree_info_key_types + : "(" "key_types" type* ")" + +betree_info_value_types + : "(" "value_types" type* ")" + +csv_columns + : "(" "columns" csv_column* ")" + +csv_asof + : "(" "asof" STRING ")" + +csv_data + : "(" "csv_data" csvlocator csv_config csv_columns csv_asof ")" + construct: logic.CSVData(locator=$3, config=$4, columns=$5, asof=$6) + +csv_locator_paths + : "(" "paths" STRING* ")" + +csv_locator_inline_data + : "(" "inline_data" STRING ")" + +csvlocator + : "(" "csv_locator" csv_locator_paths? csv_locator_inline_data? ")" + construct: logic.CSVLocator(paths=builtin.unwrap_option_or($3, list[str]()), inline_data=builtin.encode_string(builtin.unwrap_option_or($4, ""))) + +csv_config + : "(" "csv_config" config_dict ")" + construct: construct_csv_config($3) + +csv_column + : "(" "column" STRING relation_id "[" type* "]" ")" + construct: logic.CSVColumn(column_name=$3, target_id=$4, types=$6) + +undefine + : "(" "undefine" fragment_id ")" + construct: transactions.Undefine(fragment_id=$3) + +context + : "(" "context" relation_id* ")" + construct: transactions.Context(relations=$3) + +epoch_reads + : "(" "reads" read* ")" + +read + : demand + construct: transactions.Read(demand=$1) + | output + construct: transactions.Read(output=$1) + | what_if + construct: transactions.Read(what_if=$1) + | abort + construct: transactions.Read(abort=$1) + | export + construct: transactions.Read(export=$1) + +demand + : "(" "demand" relation_id ")" + construct: transactions.Demand(relation_id=$3) + +output + : "(" "output" name? relation_id ")" + construct: transactions.Output(name=builtin.unwrap_option_or($3, "output"), relation_id=$4) + +what_if + : "(" "what_if" name epoch ")" + construct: transactions.WhatIf(branch=$3, epoch=$4) + +abort + : "(" "abort" name? relation_id ")" + construct: transactions.Abort(name=builtin.unwrap_option_or($3, "abort"), relation_id=$4) + +export + : "(" "export" export_csv_config ")" + construct: transactions.Export(csv_config=$3) + +export_csv_config + : "(" "export_csv_config" export_csv_path export_csv_columns config_dict ")" + construct: export_csv_config($3, $4, $5) + +export_csv_path + : "(" "path" STRING ")" + +export_csv_columns + : "(" "columns" export_csv_column* ")" + +export_csv_column + : "(" "column" STRING relation_id ")" + construct: transactions.ExportCSVColumn(column_name=$3, column_data=$4) + + +%% + + +def _extract_value_int64(value: Optional[logic.Value], default: int) -> int: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'int_value'): + return builtin.unwrap_option(value).int_value + return default + + +def _extract_value_float64(value: Optional[logic.Value], default: float) -> float: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'float_value'): + return builtin.unwrap_option(value).float_value + return default + + +def _extract_value_string(value: Optional[logic.Value], default: str) -> str: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return builtin.unwrap_option(value).string_value + return default + + +def _extract_value_boolean(value: Optional[logic.Value], default: bool) -> bool: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'boolean_value'): + return builtin.unwrap_option(value).boolean_value + return default + + +def _extract_value_bytes(value: Optional[logic.Value], default: bytes) -> bytes: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return builtin.encode_string(builtin.unwrap_option(value).string_value) + return default + + +def _extract_value_uint128(value: Optional[logic.Value], default: logic.UInt128Value) -> logic.UInt128Value: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'uint128_value'): + return builtin.unwrap_option(value).uint128_value + return default + +def _extract_value_string_list(value: Optional[logic.Value], default: List[String]) -> List[String]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return [builtin.unwrap_option(value).string_value] + return default + +def _try_extract_value_int64(value: Optional[logic.Value]) -> Optional[int]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'int_value'): + return builtin.unwrap_option(value).int_value + return None + + +def _try_extract_value_float64(value: Optional[logic.Value]) -> Optional[float]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'float_value'): + return builtin.unwrap_option(value).float_value + return None + + +def _try_extract_value_string(value: Optional[logic.Value]) -> Optional[str]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return builtin.unwrap_option(value).string_value + return None + + +def _try_extract_value_bytes(value: Optional[logic.Value]) -> Optional[bytes]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return builtin.encode_string(builtin.unwrap_option(value).string_value) + return None + + +def _try_extract_value_uint128(value: Optional[logic.Value]) -> Optional[logic.UInt128Value]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'uint128_value'): + return builtin.unwrap_option(value).uint128_value + return None + + +def _try_extract_value_string_list(value: Optional[logic.Value]) -> Optional[List[String]]: + if value is not None and builtin.has_proto_field(builtin.unwrap_option(value), 'string_value'): + return [builtin.unwrap_option(value).string_value] + return None + + +def construct_csv_config(config_dict: List[Tuple[String, logic.Value]]) -> logic.CSVConfig: + config: Dict[String, logic.Value] = builtin.dict_from_list(config_dict) + header_row: int = _extract_value_int64(builtin.dict_get(config, "csv_header_row"), 1) + skip: int = _extract_value_int64(builtin.dict_get(config, "csv_skip"), 0) + new_line: str = _extract_value_string(builtin.dict_get(config, "csv_new_line"), "") + delimiter: str = _extract_value_string(builtin.dict_get(config, "csv_delimiter"), ",") + quotechar: str = _extract_value_string(builtin.dict_get(config, "csv_quotechar"), "\"") + escapechar: str = _extract_value_string(builtin.dict_get(config, "csv_escapechar"), "\"") + comment: str = _extract_value_string(builtin.dict_get(config, "csv_comment"), "") + missing_strings: List[String] = _extract_value_string_list(builtin.dict_get(config, "csv_missing_strings"), list[str]()) + decimal_separator: str = _extract_value_string(builtin.dict_get(config, "csv_decimal_separator"), ".") + encoding: str = _extract_value_string(builtin.dict_get(config, "csv_encoding"), "utf-8") + compression: str = _extract_value_string(builtin.dict_get(config, "csv_compression"), "auto") + return logic.CSVConfig( + header_row=builtin.int64_to_int32(header_row), + skip=skip, + new_line=new_line, + delimiter=delimiter, + quotechar=quotechar, + escapechar=escapechar, + comment=comment, + missing_strings=missing_strings, + decimal_separator=decimal_separator, + encoding=encoding, + compression=compression, + ) + + +def construct_betree_info( + key_types: List[logic.Type], + value_types: List[logic.Type], + config_dict: List[Tuple[String, logic.Value]], +) -> logic.BeTreeInfo: + config: Dict[String, logic.Value] = builtin.dict_from_list(config_dict) + epsilon: Optional[float] = _try_extract_value_float64(builtin.dict_get(config, "betree_config_epsilon")) + max_pivots: Optional[int] = _try_extract_value_int64(builtin.dict_get(config, "betree_config_max_pivots")) + max_deltas: Optional[int] = _try_extract_value_int64(builtin.dict_get(config, "betree_config_max_deltas")) + max_leaf: Optional[int] = _try_extract_value_int64(builtin.dict_get(config, "betree_config_max_leaf")) + storage_config: logic.BeTreeConfig = logic.BeTreeConfig( + epsilon=epsilon, + max_pivots=max_pivots, + max_deltas=max_deltas, + max_leaf=max_leaf, + ) + root_pageid: Optional[logic.UInt128Value] = _try_extract_value_uint128(builtin.dict_get(config, "betree_locator_root_pageid")) + inline_data: Optional[bytes] = _try_extract_value_bytes(builtin.dict_get(config, "betree_locator_inline_data")) + element_count: Optional[int] = _try_extract_value_int64(builtin.dict_get(config, "betree_locator_element_count")) + tree_height: Optional[int] = _try_extract_value_int64(builtin.dict_get(config, "betree_locator_tree_height")) + relation_locator: logic.BeTreeLocator = logic.BeTreeLocator( + root_pageid=root_pageid, + inline_data=inline_data, + element_count=element_count, + tree_height=tree_height, + ) + return logic.BeTreeInfo( + key_types=key_types, + value_types=value_types, + storage_config=storage_config, + relation_locator=relation_locator, + ) + + +def default_configure() -> transactions.Configure: + ivm_config: transactions.IVMConfig = transactions.IVMConfig(level=transactions.MaintenanceLevel.MAINTENANCE_LEVEL_OFF) + return transactions.Configure( + semantics_version=0, + ivm_config=ivm_config, + optimization_level=transactions.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT, + ) + +def construct_configure(config_dict: List[Tuple[String, logic.Value]]) -> transactions.Configure: + config: Dict[String, logic.Value] = builtin.dict_from_list(config_dict) + maintenance_level_val: Optional[logic.Value] = builtin.dict_get(config, "ivm.maintenance_level") + maintenance_level: transactions.MaintenanceLevel = transactions.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + if (maintenance_level_val is not None + and builtin.has_proto_field(maintenance_level_val, 'string_value')): + if maintenance_level_val.string_value == "off": + maintenance_level = transactions.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + elif maintenance_level_val.string_value == "auto": + maintenance_level = transactions.MaintenanceLevel.MAINTENANCE_LEVEL_AUTO + elif maintenance_level_val.string_value == "all": + maintenance_level = transactions.MaintenanceLevel.MAINTENANCE_LEVEL_ALL + else: + maintenance_level = transactions.MaintenanceLevel.MAINTENANCE_LEVEL_OFF + ivm_config: transactions.IVMConfig = transactions.IVMConfig(level=maintenance_level) + semantics_version: int = _extract_value_int64(builtin.dict_get(config, "semantics_version"), 0) + + optimization_level_val: Optional[logic.Value] = builtin.dict_get(config, "optimization_level") + optimization_level: transactions.OptimizationLevel = transactions.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + if (optimization_level_val is not None + and builtin.has_proto_field(optimization_level_val, 'string_value')): + if optimization_level_val.string_value == "default": + optimization_level = transactions.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + elif optimization_level_val.string_value == "conservative": + optimization_level = transactions.OptimizationLevel.OPTIMIZATION_LEVEL_CONSERVATIVE + elif optimization_level_val.string_value == "aggressive": + optimization_level = transactions.OptimizationLevel.OPTIMIZATION_LEVEL_AGGRESSIVE + else: + optimization_level = transactions.OptimizationLevel.OPTIMIZATION_LEVEL_DEFAULT + + return transactions.Configure( + semantics_version=semantics_version, + ivm_config=ivm_config, + optimization_level=optimization_level, + ) + + +def export_csv_config( + path: String, + columns: List[transactions.ExportCSVColumn], + config_dict: List[Tuple[String, logic.Value]], +) -> transactions.ExportCSVConfig: + config: Dict[String, logic.Value] = builtin.dict_from_list(config_dict) + partition_size: int = _extract_value_int64(builtin.dict_get(config, "partition_size"), 0) + compression: str = _extract_value_string(builtin.dict_get(config, "compression"), "") + syntax_header_row: bool = _extract_value_boolean(builtin.dict_get(config, "syntax_header_row"), True) + syntax_missing_string: str = _extract_value_string(builtin.dict_get(config, "syntax_missing_string"), "") + syntax_delim: str = _extract_value_string(builtin.dict_get(config, "syntax_delim"), ",") + syntax_quotechar: str = _extract_value_string(builtin.dict_get(config, "syntax_quotechar"), '"') + syntax_escapechar: str = _extract_value_string(builtin.dict_get(config, "syntax_escapechar"), "\\") + return transactions.ExportCSVConfig( + path=path, + data_columns=columns, + partition_size=builtin.to_ptr_int64(partition_size), + compression=builtin.to_ptr_string(compression), + syntax_header_row=builtin.to_ptr_bool(syntax_header_row), + syntax_missing_string=builtin.to_ptr_string(syntax_missing_string), + syntax_delim=builtin.to_ptr_string(syntax_delim), + syntax_quotechar=builtin.to_ptr_string(syntax_quotechar), + syntax_escapechar=builtin.to_ptr_string(syntax_escapechar), + ) diff --git a/python-tools/tests/lqp_debug_output/arithmetic.lqp b/python-tools/tests/lqp_debug_output/arithmetic.lqp new file mode 100644 index 00000000..dd5bca6e --- /dev/null +++ b/python-tools/tests/lqp_debug_output/arithmetic.lqp @@ -0,0 +1,38 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xbce2264eb3c4d756 + ([plus::(DECIMAL 18 6) minus::(DECIMAL 18 6) mult::(DECIMAL 18 6) div::(DECIMAL 18 6)] + (exists [a::(DECIMAL 18 6) b::(DECIMAL 18 6)] + (and + (relatom :dec_64_a a) + (relatom :dec_64_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div))))) + (def 0x4da0ef183c55619 + ([plus::(DECIMAL 38 10) minus::(DECIMAL 38 10) mult::(DECIMAL 38 10) div::(DECIMAL 38 10)] + (exists [a::(DECIMAL 38 10) b::(DECIMAL 38 10)] + (and + (relatom :dec_128_a a) + (relatom :dec_128_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div)))))))) + (reads + (output :dec_64 0xbce2264eb3c4d756) + (output :dec_128 0x4da0ef183c55619)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xbce2264eb3c4d756` -> `decimal_64` +;; ID `0x4da0ef183c55619` -> `decimal_128` diff --git a/python-tools/tests/lqp_debug_output/attributes.lqp b/python-tools/tests/lqp_debug_output/attributes.lqp new file mode 100644 index 00000000..b0943b77 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/attributes.lqp @@ -0,0 +1,31 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4)))) + (attrs + (attribute :function) + (attribute :inspect "normalizer" 2)))))) + (reads + (output :foo 0x2c26b46b68ffc68f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x2c26b46b68ffc68f` -> `foo` diff --git a/python-tools/tests/lqp_debug_output/config_flags.lqp b/python-tools/tests/lqp_debug_output/config_flags.lqp new file mode 100644 index 00000000..adf4ca9c --- /dev/null +++ b/python-tools/tests/lqp_debug_output/config_flags.lqp @@ -0,0 +1,19 @@ +(transaction + (configure + { :ivm.maintenance_level "auto" + :optimization_level "aggressive" + :semantics_version 1}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output 0xe0ee8bb50685e05f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe0ee8bb50685e05f` -> `output` diff --git a/python-tools/tests/lqp_debug_output/csv.lqp b/python-tools/tests/lqp_debug_output/csv.lqp new file mode 100644 index 00000000..96a8539e --- /dev/null +++ b/python-tools/tests/lqp_debug_output/csv.lqp @@ -0,0 +1,122 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (csv_data + (csv_locator + (paths "s3://bucket/data/file1.csv" "s3://bucket/data/file2.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "user_id" 0xf89d6b6960453241 [INT]) + (column "name" 0x2e0d0e00d49ec4d3 [STRING]) + (column "score" 0xd080921d895bacdb [FLOAT])) + (asof "2025-01-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "https://example.com/data.csv")) + (csv_config + { :csv_comment "#" + :csv_compression "gzip" + :csv_decimal_separator "," + :csv_delimiter "|" + :csv_encoding "latin-1" + :csv_escapechar "\\" + :csv_header_row 2 + :csv_missing_strings "NA" + :csv_quotechar "'" + :csv_skip 1}) + (columns + (column "timestamp" 0x44ad63f60af0f6db [DATETIME]) + (column "value" 0x97dfc65f74283f60 [(DECIMAL 18 4)])) + (asof "2025-01-15T12:00:00Z")) + (csv_data + (csv_locator + (inline_data "user_id,name,score\n1,Alice,95.5\n2,Bob,87.3")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "user_id" 0x1802f277114b102f [INT]) + (column "name" 0x26ce8135e472b083 [STRING]) + (column "score" 0x1fbccc1771050306 [FLOAT])) + (asof "2025-01-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "/local/path/data.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "\t" + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "id" 0xbd9cecd5353749e9 [INT STRING]) + (column "data" 0x450b548547f965e [STRING FLOAT BOOLEAN])) + (asof "2025-02-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "data/infer.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "col1" 0xd7ccbace08a86f7d []) + (column "col2" 0x59fd8313b61172d2 [])) + (asof "2025-03-01T00:00:00Z"))))) + (reads + (output :user_id 0xf89d6b6960453241) + (output :user_name 0x2e0d0e00d49ec4d3) + (output :user_score 0xd080921d895bacdb) + (output :ts 0x44ad63f60af0f6db) + (output :val 0x97dfc65f74283f60) + (output :inline_user_id 0x1802f277114b102f) + (output :inline_user_name 0x26ce8135e472b083) + (output :inline_user_score 0x1fbccc1771050306) + (output :multi_id 0xbd9cecd5353749e9) + (output :multi_data 0x450b548547f965e) + (output :inferred1 0xd7ccbace08a86f7d) + (output :inferred2 0x59fd8313b61172d2)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xf89d6b6960453241` -> `user_id` +;; ID `0x2e0d0e00d49ec4d3` -> `user_name` +;; ID `0xd080921d895bacdb` -> `user_score` +;; ID `0x44ad63f60af0f6db` -> `ts` +;; ID `0x97dfc65f74283f60` -> `val` +;; ID `0x1802f277114b102f` -> `inline_user_id` +;; ID `0x26ce8135e472b083` -> `inline_user_name` +;; ID `0x1fbccc1771050306` -> `inline_user_score` +;; ID `0xbd9cecd5353749e9` -> `multi_id` +;; ID `0x450b548547f965e` -> `multi_data` +;; ID `0xd7ccbace08a86f7d` -> `inferred1` +;; ID `0x59fd8313b61172d2` -> `inferred2` diff --git a/python-tools/tests/lqp_debug_output/edb.lqp b/python-tools/tests/lqp_debug_output/edb.lqp new file mode 100644 index 00000000..00370d19 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/edb.lqp @@ -0,0 +1,145 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (betree_relation 0xa9e35fa05f07f5bc + (betree_info + (key_types INT) + (value_types STRING INT) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 0 + :betree_locator_root_pageid 0x1234567890123456789012 + :betree_locator_tree_height 0})) + (betree_relation 0x9cc5c01c151a49f3 + (betree_info + (key_types INT STRING) + (value_types FLOAT) + { :betree_config_epsilon 0.8 + :betree_config_max_deltas 32 + :betree_config_max_leaf 32 + :betree_config_max_pivots 8 + :betree_locator_element_count 100 + :betree_locator_root_pageid 0xabcdef1234567890abcdef + :betree_locator_tree_height 2})) + (betree_relation 0x22ee775a8c966d84 + (betree_info + (key_types UINT128) + (value_types INT FLOAT (DECIMAL 18 4)) + { :betree_config_epsilon 0.3 + :betree_config_max_deltas 20 + :betree_config_max_leaf 64 + :betree_config_max_pivots 10 + :betree_locator_element_count 500 + :betree_locator_root_pageid 0xfedcba9876543210fedcba + :betree_locator_tree_height 3})) + (betree_relation 0x927cb0b0096c1296 + (betree_info + (key_types DATE) + (value_types DATETIME STRING) + { :betree_config_epsilon 0.6 + :betree_config_max_deltas 24 + :betree_config_max_leaf 48 + :betree_config_max_pivots 6 + :betree_locator_element_count 250 + :betree_locator_root_pageid 0x9999888877776666555544 + :betree_locator_tree_height 2})) + (betree_relation 0xe52f262b796e7dd2 + (betree_info + (key_types STRING) + (value_types BOOLEAN MISSING) + { :betree_config_epsilon 0.7 + :betree_config_max_deltas 15 + :betree_config_max_leaf 20 + :betree_config_max_pivots 5 + :betree_locator_element_count 75 + :betree_locator_root_pageid 0x1111222233334444555566 + :betree_locator_tree_height 1})) + (betree_relation 0x67a0ea198e6e91f9 + (betree_info + (key_types INT STRING) + (value_types) + { :betree_config_epsilon 0.4 + :betree_config_max_deltas 18 + :betree_config_max_leaf 40 + :betree_config_max_pivots 12 + :betree_locator_element_count 10 + :betree_locator_root_pageid 0x7777888899990000111122 + :betree_locator_tree_height 1})) + (rel_edb 0x15840b06a27cfd50 ["my_base_relation"] [INT STRING FLOAT]) + (rel_edb 0xd18eb5ae6b1c6d60 ["another" "path"] [INT STRING]) + (rel_edb 0x1d55ba4ed7a92d94 ["complex" "path" "here"] [(DECIMAL 10 2) INT STRING]) + (rel_edb 0xce18a64a245dea33 ["empty_path"] []) + (def 0x2c26b46b68ffc68f + ([x::INT] + (primitive :rel_primitive_eq x 1))) + (algorithm 0xfcde2b2edba56bf4 0xbaa5a0964d3320fb + (script + (assign 0xfcde2b2edba56bf4 + ([y::INT] + (primitive :rel_primitive_eq y 2))))))) + (define + (fragment :f2 + (betree_relation 0xd7458e7387db7526 + (betree_info + (key_types STRING) + (value_types INT) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 1000 + :betree_locator_root_pageid 0x3333444455556666777788 + :betree_locator_tree_height 4})) + (betree_relation 0x40295aa31ad63d24 + (betree_info + (key_types INT) + (value_types STRING) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 42 + :betree_locator_inline_data "binary_blob_data_here" + :betree_locator_tree_height 1}))))) + (reads + (output :foo 0x2c26b46b68ffc68f) + (output :edb 0xa9e35fa05f07f5bc) + (output :multi_key 0x9cc5c01c151a49f3) + (output :numeric_types 0x22ee775a8c966d84) + (output :temporal_data 0x927cb0b0096c1296) + (output :boolean_data 0xe52f262b796e7dd2) + (output :key_only 0x67a0ea198e6e91f9) + (output :path_simple 0x15840b06a27cfd50) + (output :path_specialized 0xd18eb5ae6b1c6d60) + (output :path_mixed 0x1d55ba4ed7a92d94) + (output :path_empty 0xce18a64a245dea33) + (output :bar 0xfcde2b2edba56bf4) + (output :another_edb 0xd7458e7387db7526) + (output :inline_edb 0x40295aa31ad63d24)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xd7458e7387db7526` -> `another_edb` +;; ID `0x40295aa31ad63d24` -> `inline_edb` +;; ID `0xa9e35fa05f07f5bc` -> `edb` +;; ID `0x9cc5c01c151a49f3` -> `multi_key` +;; ID `0x22ee775a8c966d84` -> `numeric_types` +;; ID `0x927cb0b0096c1296` -> `temporal_data` +;; ID `0xe52f262b796e7dd2` -> `boolean_data` +;; ID `0x67a0ea198e6e91f9` -> `key_only` +;; ID `0x15840b06a27cfd50` -> `path_simple` +;; ID `0xd18eb5ae6b1c6d60` -> `path_specialized` +;; ID `0x1d55ba4ed7a92d94` -> `path_mixed` +;; ID `0xce18a64a245dea33` -> `path_empty` +;; ID `0x2c26b46b68ffc68f` -> `foo` +;; ID `0xfcde2b2edba56bf4` -> `bar` +;; ID `0xbaa5a0964d3320fb` -> `baz` diff --git a/python-tools/tests/lqp_debug_output/fd.lqp b/python-tools/tests/lqp_debug_output/fd.lqp new file mode 100644 index 00000000..4207c123 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/fd.lqp @@ -0,0 +1,232 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :person_model + (def 0x6007db63e18e532c + ([id::INT] + (or + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq id 2)))) + (def 0xefa5ff7eefcfbef0 + ([id::INT n::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq n "SSN#Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq n "SSN#Bob")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0x8e8376f9710788de + ([n::STRING id::INT] + (atom 0xefa5ff7eefcfbef0 id n)) + (keys n) + (values id)) + (def 0x5416fbf98c1d659 + ([id::INT fn::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq fn "Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq fn "Bob")))) + (attrs + (attribute :function "checked"))) + (def 0x2326b8630011d51c + ([id::INT ln::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq ln "Smith")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq ln "Johnson")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xc3f56e92809c666 + ([fn::STRING ln::STRING id::INT] + (and + (atom 0x5416fbf98c1d659 id fn) + (atom 0x2326b8630011d51c id ln))) + (keys fn ln) + (values id)))) + (define + (fragment :emp_model + (def 0x14014e6a57032789 + ([id::INT] + (primitive :rel_primitive_eq id 1))) + (def 0x426f6eb9e6a97a37 + ([id::INT eid::INT] + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq eid 1001))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xe5b5fc109170b537 + ([n::STRING id::INT] + (atom 0xefa5ff7eefcfbef0 id n)) + (keys n) + (values id)) + (functional_dependency 0x7634153440f8a51c + ([eid::INT id::INT] + (atom 0x426f6eb9e6a97a37 id eid)) + (keys eid) + (values id)))) + (define + (fragment :query1 + (def 0x2e87d494473e3166 + ([n::STRING fn::STRING ln::STRING eid::INT] + (exists [person_id::INT] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x5416fbf98c1d659 person_id fn) + (atom 0x2326b8630011d51c person_id ln) + (atom 0x426f6eb9e6a97a37 person_id eid) + (atom 0x14014e6a57032789 person_id)))))))) + (reads + (output :output1 0x2e87d494473e3166))) + (epoch + (writes + (define + (fragment :car_model + (def 0xa5cdf07dbbc15892 + ([id::INT] + (or + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq id 4)))) + (def 0x8a2539e2b69d9daf + ([id::INT v::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq v "VIN#Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq v "VIN#Toyota")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xbc9b6f54da25926c + ([v::STRING id::INT] + (atom 0x8a2539e2b69d9daf id v)) + (keys v) + (values id)) + (def 0xd05aa2a15fb3c40e + ([id::INT m::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq m "Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq m "Toyota")))) + (attrs + (attribute :function "checked"))) + (def 0x22025b5071a4ea68 + ([person_id::INT car_id::INT date::STRING amount::INT] + (or + (and + (primitive :rel_primitive_eq person_id 1) + (primitive :rel_primitive_eq car_id 3) + (primitive :rel_primitive_eq date "2020-01-15") + (primitive :rel_primitive_eq amount 20000)) + (and + (primitive :rel_primitive_eq person_id 2) + (primitive :rel_primitive_eq car_id 4) + (primitive :rel_primitive_eq date "2021-06-30") + (primitive :rel_primitive_eq amount 25000)))) + (attrs + (attribute :function "checked" 2))))))) + (epoch + (writes + (define + (fragment :car_purchase_fd + (functional_dependency 0xe7a51e3214ced7ef + ([person_id::INT car_id::INT date::STRING amount::INT] + (atom 0x22025b5071a4ea68 person_id car_id date amount)) + (keys car_id date) + (values person_id)))) + (define + (fragment :ownership_model + (def 0xaafa8285ee3a8fc0 + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (and + (atom 0x22025b5071a4ea68 person_id car_id date amount) + (primitive :rel_primitive_gt_eq_monotype amount 20000))))) + (functional_dependency 0xb8662ba7011b5258 + ([person_id::INT car_id::INT] + (and + (atom 0xaafa8285ee3a8fc0 person_id car_id) + (atom 0x6007db63e18e532c person_id))) + (keys person_id) + (values car_id)))))) + (epoch + (writes + (define + (fragment :ownership_model + (def 0xaafa8285ee3a8fc0 + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (atom 0x22025b5071a4ea68 person_id car_id date amount)))) + (functional_dependency 0xdb22feaba0887298 + ([person_id::INT car_id::INT] + (atom 0xaafa8285ee3a8fc0 person_id car_id)) + (keys car_id) + (values person_id)))) + (undefine :emp_model))) + (epoch + (writes + (define + (fragment :query2 + (functional_dependency 0xe1f440a0b3957f3e + ([n::STRING car_id::INT person_id::INT v::STRING] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x8a2539e2b69d9daf car_id v) + (atom 0xaafa8285ee3a8fc0 person_id car_id))) + (keys v) + (values n)) + (def 0x37417896f56cfc7a + ([n::STRING fn::STRING ln::STRING v::STRING] + (exists [person_id::INT car_id::INT] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x5416fbf98c1d659 person_id fn) + (atom 0x2326b8630011d51c person_id ln) + (atom 0xaafa8285ee3a8fc0 person_id car_id) + (atom 0x8a2539e2b69d9daf car_id v)))))))) + (reads + (output :output2 0x37417896f56cfc7a)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe1f440a0b3957f3e` -> `vin_determines_owner` +;; ID `0xefa5ff7eefcfbef0` -> `ssn` +;; ID `0x8a2539e2b69d9daf` -> `vin` +;; ID `0xaafa8285ee3a8fc0` -> `owns` +;; ID `0x37417896f56cfc7a` -> `query2` +;; ID `0x5416fbf98c1d659` -> `first_name` +;; ID `0x2326b8630011d51c` -> `last_name` +;; ID `0x22025b5071a4ea68` -> `purchased_on_for` +;; ID `0xb8662ba7011b5258` -> `car_determines_owner` +;; ID `0x6007db63e18e532c` -> `Person` +;; ID `0xdb22feaba0887298` -> `car_has_at_most_one_owner` +;; ID `0xe7a51e3214ced7ef` -> `date_and_car_determine_person` +;; ID `0xa5cdf07dbbc15892` -> `Car` +;; ID `0xbc9b6f54da25926c` -> `vin_is_car_key` +;; ID `0xd05aa2a15fb3c40e` -> `make` +;; ID `0x2e87d494473e3166` -> `query1` +;; ID `0x426f6eb9e6a97a37` -> `emp_id` +;; ID `0x14014e6a57032789` -> `Employee` +;; ID `0xe5b5fc109170b537` -> `ssn_is_employee_key` +;; ID `0x7634153440f8a51c` -> `emp_id_is_employee_key` +;; ID `0x8e8376f9710788de` -> `ssn_is_person_key` +;; ID `0xc3f56e92809c666` -> `name_is_person_key` diff --git a/python-tools/tests/lqp_debug_output/ffi.lqp b/python-tools/tests/lqp_debug_output/ffi.lqp new file mode 100644 index 00000000..9f5ad85f --- /dev/null +++ b/python-tools/tests/lqp_debug_output/ffi.lqp @@ -0,0 +1,42 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def 0xf3c7807d475073ba + ([v::INT] + (or + (primitive :rel_primitive_eq v 5) + (primitive :rel_primitive_eq v 12) + (primitive :rel_primitive_eq v 3)))) + (def 0x249cb94181ef29a3 + ([ord::INT v::INT] + (ffi :rel_primitive_sort + (args + ([x::INT] + (atom 0xf3c7807d475073ba x))) + (terms ord v)))) + (def 0x6722f23c985dd9fa + ([ord::INT v::INT] + (ffi :rel_primitive_top + (args + ([x::INT] + (atom 0xf3c7807d475073ba x)) + ([limit::INT] + (primitive :rel_primitive_eq limit 2))) + (terms ord v))))))) + (reads + (output :numbers 0xf3c7807d475073ba) + (output :limit_sorted_numbers 0x6722f23c985dd9fa) + (output :sorted_numbers 0x249cb94181ef29a3)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xf3c7807d475073ba` -> `numbers` +;; ID `0x249cb94181ef29a3` -> `sorted_numbers` +;; ID `0x6722f23c985dd9fa` -> `limit_sorted_numbers` diff --git a/python-tools/tests/lqp_debug_output/loops.lqp b/python-tools/tests/lqp_debug_output/loops.lqp new file mode 100644 index 00000000..5b31c9d3 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/loops.lqp @@ -0,0 +1,105 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf394aa7979e5cc5d + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 3) + (primitive :rel_primitive_eq b 4)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 5)) + (and + (primitive :rel_primitive_eq a 5) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 6) + (primitive :rel_primitive_eq b 5))))) + (algorithm 0x6ef788f215cfb10b + (script + (loop + (init + (assign 0x6ef788f215cfb10b + ([n::INT] + (primitive :rel_primitive_eq n 1)))) + (script + (assign 0xc6c1c9a9c8543f1e + ([m::INT] + (or + (atom 0x6ef788f215cfb10b m) + (exists [n::INT] + (and + (atom 0x6ef788f215cfb10b n) + (atom 0xf394aa7979e5cc5d n m)))))) + (break 0xaa9379c9f509f248 + ([] + (ffi :rel_primitive_pairwise_equal + (args + ([n::INT] + (atom 0x6ef788f215cfb10b n)) + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))) + (terms)))) + (assign 0x6ef788f215cfb10b + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))))))) + (algorithm 0xc7575274a20d035b 0x11adcbb69df0bb6 + (script + (loop + (init + (assign 0xc7575274a20d035b + ([n::INT] + (primitive :rel_primitive_eq n 1))) + (assign 0x11adcbb69df0bb6 + ([_n::INT] + (or)))) + (script + (upsert 0x11adcbb69df0bb6 + ([n::INT] + (atom 0xc7575274a20d035b n))) + (assign 0xc6c1c9a9c8543f1e + ([m::INT] + (exists [n::INT] + (and + (and + (atom 0xc7575274a20d035b n) + (atom 0xf394aa7979e5cc5d n m)) + (not + (atom 0x11adcbb69df0bb6 m)))))) + (assign 0xc7575274a20d035b + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))) + (break 0x29b27703f6827092 + ([] + (ffi :rel_primitive_all_empty + (args + ([n::INT] + (atom 0xc7575274a20d035b n))) + (terms))))))))))) + (reads + (output :reachable 0x6ef788f215cfb10b) + (output :reachable_2 0x11adcbb69df0bb6)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xf394aa7979e5cc5d` -> `edges` +;; ID `0x6ef788f215cfb10b` -> `reachable` +;; ID `0xc6c1c9a9c8543f1e` -> `next` +;; ID `0xaa9379c9f509f248` -> `nothing_new` +;; ID `0xc7575274a20d035b` -> `frontier` +;; ID `0x11adcbb69df0bb6` -> `reachable_2` +;; ID `0x29b27703f6827092` -> `empty_frontier` diff --git a/python-tools/tests/lqp_debug_output/missing.lqp b/python-tools/tests/lqp_debug_output/missing.lqp new file mode 100644 index 00000000..3fb8bd1b --- /dev/null +++ b/python-tools/tests/lqp_debug_output/missing.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf032dded6d0944fa + ([v::MISSING] + (primitive :rel_primitive_eq missing v))) + (def 0x6b1d74b99dae825f + ([v::STRING] + (primitive :rel_primitive_eq "missing" v)))))) + (reads + (output :miss1 0xf032dded6d0944fa) + (output :miss2 0x6b1d74b99dae825f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xf032dded6d0944fa` -> `miss1` +;; ID `0x6b1d74b99dae825f` -> `miss2` diff --git a/python-tools/tests/lqp_debug_output/monoid_monus.lqp b/python-tools/tests/lqp_debug_output/monoid_monus.lqp new file mode 100644 index 00000000..9aa728dd --- /dev/null +++ b/python-tools/tests/lqp_debug_output/monoid_monus.lqp @@ -0,0 +1,100 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0xa791366f6f620125 0xd653b016db1da8f5 0x21bbd75cf6530bd 0xec7e008b5f4d05c4 + (script + (loop + (init + (assign 0xa791366f6f620125 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign 0xd653b016db1da8f5 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign 0x21bbd75cf6530bd + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20))))) + (assign 0xec7e008b5f4d05c4 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 7)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 25))))) + (assign 0xa25513c7e0f6eaa8 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20)))) + (attrs + (attribute :function))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (monoid (min INT) 0xa791366f6f620125 + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (monoid (or) 0xd653b016db1da8f5 + ([x::INT y::INT] + (atom 0xa25513c7e0f6eaa8 x y))) + (monus (or) 0x21bbd75cf6530bd + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (monus (sum INT) 0xec7e008b5f4d05c4 + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R1 0xa791366f6f620125) + (output :R2 0xd653b016db1da8f5) + (output :R3 0x21bbd75cf6530bd) + (output :R4 0xec7e008b5f4d05c4)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xa791366f6f620125` -> `R1` +;; ID `0xd653b016db1da8f5` -> `R2` +;; ID `0x21bbd75cf6530bd` -> `R3` +;; ID `0xec7e008b5f4d05c4` -> `R4` +;; ID `0xa25513c7e0f6eaa8` -> `U` +;; ID `0x9cdc6c47aa193ae7` -> `always` diff --git a/python-tools/tests/lqp_debug_output/multiple_export.lqp b/python-tools/tests/lqp_debug_output/multiple_export.lqp new file mode 100644 index 00000000..5f4a6bef --- /dev/null +++ b/python-tools/tests/lqp_debug_output/multiple_export.lqp @@ -0,0 +1,66 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x208b0074ba2817b6 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def 0x2a98c62d6dc8f9c1 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello")))) + (def 0x32310ae0104571ed + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::FLOAT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 6.1)))) + (def 0xa4404e192fa9020f + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::INT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 123))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" 0x208b0074ba2817b6) (column "col2name" 0x2a98c62d6dc8f9c1)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""})) + (export + (export_csv_config + (path "wrong") + (columns (column "blahblah" 0x32310ae0104571ed) (column "foofoo" 0xa4404e192fa9020f)) + { :compression "" + :partition_size 0 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x208b0074ba2817b6` -> `cola1` +;; ID `0x2a98c62d6dc8f9c1` -> `cola2` +;; ID `0x32310ae0104571ed` -> `colb1` +;; ID `0xa4404e192fa9020f` -> `colb2` diff --git a/python-tools/tests/lqp_debug_output/not.lqp b/python-tools/tests/lqp_debug_output/not.lqp new file mode 100644 index 00000000..61271877 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/not.lqp @@ -0,0 +1,20 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :frag + (def 0x9f86d081884c7d65 + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x9f86d081884c7d65` -> `test` diff --git a/python-tools/tests/lqp_debug_output/number_ids.lqp b/python-tools/tests/lqp_debug_output/number_ids.lqp new file mode 100644 index 00000000..eab69eb0 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/number_ids.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x1056e0f555a18ebda7d15 + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) \ No newline at end of file diff --git a/python-tools/tests/lqp_debug_output/outer.lqp b/python-tools/tests/lqp_debug_output/outer.lqp new file mode 100644 index 00000000..ee1ece29 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/outer.lqp @@ -0,0 +1,56 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0x8c2574892063f995 + (script + (loop + (init + (assign 0x8c2574892063f995 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xa25513c7e0f6eaa8 + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (assign 0x7fd7a5b0a5375b09 + ([] + (or))) + (loop + (init) + (script + (upsert 0x8c2574892063f995 + ([a::INT b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (break 0x7fd7a5b0a5375b09 + ([] + (and))))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R 0x8c2574892063f995)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x8c2574892063f995` -> `R` +;; ID `0xa25513c7e0f6eaa8` -> `U` +;; ID `0x9cdc6c47aa193ae7` -> `always` +;; ID `0x7fd7a5b0a5375b09` -> `always2` diff --git a/python-tools/tests/lqp_debug_output/piece_of_q1.lqp b/python-tools/tests/lqp_debug_output/piece_of_q1.lqp new file mode 100644 index 00000000..091291a9 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/piece_of_q1.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x92a5dc04bd6f9fb8 + ([_lineitem::UINT128 _lineitem_l_returnflag::STRING _lineitem_l_linestatus::STRING] + (exists [_lineitem_l_shipdate::DATE _date_limit::DATE] + (and + (relatom :LineItem _lineitem) + (relatom :l_shipdate _lineitem _lineitem_l_shipdate) + (relatom :l_returnflag _lineitem _lineitem_l_returnflag) + (relatom :l_linestatus _lineitem _lineitem_l_linestatus) + (relatom :date_limit _date_limit) + (primitive :rel_primitive_lt_eq_monotype _lineitem_l_shipdate _date_limit)))))))))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x92a5dc04bd6f9fb8` -> `common` diff --git a/python-tools/tests/lqp_debug_output/pragma.lqp b/python-tools/tests/lqp_debug_output/pragma.lqp new file mode 100644 index 00000000..4afc7b94 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/pragma.lqp @@ -0,0 +1,51 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x8c2574892063f995 + ([a::INT b::INT c::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq c 0))))) + (def 0x8de0b3c47f112c59 + ([b::INT a::INT] + (or + (and + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq a 1))))) + (def 0x2c26b46b68ffc68f + ([a::INT b::INT c::INT] + (and + (atom 0x8c2574892063f995 a b c) + (atom 0x8de0b3c47f112c59 b a) + (pragma :rel_primitive_force_var_order c b a))))))) + (reads + (output :foo 0x2c26b46b68ffc68f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x8c2574892063f995` -> `R` +;; ID `0x8de0b3c47f112c59` -> `S` +;; ID `0x2c26b46b68ffc68f` -> `foo` diff --git a/python-tools/tests/lqp_debug_output/primitive_types.lqp b/python-tools/tests/lqp_debug_output/primitive_types.lqp new file mode 100644 index 00000000..52e4a084 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/primitive_types.lqp @@ -0,0 +1,168 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x6da88c34ba124c41 + ([v::INT] + (primitive :rel_primitive_eq v 21))) + (def 0xf6a2efa282ea487e + ([v::INT] + (primitive :rel_primitive_eq v -21))) + (def 0x11f5eb99c00e936a + ([v::INT128] + (primitive :rel_primitive_eq v 21i128))) + (def 0x9930c5b2f0cd6ccb + ([v::INT128] + (primitive :rel_primitive_eq v 85968058283706962486085i128))) + (def 0x602371f9ccea10c8 + ([v::INT128] + (primitive :rel_primitive_eq v -5968058283706962486085i128))) + (def 0xd085cf3027bc148e + ([v::UINT128] + (primitive :rel_primitive_eq v 0x123456789abcdef12345))) + (def 0x76a7e234dc54e9c6 + ([v::FLOAT] + (primitive :rel_primitive_eq v 1.23))) + (def 0xcecffbaf6b2b8ded + ([v::FLOAT] + (primitive :rel_primitive_eq v inf))) + (def 0xc6e98691b0bd6da8 + ([v::FLOAT] + (primitive :rel_primitive_eq v nan))) + (def 0xe87632cd46bd490 + ([v::DATE] + (primitive :rel_primitive_eq v (date 2025 8 1)))) + (def 0x2763d133c5e59ca4 + ([v::DATETIME] + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)))) + (def 0xe7502c799b8f76fb + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_eq v 123.456000d18))) + (def 0x8c25cb3686462e9a + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def 0xb760f44fa5965c24 + ([v::BOOLEAN] + (primitive :rel_primitive_eq v true))) + (def 0x29280a48db1af571 + ([v::INT] + (and + (primitive :rel_primitive_eq v 21) + (atom 0x6da88c34ba124c41 21)))) + (def 0x680d4e76cfe96c15 + ([v::INT] + (and + (primitive :rel_primitive_eq v -21) + (atom 0xf6a2efa282ea487e -21)))) + (def 0xa6d172f21c940600 + ([v::INT128] + (and + (primitive :rel_primitive_eq v 21i128) + (atom 0x11f5eb99c00e936a 21i128)))) + (def 0xabb2f2ab3cbb2da9 + ([v::INT128] + (and + (primitive :rel_primitive_eq v 85968058283706962486085i128) + (atom 0x9930c5b2f0cd6ccb 85968058283706962486085i128)))) + (def 0x7885e01de1cacaa7 + ([v::INT128] + (and + (primitive :rel_primitive_eq v -5968058283706962486085i128) + (atom 0x602371f9ccea10c8 -5968058283706962486085i128)))) + (def 0x6829fcf78cf5b4ff + ([v::UINT128] + (and + (primitive :rel_primitive_eq v 0x123456789abcdef12345) + (atom 0xd085cf3027bc148e 0x123456789abcdef12345)))) + (def 0xa258ef7de76717c3 + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v 1.23) + (atom 0x76a7e234dc54e9c6 1.23)))) + (def 0x1126cea10c852660 + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v inf) + (atom 0xcecffbaf6b2b8ded inf)))) + (def 0xf737d26907ed37ef + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v nan) + (atom 0xc6e98691b0bd6da8 nan)))) + (def 0x23bfa3dfd6ba4ed5 + ([v::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_eq v 123.456000d18) + (atom 0xe7502c799b8f76fb 123.456000d18)))) + (def 0x47bbe0f73840e6e9 + ([v::DATE] + (and + (primitive :rel_primitive_eq v (date 2025 8 1)) + (atom 0xe87632cd46bd490 (date 2025 8 1))))) + (def 0x147e4ac0bf80f683 + ([v::DATETIME] + (and + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (atom 0x2763d133c5e59ca4 (datetime 2025 8 1 20 3 4 123000))))) + (def 0x737b647384c86624 + ([v::STRING] + (and + (primitive :rel_primitive_eq v "hello") + (atom 0x8c25cb3686462e9a "hello")))) + (def 0x431ed2210676d9e9 + ([v::BOOLEAN] + (and + (primitive :rel_primitive_eq v true) + (atom 0xb760f44fa5965c24 true))))))) + (reads + (output :int 0x29280a48db1af571) + (output :int_n 0x680d4e76cfe96c15) + (output :int128_s 0xa6d172f21c940600) + (output :int128_l 0xabb2f2ab3cbb2da9) + (output :int128_n 0x7885e01de1cacaa7) + (output :uint128 0x6829fcf78cf5b4ff) + (output :float 0xa258ef7de76717c3) + (output :float_inf 0x1126cea10c852660) + (output :float_nan 0xf737d26907ed37ef) + (output :dec 0x23bfa3dfd6ba4ed5) + (output :date 0x47bbe0f73840e6e9) + (output :datetime 0x147e4ac0bf80f683) + (output :str 0x737b647384c86624) + (output :bool 0x431ed2210676d9e9)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x6da88c34ba124c41` -> `int` +;; ID `0xf6a2efa282ea487e` -> `int_n` +;; ID `0x11f5eb99c00e936a` -> `int128_s` +;; ID `0x9930c5b2f0cd6ccb` -> `int128_l` +;; ID `0x602371f9ccea10c8` -> `int128_n` +;; ID `0xd085cf3027bc148e` -> `uint128` +;; ID `0x76a7e234dc54e9c6` -> `float` +;; ID `0xcecffbaf6b2b8ded` -> `float_inf` +;; ID `0xc6e98691b0bd6da8` -> `float_nan` +;; ID `0xe87632cd46bd490` -> `date` +;; ID `0x2763d133c5e59ca4` -> `datetime` +;; ID `0xe7502c799b8f76fb` -> `dec` +;; ID `0x8c25cb3686462e9a` -> `str` +;; ID `0xb760f44fa5965c24` -> `bool` +;; ID `0x29280a48db1af571` -> `output_int` +;; ID `0x680d4e76cfe96c15` -> `output_int_n` +;; ID `0xa6d172f21c940600` -> `output_int128_s` +;; ID `0xabb2f2ab3cbb2da9` -> `output_int128_l` +;; ID `0x7885e01de1cacaa7` -> `output_int128_n` +;; ID `0x6829fcf78cf5b4ff` -> `output_uint128` +;; ID `0xa258ef7de76717c3` -> `output_float` +;; ID `0x1126cea10c852660` -> `output_float_inf` +;; ID `0xf737d26907ed37ef` -> `output_float_nan` +;; ID `0x23bfa3dfd6ba4ed5` -> `output_dec` +;; ID `0x47bbe0f73840e6e9` -> `output_date` +;; ID `0x147e4ac0bf80f683` -> `output_datetime` +;; ID `0x737b647384c86624` -> `output_str` +;; ID `0x431ed2210676d9e9` -> `output_bool` diff --git a/python-tools/tests/lqp_debug_output/primitives.lqp b/python-tools/tests/lqp_debug_output/primitives.lqp new file mode 100644 index 00000000..388b53a5 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/primitives.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def 0xe87632cd46bd490 + ([v::DATE] + (primitive :rel_primitive_parse_date "1998-12-01" "Y-m-d" v))) + (def 0x3e6d4b43d473c69d + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_parse_decimal #64 #6 "3.14" v)))))) + (reads + (output :date 0xe87632cd46bd490) + (output :decimal 0x3e6d4b43d473c69d)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe87632cd46bd490` -> `date` +;; ID `0x3e6d4b43d473c69d` -> `decimal` diff --git a/python-tools/tests/lqp_debug_output/quantifier.lqp b/python-tools/tests/lqp_debug_output/quantifier.lqp new file mode 100644 index 00000000..26cfd5f9 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/quantifier.lqp @@ -0,0 +1,241 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :model + (def 0x6840674ed01ced4f + ([person::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Alice" + "age" + 10 + person))) + (def 0xfbbc2c538e81b805 + ([person::UINT128] + (atom 0x6840674ed01ced4f person))) + (def 0xb082d418a6071589 + ([person::UINT128 cvar::STRING] + (and + (primitive :rel_primitive_eq cvar "Alice") + (atom 0x6840674ed01ced4f person)))) + (def 0x83bb72ffe1698e89 + ([person::UINT128 cvar_2::INT] + (and + (primitive :rel_primitive_eq cvar_2 10) + (atom 0x6840674ed01ced4f person)))) + (def 0x74909c19481ff8bf + ([person_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Bob" + "age" + 30 + person_2))) + (def 0xfe81dde3b67ff6d2 + ([person_2::UINT128] + (atom 0x74909c19481ff8bf person_2))) + (def 0x1302477b75c5b231 + ([person_2::UINT128 cvar_3::STRING] + (and + (primitive :rel_primitive_eq cvar_3 "Bob") + (atom 0x74909c19481ff8bf person_2)))) + (def 0xec3becce2c70570 + ([person_2::UINT128 cvar_4::INT] + (and + (primitive :rel_primitive_eq cvar_4 30) + (atom 0x74909c19481ff8bf person_2)))) + (def 0x7128e551be4ef7ab + ([person_3::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3))) + (def 0xc1617e914f3bf3eb + ([person_3::UINT128] + (atom 0x7128e551be4ef7ab person_3))) + (def 0x2c7c7a582829d602 + ([person_3::UINT128 cvar_5::STRING] + (and + (primitive :rel_primitive_eq cvar_5 "Charlie") + (atom 0x7128e551be4ef7ab person_3)))) + (def 0xf76b2fbd07dba9b7 + ([person_3::UINT128 cvar_6::INT] + (and + (primitive :rel_primitive_eq cvar_6 50) + (atom 0x7128e551be4ef7ab person_3)))) + (def 0x9c3f5fe1be5efc0d + ([pet::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet))) + (def 0xd274bd27a48c663a + ([pet::UINT128] + (atom 0x9c3f5fe1be5efc0d pet))) + (def 0xd4d44f33b89fbc6f + ([pet::UINT128 cvar_7::STRING] + (and + (primitive :rel_primitive_eq cvar_7 "boots") + (atom 0x9c3f5fe1be5efc0d pet)))) + (def 0x9bbf8ea02f4e2e77 + ([pet::UINT128 cvar_8::INT] + (and + (primitive :rel_primitive_eq cvar_8 1) + (atom 0x9c3f5fe1be5efc0d pet)))) + (def 0xdcd207982df473e5 + ([pet_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2))) + (def 0xbcc16f2c1e97f5fb + ([pet_2::UINT128] + (atom 0xdcd207982df473e5 pet_2))) + (def 0x3cf86dec0d85fe5f + ([pet_2::UINT128 cvar_9::STRING] + (and + (primitive :rel_primitive_eq cvar_9 "fluffy") + (atom 0xdcd207982df473e5 pet_2)))) + (def 0xa3dc3de98f619aea + ([pet_2::UINT128 cvar_10::INT] + (and + (primitive :rel_primitive_eq cvar_10 3) + (atom 0xdcd207982df473e5 pet_2)))) + (def 0x550ccdfd1d168da2 + ([person_3::UINT128 pet::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet)))) + (def 0xe91a73771a29a1a6 + ([person_3::UINT128 pet_2::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2)))) + (def 0x6007db63e18e532c + ([person_4::UINT128] + (or + (atom 0xfbbc2c538e81b805 person_4) + (atom 0xfe81dde3b67ff6d2 person_4) + (atom 0xc1617e914f3bf3eb person_4)))) + (def 0x8f0d1b30eba57426 + ([pet_3::UINT128] + (or + (atom 0xd274bd27a48c663a pet_3) + (atom 0xbcc16f2c1e97f5fb pet_3)))) + (def 0x3be1d422a46085e1 + ([person_5::UINT128 pet_4::UINT128] + (or + (atom 0x550ccdfd1d168da2 person_5 pet_4) + (atom 0xe91a73771a29a1a6 person_5 pet_4)))) + (def 0x82a3537ff0dbce7e + ([person_6::UINT128 name::STRING] + (or + (atom 0xb082d418a6071589 person_6 name) + (atom 0x1302477b75c5b231 person_6 name) + (atom 0x2c7c7a582829d602 person_6 name)))) + (def 0x76975bdae91351e0 + ([pet_5::UINT128 name_2::STRING] + (or + (atom 0xd4d44f33b89fbc6f pet_5 name_2) + (atom 0x3cf86dec0d85fe5f pet_5 name_2)))) + (def 0x13f54400c82da08 + ([person_7::UINT128 age::INT] + (or + (atom 0x83bb72ffe1698e89 person_7 age) + (atom 0xec3becce2c70570 person_7 age) + (atom 0xf76b2fbd07dba9b7 person_7 age)))) + (def 0xe55f0c9bee47a77d + ([pet_6::UINT128 age_2::INT] + (or + (atom 0x9bbf8ea02f4e2e77 pet_6 age_2) + (atom 0xa3dc3de98f619aea pet_6 age_2)))))))) + (epoch + (writes + (define + (fragment :query + (def 0xe0ee8bb50685e05f + ([cvar::STRING cvar_2::STRING person::UINT128 name::STRING] + (and + (primitive :rel_primitive_eq cvar "cols") + (primitive :rel_primitive_eq cvar_2 "col000") + (atom 0x82a3537ff0dbce7e person name) + (not + (exists [pet::UINT128] + (atom 0x3be1d422a46085e1 person pet))) + (atom 0x6007db63e18e532c person))))))) + (reads + (output :output_0 0xe0ee8bb50685e05f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe0ee8bb50685e05f` -> `output` +;; ID `0x82a3537ff0dbce7e` -> `name` +;; ID `0x3be1d422a46085e1` -> `pets` +;; ID `0x6007db63e18e532c` -> `Person` +;; ID `0x6840674ed01ced4f` -> `_intermediate_1` +;; ID `0xfbbc2c538e81b805` -> `Person_1` +;; ID `0xb082d418a6071589` -> `name_1` +;; ID `0x83bb72ffe1698e89` -> `age_1` +;; ID `0x74909c19481ff8bf` -> `_intermediate_2` +;; ID `0xfe81dde3b67ff6d2` -> `Person_2` +;; ID `0x1302477b75c5b231` -> `name_2` +;; ID `0xec3becce2c70570` -> `age_2` +;; ID `0x7128e551be4ef7ab` -> `_intermediate_3` +;; ID `0xc1617e914f3bf3eb` -> `Person_3` +;; ID `0x2c7c7a582829d602` -> `name_3` +;; ID `0xf76b2fbd07dba9b7` -> `age_3` +;; ID `0x9c3f5fe1be5efc0d` -> `_intermediate_4` +;; ID `0xd274bd27a48c663a` -> `Pet_1` +;; ID `0xd4d44f33b89fbc6f` -> `name_1_2` +;; ID `0x9bbf8ea02f4e2e77` -> `age_1_2` +;; ID `0xdcd207982df473e5` -> `_intermediate_5` +;; ID `0xbcc16f2c1e97f5fb` -> `Pet_2` +;; ID `0x3cf86dec0d85fe5f` -> `name_2_2` +;; ID `0xa3dc3de98f619aea` -> `age_2_2` +;; ID `0x550ccdfd1d168da2` -> `pets_1` +;; ID `0xe91a73771a29a1a6` -> `pets_2` +;; ID `0x8f0d1b30eba57426` -> `Pet` +;; ID `0x76975bdae91351e0` -> `name_4` +;; ID `0x13f54400c82da08` -> `age` +;; ID `0xe55f0c9bee47a77d` -> `age_4` diff --git a/python-tools/tests/lqp_debug_output/redefine_fragment.lqp b/python-tools/tests/lqp_debug_output/redefine_fragment.lqp new file mode 100644 index 00000000..d4eec5e6 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/redefine_fragment.lqp @@ -0,0 +1,35 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xd9298a10d1b07358 + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v))) + (def 0xe0ee8bb50685e05f + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :output_0 0xe0ee8bb50685e05f) + (output :other_0 0xd9298a10d1b07358))) + (epoch + (writes + (undefine :f1) + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::STRING] + (primitive :rel_primitive_eq v "hello")))))) + (reads + (output :output_1 0xe0ee8bb50685e05f) + (output :other_1 0xd9298a10d1b07358)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xd9298a10d1b07358` -> `other` +;; ID `0xe0ee8bb50685e05f` -> `output` diff --git a/python-tools/tests/lqp_debug_output/simple_cast.lqp b/python-tools/tests/lqp_debug_output/simple_cast.lqp new file mode 100644 index 00000000..e48c07a9 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/simple_cast.lqp @@ -0,0 +1,50 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe2e6065690ad915a + ([v::UINT128] + (cast 123 v))) + (def 0x397454023aa6c35c + ([v::INT128] + (cast 123 v))) + (def 0xd70bd60ab9ad9d04 + ([v::(DECIMAL 18 6)] + (cast 1234 v))) + (def 0x20644e8e7c2cc1b3 + ([v::INT] + (exists [d::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_decimal #64 #6 7 d) + (cast d v))))) + (def 0x2ceb1aea6c1b0340 + ([v::(DECIMAL 38 10)] + (cast 12345 v))) + (def 0x48f58ca86700331c + ([v::INT] + (exists [d::(DECIMAL 38 10)] + (and + (primitive :rel_primitive_decimal #128 #10 5 d) + (cast d v)))))))) + (reads + (output :int_uint 0xe2e6065690ad915a) + (output :int_int 0x397454023aa6c35c) + (output :int_dec64 0xd70bd60ab9ad9d04) + (output :dec64_int 0x20644e8e7c2cc1b3) + (output :int_dec128 0x2ceb1aea6c1b0340) + (output :dec128_int 0x48f58ca86700331c)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe2e6065690ad915a` -> `int_uint` +;; ID `0x397454023aa6c35c` -> `int_int` +;; ID `0xd70bd60ab9ad9d04` -> `int_dec64` +;; ID `0x20644e8e7c2cc1b3` -> `dec64_int` +;; ID `0x2ceb1aea6c1b0340` -> `int_dec128` +;; ID `0x48f58ca86700331c` -> `dec128_int` diff --git a/python-tools/tests/lqp_debug_output/simple_export.lqp b/python-tools/tests/lqp_debug_output/simple_export.lqp new file mode 100644 index 00000000..c64e8bcc --- /dev/null +++ b/python-tools/tests/lqp_debug_output/simple_export.lqp @@ -0,0 +1,37 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf030f5088e744d22 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def 0x6f2f3abd5cd439ac + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello"))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" 0xf030f5088e744d22) (column "col2name" 0x6f2f3abd5cd439ac)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xf030f5088e744d22` -> `col1` +;; ID `0x6f2f3abd5cd439ac` -> `col2` diff --git a/python-tools/tests/lqp_debug_output/simple_ic.lqp b/python-tools/tests/lqp_debug_output/simple_ic.lqp new file mode 100644 index 00000000..a8d896d0 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/simple_ic.lqp @@ -0,0 +1,28 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([] + (primitive :rel_primitive_eq 1 1))) + (def 0x3a53db8a2c8a17ee + ([] + (atom 0x2c26b46b68ffc68f ))) + (def 0xe0ee8bb50685e05f + ([] + (atom 0x2c26b46b68ffc68f )))))) + (reads + (output :result 0xe0ee8bb50685e05f) + (abort :abort_1_eq_1 0x3a53db8a2c8a17ee)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x2c26b46b68ffc68f` -> `foo` +;; ID `0x3a53db8a2c8a17ee` -> `abort` +;; ID `0xe0ee8bb50685e05f` -> `output` diff --git a/python-tools/tests/lqp_debug_output/simple_recursion.lqp b/python-tools/tests/lqp_debug_output/simple_recursion.lqp new file mode 100644 index 00000000..51149e6f --- /dev/null +++ b/python-tools/tests/lqp_debug_output/simple_recursion.lqp @@ -0,0 +1,68 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xb4baca894ba024f0 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "a") + (primitive :rel_primitive_eq y "b")))) + (def 0xbee95ea87c7ca866 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "c")))) + (def 0x5aed700ad29d503 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "d")))) + (def 0x651bbd6dbf7b1548 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "d") + (primitive :rel_primitive_eq y "e")))) + (def 0xa1cb100f57e971ca + ([x::STRING y::STRING] + (or + (atom 0xb4baca894ba024f0 x y) + (atom 0xbee95ea87c7ca866 x y) + (atom 0x5aed700ad29d503 x y) + (atom 0x651bbd6dbf7b1548 x y)))) + (def 0x9b337ac875ffe61c + ([x::STRING y::STRING] + (atom 0xa1cb100f57e971ca x y))) + (def 0x1ed02f257edc80df + ([x::STRING z::STRING] + (exists [y::STRING] + (and + (atom 0xa1cb100f57e971ca x y) + (atom 0xa0af9f865bf637e6 y z))))) + (def 0xa0af9f865bf637e6 + ([x::STRING y::STRING] + (or + (atom 0x9b337ac875ffe61c x y) + (atom 0x1ed02f257edc80df x y)))) + (def 0xe0ee8bb50685e05f + ([x::STRING y::STRING] + (atom 0xa0af9f865bf637e6 x y)))))) + (reads + (output :result 0xe0ee8bb50685e05f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xb4baca894ba024f0` -> `edge1` +;; ID `0xbee95ea87c7ca866` -> `edge2` +;; ID `0x5aed700ad29d503` -> `edge3` +;; ID `0x651bbd6dbf7b1548` -> `edge4` +;; ID `0xa1cb100f57e971ca` -> `edge` +;; ID `0x9b337ac875ffe61c` -> `path1` +;; ID `0x1ed02f257edc80df` -> `path2` +;; ID `0xa0af9f865bf637e6` -> `path` +;; ID `0xe0ee8bb50685e05f` -> `output` diff --git a/python-tools/tests/lqp_debug_output/simple_relatom.lqp b/python-tools/tests/lqp_debug_output/simple_relatom.lqp new file mode 100644 index 00000000..9cc67873 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/simple_relatom.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([x::INT] + (relatom :hello x))) + (def 0xfcde2b2edba56bf4 + ([x::INT y::STRING] + (relatom :bar #"sp_str" x #123 y)))))) + (reads + (output :foo 0x2c26b46b68ffc68f) + (output :bar 0xfcde2b2edba56bf4)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x2c26b46b68ffc68f` -> `foo` +;; ID `0xfcde2b2edba56bf4` -> `bar` diff --git a/python-tools/tests/lqp_debug_output/sum_with_groupby.lqp b/python-tools/tests/lqp_debug_output/sum_with_groupby.lqp new file mode 100644 index 00000000..327f24d5 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/sum_with_groupby.lqp @@ -0,0 +1,55 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([category::STRING amount::FLOAT] + (or + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 1.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 10.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 13.0)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 6.34)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 2.82))))) + (def 0x9f5ffef28309853 + ([cat::STRING x::FLOAT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT] + (atom 0x2c26b46b68ffc68f cat num)) + (terms x)))) + (def 0x6c35493a2b937829 + ([cat::STRING x::INT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT one::INT] + (and + (atom 0x2c26b46b68ffc68f cat num) + (primitive :rel_primitive_eq one 1))) + (terms x))))))) + (reads + (output :items_sum 0x9f5ffef28309853) + (output :items_count 0x6c35493a2b937829)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x2c26b46b68ffc68f` -> `foo` +;; ID `0x9f5ffef28309853` -> `sum` +;; ID `0x6c35493a2b937829` -> `count` diff --git a/python-tools/tests/lqp_debug_output/sync.lqp b/python-tools/tests/lqp_debug_output/sync.lqp new file mode 100644 index 00000000..f9fdfcf3 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/sync.lqp @@ -0,0 +1,19 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (sync :foo :bar) + (epoch + (writes + (define + (fragment :frag + (def 0x9f86d081884c7d65 + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x9f86d081884c7d65` -> `test` diff --git a/python-tools/tests/lqp_debug_output/undefined_relation.lqp b/python-tools/tests/lqp_debug_output/undefined_relation.lqp new file mode 100644 index 00000000..e66533b3 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/undefined_relation.lqp @@ -0,0 +1,30 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (atom 0x2cf24dba5fb0a30e v)))))) + (reads + (output :epoch0 0xe0ee8bb50685e05f) + (output :nonexistent 0x7945bc2d6e4fd0a0))) + (epoch + (writes + (define + (fragment :f2 + (def 0x2cf24dba5fb0a30e + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :epoch1 0xe0ee8bb50685e05f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x2cf24dba5fb0a30e` -> `hello` +;; ID `0xe0ee8bb50685e05f` -> `output` diff --git a/python-tools/tests/lqp_debug_output/undefined_relation2.lqp b/python-tools/tests/lqp_debug_output/undefined_relation2.lqp new file mode 100644 index 00000000..320aec72 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/undefined_relation2.lqp @@ -0,0 +1,30 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f2 + (def 0x2cf24dba5fb0a30e + ([v::INT] + (primitive :rel_primitive_eq v 101))))) + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (atom 0x2cf24dba5fb0a30e v)))))) + (reads + (output :epoch0 0xe0ee8bb50685e05f))) + (epoch + (writes + (undefine :f2)) + (reads + (output :epoch1 0xe0ee8bb50685e05f)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xe0ee8bb50685e05f` -> `output` +;; ID `0x2cf24dba5fb0a30e` -> `hello` diff --git a/python-tools/tests/lqp_debug_output/unicode.lqp b/python-tools/tests/lqp_debug_output/unicode.lqp new file mode 100644 index 00000000..af3683d7 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/unicode.lqp @@ -0,0 +1,46 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (csv_data + (csv_locator + (inline_data "id,name,city,greeting\n1,François,Paris,Bonjour\n2,田中,æ±äº¬,ã“ã‚“ã«ã¡ã¯\n3,Müller,München,Grüß Gott\n4,Иван,МоÑква,Привет")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\\" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "id" 0xa56145270ce6b3be [INT INT]) + (column "name" 0x82a3537ff0dbce7e [INT STRING]) + (column "city" 0x11a62c23412b7747 [INT STRING]) + (column "greeting" 0x18f6b0200b6fd32c [INT STRING])) + (asof "2025-01-01T00:00:00Z")) + (def 0x7260ba22cddf4132 + ([id::INT name::STRING city::STRING greeting::STRING] + (exists [row::INT] + (and + (atom 0xa56145270ce6b3be row id) + (atom 0x82a3537ff0dbce7e row name) + (atom 0x11a62c23412b7747 row city) + (atom 0x18f6b0200b6fd32c row greeting)))))))) + (reads + (output :unicode_data 0x7260ba22cddf4132)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xa56145270ce6b3be` -> `id` +;; ID `0x82a3537ff0dbce7e` -> `name` +;; ID `0x11a62c23412b7747` -> `city` +;; ID `0x18f6b0200b6fd32c` -> `greeting` +;; ID `0x7260ba22cddf4132` -> `unicode_data` diff --git a/python-tools/tests/lqp_debug_output/upsert.lqp b/python-tools/tests/lqp_debug_output/upsert.lqp new file mode 100644 index 00000000..ce61b61e --- /dev/null +++ b/python-tools/tests/lqp_debug_output/upsert.lqp @@ -0,0 +1,60 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0xa791366f6f620125 0xd653b016db1da8f5 + (script + (loop + (init + (assign 0xa791366f6f620125 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xd653b016db1da8f5 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xa25513c7e0f6eaa8 + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (upsert 0xa791366f6f620125 + ([a::INT b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (upsert 0xd653b016db1da8f5 + ([a::INT | b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R1 0xa791366f6f620125) + (output :R2 0xd653b016db1da8f5)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0xa791366f6f620125` -> `R1` +;; ID `0xd653b016db1da8f5` -> `R2` +;; ID `0xa25513c7e0f6eaa8` -> `U` +;; ID `0x9cdc6c47aa193ae7` -> `always` diff --git a/python-tools/tests/lqp_debug_output/value_types.lqp b/python-tools/tests/lqp_debug_output/value_types.lqp new file mode 100644 index 00000000..4f0ebfed --- /dev/null +++ b/python-tools/tests/lqp_debug_output/value_types.lqp @@ -0,0 +1,34 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x99d0b9775c18b59e + ([v::(DECIMAL 18 6)] + (relatom :dec64 v))) + (def 0xf889d8ce58451c30 + ([v::(DECIMAL 38 10)] + (relatom :dec128 v))) + (def 0x47bbe0f73840e6e9 + ([v::DATE] + (relatom :date v))) + (def 0x147e4ac0bf80f683 + ([v::DATETIME] + (relatom :datetime v)))))) + (reads + (output :dec64 0x99d0b9775c18b59e) + (output :dec128 0xf889d8ce58451c30) + (output :date 0x47bbe0f73840e6e9) + (output :datetime 0x147e4ac0bf80f683)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x99d0b9775c18b59e` -> `output_decimal64` +;; ID `0xf889d8ce58451c30` -> `output_decimal128` +;; ID `0x47bbe0f73840e6e9` -> `output_date` +;; ID `0x147e4ac0bf80f683` -> `output_datetime` diff --git a/python-tools/tests/lqp_debug_output/values.lqp b/python-tools/tests/lqp_debug_output/values.lqp new file mode 100644 index 00000000..3a1fa200 --- /dev/null +++ b/python-tools/tests/lqp_debug_output/values.lqp @@ -0,0 +1,92 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x6da88c34ba124c41 + ([v::INT] + (or + (primitive :rel_primitive_eq v -9223372036854775808) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 0) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 9223372036854775807)))) + (def 0x2c5a93435dc0f51a + ([v::INT128] + (or + (primitive :rel_primitive_eq v -170141183460469231731687303715884105728i128) + (primitive :rel_primitive_eq v -9223372036854775809i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 0i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 9223372036854775808i128) + (primitive :rel_primitive_eq v 170141183460469231731687303715884105727i128)))) + (def 0xd085cf3027bc148e + ([v::UINT128] + (or + (primitive :rel_primitive_eq v 0x0) + (primitive :rel_primitive_eq v 0x1) + (primitive :rel_primitive_eq v 0xffffffffffffffffffffffffffffffff)))) + (def 0x76a7e234dc54e9c6 + ([v::FLOAT] + (or + (primitive :rel_primitive_eq v -4.5) + (primitive :rel_primitive_eq v -4.4) + (primitive :rel_primitive_eq v 4.4) + (primitive :rel_primitive_eq v 4.5)))) + (def 0xe87632cd46bd490 + ([v::DATE] + (or + (primitive :rel_primitive_eq v (date 1 1 1)) + (primitive :rel_primitive_eq v (date 2024 2 29)) + (primitive :rel_primitive_eq v (date 2025 8 1)) + (primitive :rel_primitive_eq v (date 9999 12 31))))) + (def 0x2763d133c5e59ca4 + ([v::DATETIME] + (or + (primitive :rel_primitive_eq v (datetime 1 1 1 0 0 0 0)) + (primitive :rel_primitive_eq v (datetime 2024 2 29 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 9999 12 31 23 59 59 999000))))) + (def 0xe7502c799b8f76fb + ([v::(DECIMAL 18 6)] + (or + (primitive :rel_primitive_eq v 0.000000d18) + (primitive :rel_primitive_eq v -123.456789d18) + (primitive :rel_primitive_eq v 123.456789d18) + (primitive :rel_primitive_eq v 123456789012.345678d18)))) + (def 0x8c25cb3686462e9a + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def 0xb760f44fa5965c24 + ([v::BOOLEAN] + (or + (primitive :rel_primitive_eq v true) + (primitive :rel_primitive_eq v false))))))) + (reads + (output :int 0x6da88c34ba124c41) + (output :int128 0x2c5a93435dc0f51a) + (output :uint128 0xd085cf3027bc148e) + (output :float 0x76a7e234dc54e9c6) + (output :dec 0xe7502c799b8f76fb) + (output :date 0xe87632cd46bd490) + (output :datetime 0x2763d133c5e59ca4) + (output :str 0x8c25cb3686462e9a) + (output :bool 0xb760f44fa5965c24)))) + +;; Debug information +;; ----------------------- +;; Original names +;; ID `0x6da88c34ba124c41` -> `int` +;; ID `0x2c5a93435dc0f51a` -> `int128` +;; ID `0xd085cf3027bc148e` -> `uint128` +;; ID `0x76a7e234dc54e9c6` -> `float` +;; ID `0xe87632cd46bd490` -> `date` +;; ID `0x2763d133c5e59ca4` -> `datetime` +;; ID `0xe7502c799b8f76fb` -> `dec` +;; ID `0x8c25cb3686462e9a` -> `str` +;; ID `0xb760f44fa5965c24` -> `bool` diff --git a/python-tools/tests/lqp_no_csv_filename_output/multiple_export.lqp b/python-tools/tests/lqp_no_csv_filename_output/multiple_export.lqp new file mode 100644 index 00000000..a079f6bb --- /dev/null +++ b/python-tools/tests/lqp_no_csv_filename_output/multiple_export.lqp @@ -0,0 +1,58 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :cola1 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def :cola2 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello")))) + (def :colb1 + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::FLOAT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 6.1)))) + (def :colb2 + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::INT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 123))))))) + (reads + (export + (export_csv_config + (path "") + (columns (column "col1name" :cola1) (column "col2name" :cola2)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""})) + (export + (export_csv_config + (path "") + (columns (column "blahblah" :colb1) (column "foofoo" :colb2)) + { :compression "" + :partition_size 0 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_no_csv_filename_output/simple_export.lqp b/python-tools/tests/lqp_no_csv_filename_output/simple_export.lqp new file mode 100644 index 00000000..6d3f075f --- /dev/null +++ b/python-tools/tests/lqp_no_csv_filename_output/simple_export.lqp @@ -0,0 +1,31 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :col1 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def :col2 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello"))))))) + (reads + (export + (export_csv_config + (path "") + (columns (column "col1name" :col1) (column "col2name" :col2)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_output/arithmetic.lqp b/python-tools/tests/lqp_output/arithmetic.lqp new file mode 100644 index 00000000..cc331fdf --- /dev/null +++ b/python-tools/tests/lqp_output/arithmetic.lqp @@ -0,0 +1,32 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xbce2264eb3c4d756 + ([plus::(DECIMAL 18 6) minus::(DECIMAL 18 6) mult::(DECIMAL 18 6) div::(DECIMAL 18 6)] + (exists [a::(DECIMAL 18 6) b::(DECIMAL 18 6)] + (and + (relatom :dec_64_a a) + (relatom :dec_64_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div))))) + (def 0x4da0ef183c55619 + ([plus::(DECIMAL 38 10) minus::(DECIMAL 38 10) mult::(DECIMAL 38 10) div::(DECIMAL 38 10)] + (exists [a::(DECIMAL 38 10) b::(DECIMAL 38 10)] + (and + (relatom :dec_128_a a) + (relatom :dec_128_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div)))))))) + (reads + (output :dec_64 0xbce2264eb3c4d756) + (output :dec_128 0x4da0ef183c55619)))) diff --git a/python-tools/tests/lqp_output/attributes.lqp b/python-tools/tests/lqp_output/attributes.lqp new file mode 100644 index 00000000..eb2aa8dd --- /dev/null +++ b/python-tools/tests/lqp_output/attributes.lqp @@ -0,0 +1,26 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4)))) + (attrs + (attribute :function) + (attribute :inspect "normalizer" 2)))))) + (reads + (output :foo 0x2c26b46b68ffc68f)))) diff --git a/python-tools/tests/lqp_output/config_flags.lqp b/python-tools/tests/lqp_output/config_flags.lqp new file mode 100644 index 00000000..df14e8b0 --- /dev/null +++ b/python-tools/tests/lqp_output/config_flags.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "auto" + :optimization_level "aggressive" + :semantics_version 1}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output 0xe0ee8bb50685e05f)))) diff --git a/python-tools/tests/lqp_output/csv.lqp b/python-tools/tests/lqp_output/csv.lqp new file mode 100644 index 00000000..6f3cc26d --- /dev/null +++ b/python-tools/tests/lqp_output/csv.lqp @@ -0,0 +1,106 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (csv_data + (csv_locator + (paths "s3://bucket/data/file1.csv" "s3://bucket/data/file2.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "user_id" 0xf89d6b6960453241 [INT]) + (column "name" 0x2e0d0e00d49ec4d3 [STRING]) + (column "score" 0xd080921d895bacdb [FLOAT])) + (asof "2025-01-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "https://example.com/data.csv")) + (csv_config + { :csv_comment "#" + :csv_compression "gzip" + :csv_decimal_separator "," + :csv_delimiter "|" + :csv_encoding "latin-1" + :csv_escapechar "\\" + :csv_header_row 2 + :csv_missing_strings "NA" + :csv_quotechar "'" + :csv_skip 1}) + (columns + (column "timestamp" 0x44ad63f60af0f6db [DATETIME]) + (column "value" 0x97dfc65f74283f60 [(DECIMAL 18 4)])) + (asof "2025-01-15T12:00:00Z")) + (csv_data + (csv_locator + (inline_data "user_id,name,score\n1,Alice,95.5\n2,Bob,87.3")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "user_id" 0x1802f277114b102f [INT]) + (column "name" 0x26ce8135e472b083 [STRING]) + (column "score" 0x1fbccc1771050306 [FLOAT])) + (asof "2025-01-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "/local/path/data.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "\t" + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "id" 0xbd9cecd5353749e9 [INT STRING]) + (column "data" 0x450b548547f965e [STRING FLOAT BOOLEAN])) + (asof "2025-02-01T00:00:00Z")) + (csv_data + (csv_locator + (paths "data/infer.csv")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\"" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "col1" 0xd7ccbace08a86f7d []) + (column "col2" 0x59fd8313b61172d2 [])) + (asof "2025-03-01T00:00:00Z"))))) + (reads + (output :user_id 0xf89d6b6960453241) + (output :user_name 0x2e0d0e00d49ec4d3) + (output :user_score 0xd080921d895bacdb) + (output :ts 0x44ad63f60af0f6db) + (output :val 0x97dfc65f74283f60) + (output :inline_user_id 0x1802f277114b102f) + (output :inline_user_name 0x26ce8135e472b083) + (output :inline_user_score 0x1fbccc1771050306) + (output :multi_id 0xbd9cecd5353749e9) + (output :multi_data 0x450b548547f965e) + (output :inferred1 0xd7ccbace08a86f7d) + (output :inferred2 0x59fd8313b61172d2)))) diff --git a/python-tools/tests/lqp_output/edb.lqp b/python-tools/tests/lqp_output/edb.lqp new file mode 100644 index 00000000..eaad7827 --- /dev/null +++ b/python-tools/tests/lqp_output/edb.lqp @@ -0,0 +1,126 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (betree_relation 0xa9e35fa05f07f5bc + (betree_info + (key_types INT) + (value_types STRING INT) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 0 + :betree_locator_root_pageid 0x1234567890123456789012 + :betree_locator_tree_height 0})) + (betree_relation 0x9cc5c01c151a49f3 + (betree_info + (key_types INT STRING) + (value_types FLOAT) + { :betree_config_epsilon 0.8 + :betree_config_max_deltas 32 + :betree_config_max_leaf 32 + :betree_config_max_pivots 8 + :betree_locator_element_count 100 + :betree_locator_root_pageid 0xabcdef1234567890abcdef + :betree_locator_tree_height 2})) + (betree_relation 0x22ee775a8c966d84 + (betree_info + (key_types UINT128) + (value_types INT FLOAT (DECIMAL 18 4)) + { :betree_config_epsilon 0.3 + :betree_config_max_deltas 20 + :betree_config_max_leaf 64 + :betree_config_max_pivots 10 + :betree_locator_element_count 500 + :betree_locator_root_pageid 0xfedcba9876543210fedcba + :betree_locator_tree_height 3})) + (betree_relation 0x927cb0b0096c1296 + (betree_info + (key_types DATE) + (value_types DATETIME STRING) + { :betree_config_epsilon 0.6 + :betree_config_max_deltas 24 + :betree_config_max_leaf 48 + :betree_config_max_pivots 6 + :betree_locator_element_count 250 + :betree_locator_root_pageid 0x9999888877776666555544 + :betree_locator_tree_height 2})) + (betree_relation 0xe52f262b796e7dd2 + (betree_info + (key_types STRING) + (value_types BOOLEAN MISSING) + { :betree_config_epsilon 0.7 + :betree_config_max_deltas 15 + :betree_config_max_leaf 20 + :betree_config_max_pivots 5 + :betree_locator_element_count 75 + :betree_locator_root_pageid 0x1111222233334444555566 + :betree_locator_tree_height 1})) + (betree_relation 0x67a0ea198e6e91f9 + (betree_info + (key_types INT STRING) + (value_types) + { :betree_config_epsilon 0.4 + :betree_config_max_deltas 18 + :betree_config_max_leaf 40 + :betree_config_max_pivots 12 + :betree_locator_element_count 10 + :betree_locator_root_pageid 0x7777888899990000111122 + :betree_locator_tree_height 1})) + (rel_edb 0x15840b06a27cfd50 ["my_base_relation"] [INT STRING FLOAT]) + (rel_edb 0xd18eb5ae6b1c6d60 ["another" "path"] [INT STRING]) + (rel_edb 0x1d55ba4ed7a92d94 ["complex" "path" "here"] [(DECIMAL 10 2) INT STRING]) + (rel_edb 0xce18a64a245dea33 ["empty_path"] []) + (def 0x2c26b46b68ffc68f + ([x::INT] + (primitive :rel_primitive_eq x 1))) + (algorithm 0xfcde2b2edba56bf4 0xbaa5a0964d3320fb + (script + (assign 0xfcde2b2edba56bf4 + ([y::INT] + (primitive :rel_primitive_eq y 2))))))) + (define + (fragment :f2 + (betree_relation 0xd7458e7387db7526 + (betree_info + (key_types STRING) + (value_types INT) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 1000 + :betree_locator_root_pageid 0x3333444455556666777788 + :betree_locator_tree_height 4})) + (betree_relation 0x40295aa31ad63d24 + (betree_info + (key_types INT) + (value_types STRING) + { :betree_config_epsilon 0.5 + :betree_config_max_deltas 16 + :betree_config_max_leaf 16 + :betree_config_max_pivots 4 + :betree_locator_element_count 42 + :betree_locator_inline_data "binary_blob_data_here" + :betree_locator_tree_height 1}))))) + (reads + (output :foo 0x2c26b46b68ffc68f) + (output :edb 0xa9e35fa05f07f5bc) + (output :multi_key 0x9cc5c01c151a49f3) + (output :numeric_types 0x22ee775a8c966d84) + (output :temporal_data 0x927cb0b0096c1296) + (output :boolean_data 0xe52f262b796e7dd2) + (output :key_only 0x67a0ea198e6e91f9) + (output :path_simple 0x15840b06a27cfd50) + (output :path_specialized 0xd18eb5ae6b1c6d60) + (output :path_mixed 0x1d55ba4ed7a92d94) + (output :path_empty 0xce18a64a245dea33) + (output :bar 0xfcde2b2edba56bf4) + (output :another_edb 0xd7458e7387db7526) + (output :inline_edb 0x40295aa31ad63d24)))) diff --git a/python-tools/tests/lqp_output/fd.lqp b/python-tools/tests/lqp_output/fd.lqp new file mode 100644 index 00000000..77d4dd9d --- /dev/null +++ b/python-tools/tests/lqp_output/fd.lqp @@ -0,0 +1,206 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :person_model + (def 0x6007db63e18e532c + ([id::INT] + (or + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq id 2)))) + (def 0xefa5ff7eefcfbef0 + ([id::INT n::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq n "SSN#Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq n "SSN#Bob")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0x8e8376f9710788de + ([n::STRING id::INT] + (atom 0xefa5ff7eefcfbef0 id n)) + (keys n) + (values id)) + (def 0x5416fbf98c1d659 + ([id::INT fn::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq fn "Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq fn "Bob")))) + (attrs + (attribute :function "checked"))) + (def 0x2326b8630011d51c + ([id::INT ln::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq ln "Smith")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq ln "Johnson")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xc3f56e92809c666 + ([fn::STRING ln::STRING id::INT] + (and + (atom 0x5416fbf98c1d659 id fn) + (atom 0x2326b8630011d51c id ln))) + (keys fn ln) + (values id)))) + (define + (fragment :emp_model + (def 0x14014e6a57032789 + ([id::INT] + (primitive :rel_primitive_eq id 1))) + (def 0x426f6eb9e6a97a37 + ([id::INT eid::INT] + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq eid 1001))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xe5b5fc109170b537 + ([n::STRING id::INT] + (atom 0xefa5ff7eefcfbef0 id n)) + (keys n) + (values id)) + (functional_dependency 0x7634153440f8a51c + ([eid::INT id::INT] + (atom 0x426f6eb9e6a97a37 id eid)) + (keys eid) + (values id)))) + (define + (fragment :query1 + (def 0x2e87d494473e3166 + ([n::STRING fn::STRING ln::STRING eid::INT] + (exists [person_id::INT] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x5416fbf98c1d659 person_id fn) + (atom 0x2326b8630011d51c person_id ln) + (atom 0x426f6eb9e6a97a37 person_id eid) + (atom 0x14014e6a57032789 person_id)))))))) + (reads + (output :output1 0x2e87d494473e3166))) + (epoch + (writes + (define + (fragment :car_model + (def 0xa5cdf07dbbc15892 + ([id::INT] + (or + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq id 4)))) + (def 0x8a2539e2b69d9daf + ([id::INT v::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq v "VIN#Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq v "VIN#Toyota")))) + (attrs + (attribute :function "checked"))) + (functional_dependency 0xbc9b6f54da25926c + ([v::STRING id::INT] + (atom 0x8a2539e2b69d9daf id v)) + (keys v) + (values id)) + (def 0xd05aa2a15fb3c40e + ([id::INT m::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq m "Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq m "Toyota")))) + (attrs + (attribute :function "checked"))) + (def 0x22025b5071a4ea68 + ([person_id::INT car_id::INT date::STRING amount::INT] + (or + (and + (primitive :rel_primitive_eq person_id 1) + (primitive :rel_primitive_eq car_id 3) + (primitive :rel_primitive_eq date "2020-01-15") + (primitive :rel_primitive_eq amount 20000)) + (and + (primitive :rel_primitive_eq person_id 2) + (primitive :rel_primitive_eq car_id 4) + (primitive :rel_primitive_eq date "2021-06-30") + (primitive :rel_primitive_eq amount 25000)))) + (attrs + (attribute :function "checked" 2))))))) + (epoch + (writes + (define + (fragment :car_purchase_fd + (functional_dependency 0xe7a51e3214ced7ef + ([person_id::INT car_id::INT date::STRING amount::INT] + (atom 0x22025b5071a4ea68 person_id car_id date amount)) + (keys car_id date) + (values person_id)))) + (define + (fragment :ownership_model + (def 0xaafa8285ee3a8fc0 + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (and + (atom 0x22025b5071a4ea68 person_id car_id date amount) + (primitive :rel_primitive_gt_eq_monotype amount 20000))))) + (functional_dependency 0xb8662ba7011b5258 + ([person_id::INT car_id::INT] + (and + (atom 0xaafa8285ee3a8fc0 person_id car_id) + (atom 0x6007db63e18e532c person_id))) + (keys person_id) + (values car_id)))))) + (epoch + (writes + (define + (fragment :ownership_model + (def 0xaafa8285ee3a8fc0 + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (atom 0x22025b5071a4ea68 person_id car_id date amount)))) + (functional_dependency 0xdb22feaba0887298 + ([person_id::INT car_id::INT] + (atom 0xaafa8285ee3a8fc0 person_id car_id)) + (keys car_id) + (values person_id)))) + (undefine :emp_model))) + (epoch + (writes + (define + (fragment :query2 + (functional_dependency 0xe1f440a0b3957f3e + ([n::STRING car_id::INT person_id::INT v::STRING] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x8a2539e2b69d9daf car_id v) + (atom 0xaafa8285ee3a8fc0 person_id car_id))) + (keys v) + (values n)) + (def 0x37417896f56cfc7a + ([n::STRING fn::STRING ln::STRING v::STRING] + (exists [person_id::INT car_id::INT] + (and + (atom 0xefa5ff7eefcfbef0 person_id n) + (atom 0x5416fbf98c1d659 person_id fn) + (atom 0x2326b8630011d51c person_id ln) + (atom 0xaafa8285ee3a8fc0 person_id car_id) + (atom 0x8a2539e2b69d9daf car_id v)))))))) + (reads + (output :output2 0x37417896f56cfc7a)))) diff --git a/python-tools/tests/lqp_output/ffi.lqp b/python-tools/tests/lqp_output/ffi.lqp new file mode 100644 index 00000000..86852a2f --- /dev/null +++ b/python-tools/tests/lqp_output/ffi.lqp @@ -0,0 +1,35 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def 0xf3c7807d475073ba + ([v::INT] + (or + (primitive :rel_primitive_eq v 5) + (primitive :rel_primitive_eq v 12) + (primitive :rel_primitive_eq v 3)))) + (def 0x249cb94181ef29a3 + ([ord::INT v::INT] + (ffi :rel_primitive_sort + (args + ([x::INT] + (atom 0xf3c7807d475073ba x))) + (terms ord v)))) + (def 0x6722f23c985dd9fa + ([ord::INT v::INT] + (ffi :rel_primitive_top + (args + ([x::INT] + (atom 0xf3c7807d475073ba x)) + ([limit::INT] + (primitive :rel_primitive_eq limit 2))) + (terms ord v))))))) + (reads + (output :numbers 0xf3c7807d475073ba) + (output :limit_sorted_numbers 0x6722f23c985dd9fa) + (output :sorted_numbers 0x249cb94181ef29a3)))) diff --git a/python-tools/tests/lqp_output/loops.lqp b/python-tools/tests/lqp_output/loops.lqp new file mode 100644 index 00000000..5aa3db6e --- /dev/null +++ b/python-tools/tests/lqp_output/loops.lqp @@ -0,0 +1,94 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf394aa7979e5cc5d + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 3) + (primitive :rel_primitive_eq b 4)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 5)) + (and + (primitive :rel_primitive_eq a 5) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 6) + (primitive :rel_primitive_eq b 5))))) + (algorithm 0x6ef788f215cfb10b + (script + (loop + (init + (assign 0x6ef788f215cfb10b + ([n::INT] + (primitive :rel_primitive_eq n 1)))) + (script + (assign 0xc6c1c9a9c8543f1e + ([m::INT] + (or + (atom 0x6ef788f215cfb10b m) + (exists [n::INT] + (and + (atom 0x6ef788f215cfb10b n) + (atom 0xf394aa7979e5cc5d n m)))))) + (break 0xaa9379c9f509f248 + ([] + (ffi :rel_primitive_pairwise_equal + (args + ([n::INT] + (atom 0x6ef788f215cfb10b n)) + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))) + (terms)))) + (assign 0x6ef788f215cfb10b + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))))))) + (algorithm 0xc7575274a20d035b 0x11adcbb69df0bb6 + (script + (loop + (init + (assign 0xc7575274a20d035b + ([n::INT] + (primitive :rel_primitive_eq n 1))) + (assign 0x11adcbb69df0bb6 + ([_n::INT] + (or)))) + (script + (upsert 0x11adcbb69df0bb6 + ([n::INT] + (atom 0xc7575274a20d035b n))) + (assign 0xc6c1c9a9c8543f1e + ([m::INT] + (exists [n::INT] + (and + (and + (atom 0xc7575274a20d035b n) + (atom 0xf394aa7979e5cc5d n m)) + (not + (atom 0x11adcbb69df0bb6 m)))))) + (assign 0xc7575274a20d035b + ([n::INT] + (atom 0xc6c1c9a9c8543f1e n))) + (break 0x29b27703f6827092 + ([] + (ffi :rel_primitive_all_empty + (args + ([n::INT] + (atom 0xc7575274a20d035b n))) + (terms))))))))))) + (reads + (output :reachable 0x6ef788f215cfb10b) + (output :reachable_2 0x11adcbb69df0bb6)))) diff --git a/python-tools/tests/lqp_output/missing.lqp b/python-tools/tests/lqp_output/missing.lqp new file mode 100644 index 00000000..bc541153 --- /dev/null +++ b/python-tools/tests/lqp_output/missing.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf032dded6d0944fa + ([v::MISSING] + (primitive :rel_primitive_eq missing v))) + (def 0x6b1d74b99dae825f + ([v::STRING] + (primitive :rel_primitive_eq "missing" v)))))) + (reads + (output :miss1 0xf032dded6d0944fa) + (output :miss2 0x6b1d74b99dae825f)))) diff --git a/python-tools/tests/lqp_output/monoid_monus.lqp b/python-tools/tests/lqp_output/monoid_monus.lqp new file mode 100644 index 00000000..b2c88e3b --- /dev/null +++ b/python-tools/tests/lqp_output/monoid_monus.lqp @@ -0,0 +1,90 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0xa791366f6f620125 0xd653b016db1da8f5 0x21bbd75cf6530bd 0xec7e008b5f4d05c4 + (script + (loop + (init + (assign 0xa791366f6f620125 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign 0xd653b016db1da8f5 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign 0x21bbd75cf6530bd + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20))))) + (assign 0xec7e008b5f4d05c4 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 7)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 25))))) + (assign 0xa25513c7e0f6eaa8 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20)))) + (attrs + (attribute :function))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (monoid (min INT) 0xa791366f6f620125 + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (monoid (or) 0xd653b016db1da8f5 + ([x::INT y::INT] + (atom 0xa25513c7e0f6eaa8 x y))) + (monus (or) 0x21bbd75cf6530bd + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (monus (sum INT) 0xec7e008b5f4d05c4 + ([x::INT | y::INT] + (atom 0xa25513c7e0f6eaa8 x y)) + (attrs + (attribute :function))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R1 0xa791366f6f620125) + (output :R2 0xd653b016db1da8f5) + (output :R3 0x21bbd75cf6530bd) + (output :R4 0xec7e008b5f4d05c4)))) diff --git a/python-tools/tests/lqp_output/multiple_export.lqp b/python-tools/tests/lqp_output/multiple_export.lqp new file mode 100644 index 00000000..cab6f03a --- /dev/null +++ b/python-tools/tests/lqp_output/multiple_export.lqp @@ -0,0 +1,58 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x208b0074ba2817b6 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def 0x2a98c62d6dc8f9c1 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello")))) + (def 0x32310ae0104571ed + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::FLOAT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 6.1)))) + (def 0xa4404e192fa9020f + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::INT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 123))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" 0x208b0074ba2817b6) (column "col2name" 0x2a98c62d6dc8f9c1)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""})) + (export + (export_csv_config + (path "wrong") + (columns (column "blahblah" 0x32310ae0104571ed) (column "foofoo" 0xa4404e192fa9020f)) + { :compression "" + :partition_size 0 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_output/not.lqp b/python-tools/tests/lqp_output/not.lqp new file mode 100644 index 00000000..c75176ec --- /dev/null +++ b/python-tools/tests/lqp_output/not.lqp @@ -0,0 +1,15 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :frag + (def 0x9f86d081884c7d65 + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) diff --git a/python-tools/tests/lqp_output/number_ids.lqp b/python-tools/tests/lqp_output/number_ids.lqp new file mode 100644 index 00000000..957f89eb --- /dev/null +++ b/python-tools/tests/lqp_output/number_ids.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x1056e0f555a18ebda7d15 + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) diff --git a/python-tools/tests/lqp_output/outer.lqp b/python-tools/tests/lqp_output/outer.lqp new file mode 100644 index 00000000..7dc66152 --- /dev/null +++ b/python-tools/tests/lqp_output/outer.lqp @@ -0,0 +1,48 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0x8c2574892063f995 + (script + (loop + (init + (assign 0x8c2574892063f995 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xa25513c7e0f6eaa8 + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (assign 0x7fd7a5b0a5375b09 + ([] + (or))) + (loop + (init) + (script + (upsert 0x8c2574892063f995 + ([a::INT b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (break 0x7fd7a5b0a5375b09 + ([] + (and))))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R 0x8c2574892063f995)))) diff --git a/python-tools/tests/lqp_output/piece_of_q1.lqp b/python-tools/tests/lqp_output/piece_of_q1.lqp new file mode 100644 index 00000000..f1965a27 --- /dev/null +++ b/python-tools/tests/lqp_output/piece_of_q1.lqp @@ -0,0 +1,19 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x92a5dc04bd6f9fb8 + ([_lineitem::UINT128 _lineitem_l_returnflag::STRING _lineitem_l_linestatus::STRING] + (exists [_lineitem_l_shipdate::DATE _date_limit::DATE] + (and + (relatom :LineItem _lineitem) + (relatom :l_shipdate _lineitem _lineitem_l_shipdate) + (relatom :l_returnflag _lineitem _lineitem_l_returnflag) + (relatom :l_linestatus _lineitem _lineitem_l_linestatus) + (relatom :date_limit _date_limit) + (primitive :rel_primitive_lt_eq_monotype _lineitem_l_shipdate _date_limit)))))))))) diff --git a/python-tools/tests/lqp_output/pragma.lqp b/python-tools/tests/lqp_output/pragma.lqp new file mode 100644 index 00000000..611d5a7b --- /dev/null +++ b/python-tools/tests/lqp_output/pragma.lqp @@ -0,0 +1,44 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x8c2574892063f995 + ([a::INT b::INT c::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq c 0))))) + (def 0x8de0b3c47f112c59 + ([b::INT a::INT] + (or + (and + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq a 1))))) + (def 0x2c26b46b68ffc68f + ([a::INT b::INT c::INT] + (and + (atom 0x8c2574892063f995 a b c) + (atom 0x8de0b3c47f112c59 b a) + (pragma :rel_primitive_force_var_order c b a))))))) + (reads + (output :foo 0x2c26b46b68ffc68f)))) diff --git a/python-tools/tests/lqp_output/primitive_types.lqp b/python-tools/tests/lqp_output/primitive_types.lqp new file mode 100644 index 00000000..5ce7ca5a --- /dev/null +++ b/python-tools/tests/lqp_output/primitive_types.lqp @@ -0,0 +1,136 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x6da88c34ba124c41 + ([v::INT] + (primitive :rel_primitive_eq v 21))) + (def 0xf6a2efa282ea487e + ([v::INT] + (primitive :rel_primitive_eq v -21))) + (def 0x11f5eb99c00e936a + ([v::INT128] + (primitive :rel_primitive_eq v 21i128))) + (def 0x9930c5b2f0cd6ccb + ([v::INT128] + (primitive :rel_primitive_eq v 85968058283706962486085i128))) + (def 0x602371f9ccea10c8 + ([v::INT128] + (primitive :rel_primitive_eq v -5968058283706962486085i128))) + (def 0xd085cf3027bc148e + ([v::UINT128] + (primitive :rel_primitive_eq v 0x123456789abcdef12345))) + (def 0x76a7e234dc54e9c6 + ([v::FLOAT] + (primitive :rel_primitive_eq v 1.23))) + (def 0xcecffbaf6b2b8ded + ([v::FLOAT] + (primitive :rel_primitive_eq v inf))) + (def 0xc6e98691b0bd6da8 + ([v::FLOAT] + (primitive :rel_primitive_eq v nan))) + (def 0xe87632cd46bd490 + ([v::DATE] + (primitive :rel_primitive_eq v (date 2025 8 1)))) + (def 0x2763d133c5e59ca4 + ([v::DATETIME] + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)))) + (def 0xe7502c799b8f76fb + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_eq v 123.456000d18))) + (def 0x8c25cb3686462e9a + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def 0xb760f44fa5965c24 + ([v::BOOLEAN] + (primitive :rel_primitive_eq v true))) + (def 0x29280a48db1af571 + ([v::INT] + (and + (primitive :rel_primitive_eq v 21) + (atom 0x6da88c34ba124c41 21)))) + (def 0x680d4e76cfe96c15 + ([v::INT] + (and + (primitive :rel_primitive_eq v -21) + (atom 0xf6a2efa282ea487e -21)))) + (def 0xa6d172f21c940600 + ([v::INT128] + (and + (primitive :rel_primitive_eq v 21i128) + (atom 0x11f5eb99c00e936a 21i128)))) + (def 0xabb2f2ab3cbb2da9 + ([v::INT128] + (and + (primitive :rel_primitive_eq v 85968058283706962486085i128) + (atom 0x9930c5b2f0cd6ccb 85968058283706962486085i128)))) + (def 0x7885e01de1cacaa7 + ([v::INT128] + (and + (primitive :rel_primitive_eq v -5968058283706962486085i128) + (atom 0x602371f9ccea10c8 -5968058283706962486085i128)))) + (def 0x6829fcf78cf5b4ff + ([v::UINT128] + (and + (primitive :rel_primitive_eq v 0x123456789abcdef12345) + (atom 0xd085cf3027bc148e 0x123456789abcdef12345)))) + (def 0xa258ef7de76717c3 + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v 1.23) + (atom 0x76a7e234dc54e9c6 1.23)))) + (def 0x1126cea10c852660 + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v inf) + (atom 0xcecffbaf6b2b8ded inf)))) + (def 0xf737d26907ed37ef + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v nan) + (atom 0xc6e98691b0bd6da8 nan)))) + (def 0x23bfa3dfd6ba4ed5 + ([v::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_eq v 123.456000d18) + (atom 0xe7502c799b8f76fb 123.456000d18)))) + (def 0x47bbe0f73840e6e9 + ([v::DATE] + (and + (primitive :rel_primitive_eq v (date 2025 8 1)) + (atom 0xe87632cd46bd490 (date 2025 8 1))))) + (def 0x147e4ac0bf80f683 + ([v::DATETIME] + (and + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (atom 0x2763d133c5e59ca4 (datetime 2025 8 1 20 3 4 123000))))) + (def 0x737b647384c86624 + ([v::STRING] + (and + (primitive :rel_primitive_eq v "hello") + (atom 0x8c25cb3686462e9a "hello")))) + (def 0x431ed2210676d9e9 + ([v::BOOLEAN] + (and + (primitive :rel_primitive_eq v true) + (atom 0xb760f44fa5965c24 true))))))) + (reads + (output :int 0x29280a48db1af571) + (output :int_n 0x680d4e76cfe96c15) + (output :int128_s 0xa6d172f21c940600) + (output :int128_l 0xabb2f2ab3cbb2da9) + (output :int128_n 0x7885e01de1cacaa7) + (output :uint128 0x6829fcf78cf5b4ff) + (output :float 0xa258ef7de76717c3) + (output :float_inf 0x1126cea10c852660) + (output :float_nan 0xf737d26907ed37ef) + (output :dec 0x23bfa3dfd6ba4ed5) + (output :date 0x47bbe0f73840e6e9) + (output :datetime 0x147e4ac0bf80f683) + (output :str 0x737b647384c86624) + (output :bool 0x431ed2210676d9e9)))) diff --git a/python-tools/tests/lqp_output/primitives.lqp b/python-tools/tests/lqp_output/primitives.lqp new file mode 100644 index 00000000..fc352afe --- /dev/null +++ b/python-tools/tests/lqp_output/primitives.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def 0xe87632cd46bd490 + ([v::DATE] + (primitive :rel_primitive_parse_date "1998-12-01" "Y-m-d" v))) + (def 0x3e6d4b43d473c69d + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_parse_decimal #64 #6 "3.14" v)))))) + (reads + (output :date 0xe87632cd46bd490) + (output :decimal 0x3e6d4b43d473c69d)))) diff --git a/python-tools/tests/lqp_output/quantifier.lqp b/python-tools/tests/lqp_output/quantifier.lqp new file mode 100644 index 00000000..ba642c89 --- /dev/null +++ b/python-tools/tests/lqp_output/quantifier.lqp @@ -0,0 +1,207 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :model + (def 0x6840674ed01ced4f + ([person::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Alice" + "age" + 10 + person))) + (def 0xfbbc2c538e81b805 + ([person::UINT128] + (atom 0x6840674ed01ced4f person))) + (def 0xb082d418a6071589 + ([person::UINT128 cvar::STRING] + (and + (primitive :rel_primitive_eq cvar "Alice") + (atom 0x6840674ed01ced4f person)))) + (def 0x83bb72ffe1698e89 + ([person::UINT128 cvar_2::INT] + (and + (primitive :rel_primitive_eq cvar_2 10) + (atom 0x6840674ed01ced4f person)))) + (def 0x74909c19481ff8bf + ([person_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Bob" + "age" + 30 + person_2))) + (def 0xfe81dde3b67ff6d2 + ([person_2::UINT128] + (atom 0x74909c19481ff8bf person_2))) + (def 0x1302477b75c5b231 + ([person_2::UINT128 cvar_3::STRING] + (and + (primitive :rel_primitive_eq cvar_3 "Bob") + (atom 0x74909c19481ff8bf person_2)))) + (def 0xec3becce2c70570 + ([person_2::UINT128 cvar_4::INT] + (and + (primitive :rel_primitive_eq cvar_4 30) + (atom 0x74909c19481ff8bf person_2)))) + (def 0x7128e551be4ef7ab + ([person_3::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3))) + (def 0xc1617e914f3bf3eb + ([person_3::UINT128] + (atom 0x7128e551be4ef7ab person_3))) + (def 0x2c7c7a582829d602 + ([person_3::UINT128 cvar_5::STRING] + (and + (primitive :rel_primitive_eq cvar_5 "Charlie") + (atom 0x7128e551be4ef7ab person_3)))) + (def 0xf76b2fbd07dba9b7 + ([person_3::UINT128 cvar_6::INT] + (and + (primitive :rel_primitive_eq cvar_6 50) + (atom 0x7128e551be4ef7ab person_3)))) + (def 0x9c3f5fe1be5efc0d + ([pet::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet))) + (def 0xd274bd27a48c663a + ([pet::UINT128] + (atom 0x9c3f5fe1be5efc0d pet))) + (def 0xd4d44f33b89fbc6f + ([pet::UINT128 cvar_7::STRING] + (and + (primitive :rel_primitive_eq cvar_7 "boots") + (atom 0x9c3f5fe1be5efc0d pet)))) + (def 0x9bbf8ea02f4e2e77 + ([pet::UINT128 cvar_8::INT] + (and + (primitive :rel_primitive_eq cvar_8 1) + (atom 0x9c3f5fe1be5efc0d pet)))) + (def 0xdcd207982df473e5 + ([pet_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2))) + (def 0xbcc16f2c1e97f5fb + ([pet_2::UINT128] + (atom 0xdcd207982df473e5 pet_2))) + (def 0x3cf86dec0d85fe5f + ([pet_2::UINT128 cvar_9::STRING] + (and + (primitive :rel_primitive_eq cvar_9 "fluffy") + (atom 0xdcd207982df473e5 pet_2)))) + (def 0xa3dc3de98f619aea + ([pet_2::UINT128 cvar_10::INT] + (and + (primitive :rel_primitive_eq cvar_10 3) + (atom 0xdcd207982df473e5 pet_2)))) + (def 0x550ccdfd1d168da2 + ([person_3::UINT128 pet::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet)))) + (def 0xe91a73771a29a1a6 + ([person_3::UINT128 pet_2::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2)))) + (def 0x6007db63e18e532c + ([person_4::UINT128] + (or + (atom 0xfbbc2c538e81b805 person_4) + (atom 0xfe81dde3b67ff6d2 person_4) + (atom 0xc1617e914f3bf3eb person_4)))) + (def 0x8f0d1b30eba57426 + ([pet_3::UINT128] + (or + (atom 0xd274bd27a48c663a pet_3) + (atom 0xbcc16f2c1e97f5fb pet_3)))) + (def 0x3be1d422a46085e1 + ([person_5::UINT128 pet_4::UINT128] + (or + (atom 0x550ccdfd1d168da2 person_5 pet_4) + (atom 0xe91a73771a29a1a6 person_5 pet_4)))) + (def 0x82a3537ff0dbce7e + ([person_6::UINT128 name::STRING] + (or + (atom 0xb082d418a6071589 person_6 name) + (atom 0x1302477b75c5b231 person_6 name) + (atom 0x2c7c7a582829d602 person_6 name)))) + (def 0x76975bdae91351e0 + ([pet_5::UINT128 name_2::STRING] + (or + (atom 0xd4d44f33b89fbc6f pet_5 name_2) + (atom 0x3cf86dec0d85fe5f pet_5 name_2)))) + (def 0x13f54400c82da08 + ([person_7::UINT128 age::INT] + (or + (atom 0x83bb72ffe1698e89 person_7 age) + (atom 0xec3becce2c70570 person_7 age) + (atom 0xf76b2fbd07dba9b7 person_7 age)))) + (def 0xe55f0c9bee47a77d + ([pet_6::UINT128 age_2::INT] + (or + (atom 0x9bbf8ea02f4e2e77 pet_6 age_2) + (atom 0xa3dc3de98f619aea pet_6 age_2)))))))) + (epoch + (writes + (define + (fragment :query + (def 0xe0ee8bb50685e05f + ([cvar::STRING cvar_2::STRING person::UINT128 name::STRING] + (and + (primitive :rel_primitive_eq cvar "cols") + (primitive :rel_primitive_eq cvar_2 "col000") + (atom 0x82a3537ff0dbce7e person name) + (not + (exists [pet::UINT128] + (atom 0x3be1d422a46085e1 person pet))) + (atom 0x6007db63e18e532c person))))))) + (reads + (output :output_0 0xe0ee8bb50685e05f)))) diff --git a/python-tools/tests/lqp_output/redefine_fragment.lqp b/python-tools/tests/lqp_output/redefine_fragment.lqp new file mode 100644 index 00000000..af0ef9a8 --- /dev/null +++ b/python-tools/tests/lqp_output/redefine_fragment.lqp @@ -0,0 +1,29 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xd9298a10d1b07358 + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v))) + (def 0xe0ee8bb50685e05f + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :output_0 0xe0ee8bb50685e05f) + (output :other_0 0xd9298a10d1b07358))) + (epoch + (writes + (undefine :f1) + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::STRING] + (primitive :rel_primitive_eq v "hello")))))) + (reads + (output :output_1 0xe0ee8bb50685e05f) + (output :other_1 0xd9298a10d1b07358)))) diff --git a/python-tools/tests/lqp_output/simple_cast.lqp b/python-tools/tests/lqp_output/simple_cast.lqp new file mode 100644 index 00000000..40781a61 --- /dev/null +++ b/python-tools/tests/lqp_output/simple_cast.lqp @@ -0,0 +1,40 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe2e6065690ad915a + ([v::UINT128] + (cast 123 v))) + (def 0x397454023aa6c35c + ([v::INT128] + (cast 123 v))) + (def 0xd70bd60ab9ad9d04 + ([v::(DECIMAL 18 6)] + (cast 1234 v))) + (def 0x20644e8e7c2cc1b3 + ([v::INT] + (exists [d::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_decimal #64 #6 7 d) + (cast d v))))) + (def 0x2ceb1aea6c1b0340 + ([v::(DECIMAL 38 10)] + (cast 12345 v))) + (def 0x48f58ca86700331c + ([v::INT] + (exists [d::(DECIMAL 38 10)] + (and + (primitive :rel_primitive_decimal #128 #10 5 d) + (cast d v)))))))) + (reads + (output :int_uint 0xe2e6065690ad915a) + (output :int_int 0x397454023aa6c35c) + (output :int_dec64 0xd70bd60ab9ad9d04) + (output :dec64_int 0x20644e8e7c2cc1b3) + (output :int_dec128 0x2ceb1aea6c1b0340) + (output :dec128_int 0x48f58ca86700331c)))) diff --git a/python-tools/tests/lqp_output/simple_export.lqp b/python-tools/tests/lqp_output/simple_export.lqp new file mode 100644 index 00000000..4adae0c1 --- /dev/null +++ b/python-tools/tests/lqp_output/simple_export.lqp @@ -0,0 +1,31 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xf030f5088e744d22 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def 0x6f2f3abd5cd439ac + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello"))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" 0xf030f5088e744d22) (column "col2name" 0x6f2f3abd5cd439ac)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_output/simple_ic.lqp b/python-tools/tests/lqp_output/simple_ic.lqp new file mode 100644 index 00000000..c7f51013 --- /dev/null +++ b/python-tools/tests/lqp_output/simple_ic.lqp @@ -0,0 +1,21 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([] + (primitive :rel_primitive_eq 1 1))) + (def 0x3a53db8a2c8a17ee + ([] + (atom 0x2c26b46b68ffc68f ))) + (def 0xe0ee8bb50685e05f + ([] + (atom 0x2c26b46b68ffc68f )))))) + (reads + (output :result 0xe0ee8bb50685e05f) + (abort :abort_1_eq_1 0x3a53db8a2c8a17ee)))) diff --git a/python-tools/tests/lqp_output/simple_recursion.lqp b/python-tools/tests/lqp_output/simple_recursion.lqp new file mode 100644 index 00000000..723e2188 --- /dev/null +++ b/python-tools/tests/lqp_output/simple_recursion.lqp @@ -0,0 +1,55 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xb4baca894ba024f0 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "a") + (primitive :rel_primitive_eq y "b")))) + (def 0xbee95ea87c7ca866 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "c")))) + (def 0x5aed700ad29d503 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "d")))) + (def 0x651bbd6dbf7b1548 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "d") + (primitive :rel_primitive_eq y "e")))) + (def 0xa1cb100f57e971ca + ([x::STRING y::STRING] + (or + (atom 0xb4baca894ba024f0 x y) + (atom 0xbee95ea87c7ca866 x y) + (atom 0x5aed700ad29d503 x y) + (atom 0x651bbd6dbf7b1548 x y)))) + (def 0x9b337ac875ffe61c + ([x::STRING y::STRING] + (atom 0xa1cb100f57e971ca x y))) + (def 0x1ed02f257edc80df + ([x::STRING z::STRING] + (exists [y::STRING] + (and + (atom 0xa1cb100f57e971ca x y) + (atom 0xa0af9f865bf637e6 y z))))) + (def 0xa0af9f865bf637e6 + ([x::STRING y::STRING] + (or + (atom 0x9b337ac875ffe61c x y) + (atom 0x1ed02f257edc80df x y)))) + (def 0xe0ee8bb50685e05f + ([x::STRING y::STRING] + (atom 0xa0af9f865bf637e6 x y)))))) + (reads + (output :result 0xe0ee8bb50685e05f)))) diff --git a/python-tools/tests/lqp_output/simple_relatom.lqp b/python-tools/tests/lqp_output/simple_relatom.lqp new file mode 100644 index 00000000..2fb2bb12 --- /dev/null +++ b/python-tools/tests/lqp_output/simple_relatom.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([x::INT] + (relatom :hello x))) + (def 0xfcde2b2edba56bf4 + ([x::INT y::STRING] + (relatom :bar #"sp_str" x #123 y)))))) + (reads + (output :foo 0x2c26b46b68ffc68f) + (output :bar 0xfcde2b2edba56bf4)))) diff --git a/python-tools/tests/lqp_output/sum_with_groupby.lqp b/python-tools/tests/lqp_output/sum_with_groupby.lqp new file mode 100644 index 00000000..547bbff4 --- /dev/null +++ b/python-tools/tests/lqp_output/sum_with_groupby.lqp @@ -0,0 +1,48 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x2c26b46b68ffc68f + ([category::STRING amount::FLOAT] + (or + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 1.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 10.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 13.0)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 6.34)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 2.82))))) + (def 0x9f5ffef28309853 + ([cat::STRING x::FLOAT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT] + (atom 0x2c26b46b68ffc68f cat num)) + (terms x)))) + (def 0x6c35493a2b937829 + ([cat::STRING x::INT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT one::INT] + (and + (atom 0x2c26b46b68ffc68f cat num) + (primitive :rel_primitive_eq one 1))) + (terms x))))))) + (reads + (output :items_sum 0x9f5ffef28309853) + (output :items_count 0x6c35493a2b937829)))) diff --git a/python-tools/tests/lqp_output/sync.lqp b/python-tools/tests/lqp_output/sync.lqp new file mode 100644 index 00000000..f90f689c --- /dev/null +++ b/python-tools/tests/lqp_output/sync.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (sync :foo :bar) + (epoch + (writes + (define + (fragment :frag + (def 0x9f86d081884c7d65 + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))))) diff --git a/python-tools/tests/lqp_output/undefined_relation.lqp b/python-tools/tests/lqp_output/undefined_relation.lqp new file mode 100644 index 00000000..91490417 --- /dev/null +++ b/python-tools/tests/lqp_output/undefined_relation.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (atom 0x2cf24dba5fb0a30e v)))))) + (reads + (output :epoch0 0xe0ee8bb50685e05f) + (output :nonexistent 0x7945bc2d6e4fd0a0))) + (epoch + (writes + (define + (fragment :f2 + (def 0x2cf24dba5fb0a30e + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :epoch1 0xe0ee8bb50685e05f)))) diff --git a/python-tools/tests/lqp_output/undefined_relation2.lqp b/python-tools/tests/lqp_output/undefined_relation2.lqp new file mode 100644 index 00000000..df4172b1 --- /dev/null +++ b/python-tools/tests/lqp_output/undefined_relation2.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f2 + (def 0x2cf24dba5fb0a30e + ([v::INT] + (primitive :rel_primitive_eq v 101))))) + (define + (fragment :f1 + (def 0xe0ee8bb50685e05f + ([v::INT] + (atom 0x2cf24dba5fb0a30e v)))))) + (reads + (output :epoch0 0xe0ee8bb50685e05f))) + (epoch + (writes + (undefine :f2)) + (reads + (output :epoch1 0xe0ee8bb50685e05f)))) diff --git a/python-tools/tests/lqp_output/unicode.lqp b/python-tools/tests/lqp_output/unicode.lqp new file mode 100644 index 00000000..ec9f1b35 --- /dev/null +++ b/python-tools/tests/lqp_output/unicode.lqp @@ -0,0 +1,37 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (csv_data + (csv_locator + (inline_data "id,name,city,greeting\n1,François,Paris,Bonjour\n2,田中,æ±äº¬,ã“ã‚“ã«ã¡ã¯\n3,Müller,München,Grüß Gott\n4,Иван,МоÑква,Привет")) + (csv_config + { :csv_compression "auto" + :csv_decimal_separator "." + :csv_delimiter "," + :csv_encoding "utf-8" + :csv_escapechar "\\" + :csv_header_row 1 + :csv_quotechar "\"" + :csv_skip 0}) + (columns + (column "id" 0xa56145270ce6b3be [INT INT]) + (column "name" 0x82a3537ff0dbce7e [INT STRING]) + (column "city" 0x11a62c23412b7747 [INT STRING]) + (column "greeting" 0x18f6b0200b6fd32c [INT STRING])) + (asof "2025-01-01T00:00:00Z")) + (def 0x7260ba22cddf4132 + ([id::INT name::STRING city::STRING greeting::STRING] + (exists [row::INT] + (and + (atom 0xa56145270ce6b3be row id) + (atom 0x82a3537ff0dbce7e row name) + (atom 0x11a62c23412b7747 row city) + (atom 0x18f6b0200b6fd32c row greeting)))))))) + (reads + (output :unicode_data 0x7260ba22cddf4132)))) diff --git a/python-tools/tests/lqp_output/upsert.lqp b/python-tools/tests/lqp_output/upsert.lqp new file mode 100644 index 00000000..49b2d635 --- /dev/null +++ b/python-tools/tests/lqp_output/upsert.lqp @@ -0,0 +1,52 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm 0xa791366f6f620125 0xd653b016db1da8f5 + (script + (loop + (init + (assign 0xa791366f6f620125 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xd653b016db1da8f5 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign 0xa25513c7e0f6eaa8 + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign 0x9cdc6c47aa193ae7 + ([] + (or)))) + (script + (upsert 0xa791366f6f620125 + ([a::INT b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (upsert 0xd653b016db1da8f5 + ([a::INT | b::INT] + (atom 0xa25513c7e0f6eaa8 a b))) + (break 0x9cdc6c47aa193ae7 + ([] + (and)))))))))) + (reads + (output :R1 0xa791366f6f620125) + (output :R2 0xd653b016db1da8f5)))) diff --git a/python-tools/tests/lqp_output/value_types.lqp b/python-tools/tests/lqp_output/value_types.lqp new file mode 100644 index 00000000..1470b872 --- /dev/null +++ b/python-tools/tests/lqp_output/value_types.lqp @@ -0,0 +1,26 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x99d0b9775c18b59e + ([v::(DECIMAL 18 6)] + (relatom :dec64 v))) + (def 0xf889d8ce58451c30 + ([v::(DECIMAL 38 10)] + (relatom :dec128 v))) + (def 0x47bbe0f73840e6e9 + ([v::DATE] + (relatom :date v))) + (def 0x147e4ac0bf80f683 + ([v::DATETIME] + (relatom :datetime v)))))) + (reads + (output :dec64 0x99d0b9775c18b59e) + (output :dec128 0xf889d8ce58451c30) + (output :date 0x47bbe0f73840e6e9) + (output :datetime 0x147e4ac0bf80f683)))) diff --git a/python-tools/tests/lqp_output/values.lqp b/python-tools/tests/lqp_output/values.lqp new file mode 100644 index 00000000..d176dba3 --- /dev/null +++ b/python-tools/tests/lqp_output/values.lqp @@ -0,0 +1,79 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x6da88c34ba124c41 + ([v::INT] + (or + (primitive :rel_primitive_eq v -9223372036854775808) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 0) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 9223372036854775807)))) + (def 0x2c5a93435dc0f51a + ([v::INT128] + (or + (primitive :rel_primitive_eq v -170141183460469231731687303715884105728i128) + (primitive :rel_primitive_eq v -9223372036854775809i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 0i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 9223372036854775808i128) + (primitive :rel_primitive_eq v 170141183460469231731687303715884105727i128)))) + (def 0xd085cf3027bc148e + ([v::UINT128] + (or + (primitive :rel_primitive_eq v 0x0) + (primitive :rel_primitive_eq v 0x1) + (primitive :rel_primitive_eq v 0xffffffffffffffffffffffffffffffff)))) + (def 0x76a7e234dc54e9c6 + ([v::FLOAT] + (or + (primitive :rel_primitive_eq v -4.5) + (primitive :rel_primitive_eq v -4.4) + (primitive :rel_primitive_eq v 4.4) + (primitive :rel_primitive_eq v 4.5)))) + (def 0xe87632cd46bd490 + ([v::DATE] + (or + (primitive :rel_primitive_eq v (date 1 1 1)) + (primitive :rel_primitive_eq v (date 2024 2 29)) + (primitive :rel_primitive_eq v (date 2025 8 1)) + (primitive :rel_primitive_eq v (date 9999 12 31))))) + (def 0x2763d133c5e59ca4 + ([v::DATETIME] + (or + (primitive :rel_primitive_eq v (datetime 1 1 1 0 0 0 0)) + (primitive :rel_primitive_eq v (datetime 2024 2 29 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 9999 12 31 23 59 59 999000))))) + (def 0xe7502c799b8f76fb + ([v::(DECIMAL 18 6)] + (or + (primitive :rel_primitive_eq v 0.000000d18) + (primitive :rel_primitive_eq v -123.456789d18) + (primitive :rel_primitive_eq v 123.456789d18) + (primitive :rel_primitive_eq v 123456789012.345678d18)))) + (def 0x8c25cb3686462e9a + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def 0xb760f44fa5965c24 + ([v::BOOLEAN] + (or + (primitive :rel_primitive_eq v true) + (primitive :rel_primitive_eq v false))))))) + (reads + (output :int 0x6da88c34ba124c41) + (output :int128 0x2c5a93435dc0f51a) + (output :uint128 0xd085cf3027bc148e) + (output :float 0x76a7e234dc54e9c6) + (output :dec 0xe7502c799b8f76fb) + (output :date 0xe87632cd46bd490) + (output :datetime 0x2763d133c5e59ca4) + (output :str 0x8c25cb3686462e9a) + (output :bool 0xb760f44fa5965c24)))) diff --git a/python-tools/tests/lqp_pretty_output/arithmetic.lqp b/python-tools/tests/lqp_pretty_output/arithmetic.lqp new file mode 100644 index 00000000..a5b8d749 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/arithmetic.lqp @@ -0,0 +1,32 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :decimal_64 + ([plus::(DECIMAL 18 6) minus::(DECIMAL 18 6) mult::(DECIMAL 18 6) div::(DECIMAL 18 6)] + (exists [a::(DECIMAL 18 6) b::(DECIMAL 18 6)] + (and + (relatom :dec_64_a a) + (relatom :dec_64_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div))))) + (def :decimal_128 + ([plus::(DECIMAL 38 10) minus::(DECIMAL 38 10) mult::(DECIMAL 38 10) div::(DECIMAL 38 10)] + (exists [a::(DECIMAL 38 10) b::(DECIMAL 38 10)] + (and + (relatom :dec_128_a a) + (relatom :dec_128_b b) + (primitive :rel_primitive_add_monotype a b plus) + (primitive :rel_primitive_subtract_monotype a b minus) + (primitive :rel_primitive_multiply_monotype a b mult) + (primitive :rel_primitive_divide_monotype a b div)))))))) + (reads + (output :dec_64 :decimal_64) + (output :dec_128 :decimal_128)))) diff --git a/python-tools/tests/lqp_pretty_output/attributes.lqp b/python-tools/tests/lqp_pretty_output/attributes.lqp new file mode 100644 index 00000000..39161d9d --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/attributes.lqp @@ -0,0 +1,26 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :foo + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4)))) + (attrs + (attribute :function) + (attribute :inspect "normalizer" 2)))))) + (reads + (output :foo :foo)))) diff --git a/python-tools/tests/lqp_pretty_output/config_flags.lqp b/python-tools/tests/lqp_pretty_output/config_flags.lqp new file mode 100644 index 00000000..9f41ef95 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/config_flags.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "auto" + :optimization_level "aggressive" + :semantics_version 1}) + (epoch + (writes + (define + (fragment :f1 + (def :output + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output :output)))) diff --git a/python-tools/tests/lqp_pretty_output/fd.lqp b/python-tools/tests/lqp_pretty_output/fd.lqp new file mode 100644 index 00000000..3a2415ee --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/fd.lqp @@ -0,0 +1,206 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :person_model + (def :Person + ([id::INT] + (or + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq id 2)))) + (def :ssn + ([id::INT n::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq n "SSN#Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq n "SSN#Bob")))) + (attrs + (attribute :function "checked"))) + (functional_dependency :ssn_is_person_key + ([n::STRING id::INT] + (atom :ssn id n)) + (keys n) + (values id)) + (def :first_name + ([id::INT fn::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq fn "Alice")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq fn "Bob")))) + (attrs + (attribute :function "checked"))) + (def :last_name + ([id::INT ln::STRING] + (or + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq ln "Smith")) + (and + (primitive :rel_primitive_eq id 2) + (primitive :rel_primitive_eq ln "Johnson")))) + (attrs + (attribute :function "checked"))) + (functional_dependency :name_is_person_key + ([fn::STRING ln::STRING id::INT] + (and + (atom :first_name id fn) + (atom :last_name id ln))) + (keys fn ln) + (values id)))) + (define + (fragment :emp_model + (def :Employee + ([id::INT] + (primitive :rel_primitive_eq id 1))) + (def :emp_id + ([id::INT eid::INT] + (and + (primitive :rel_primitive_eq id 1) + (primitive :rel_primitive_eq eid 1001))) + (attrs + (attribute :function "checked"))) + (functional_dependency :ssn_is_employee_key + ([n::STRING id::INT] + (atom :ssn id n)) + (keys n) + (values id)) + (functional_dependency :emp_id_is_employee_key + ([eid::INT id::INT] + (atom :emp_id id eid)) + (keys eid) + (values id)))) + (define + (fragment :query1 + (def :query1 + ([n::STRING fn::STRING ln::STRING eid::INT] + (exists [person_id::INT] + (and + (atom :ssn person_id n) + (atom :first_name person_id fn) + (atom :last_name person_id ln) + (atom :emp_id person_id eid) + (atom :Employee person_id)))))))) + (reads + (output :output1 :query1))) + (epoch + (writes + (define + (fragment :car_model + (def :Car + ([id::INT] + (or + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq id 4)))) + (def :vin + ([id::INT v::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq v "VIN#Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq v "VIN#Toyota")))) + (attrs + (attribute :function "checked"))) + (functional_dependency :vin_is_car_key + ([v::STRING id::INT] + (atom :vin id v)) + (keys v) + (values id)) + (def :make + ([id::INT m::STRING] + (or + (and + (primitive :rel_primitive_eq id 3) + (primitive :rel_primitive_eq m "Honda")) + (and + (primitive :rel_primitive_eq id 4) + (primitive :rel_primitive_eq m "Toyota")))) + (attrs + (attribute :function "checked"))) + (def :purchased_on_for + ([person_id::INT car_id::INT date::STRING amount::INT] + (or + (and + (primitive :rel_primitive_eq person_id 1) + (primitive :rel_primitive_eq car_id 3) + (primitive :rel_primitive_eq date "2020-01-15") + (primitive :rel_primitive_eq amount 20000)) + (and + (primitive :rel_primitive_eq person_id 2) + (primitive :rel_primitive_eq car_id 4) + (primitive :rel_primitive_eq date "2021-06-30") + (primitive :rel_primitive_eq amount 25000)))) + (attrs + (attribute :function "checked" 2))))))) + (epoch + (writes + (define + (fragment :car_purchase_fd + (functional_dependency :date_and_car_determine_person + ([person_id::INT car_id::INT date::STRING amount::INT] + (atom :purchased_on_for person_id car_id date amount)) + (keys car_id date) + (values person_id)))) + (define + (fragment :ownership_model + (def :owns + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (and + (atom :purchased_on_for person_id car_id date amount) + (primitive :rel_primitive_gt_eq_monotype amount 20000))))) + (functional_dependency :car_determines_owner + ([person_id::INT car_id::INT] + (and + (atom :owns person_id car_id) + (atom :Person person_id))) + (keys person_id) + (values car_id)))))) + (epoch + (writes + (define + (fragment :ownership_model + (def :owns + ([person_id::INT car_id::INT] + (exists [date::STRING amount::INT] + (atom :purchased_on_for person_id car_id date amount)))) + (functional_dependency :car_has_at_most_one_owner + ([person_id::INT car_id::INT] + (atom :owns person_id car_id)) + (keys car_id) + (values person_id)))) + (undefine :emp_model))) + (epoch + (writes + (define + (fragment :query2 + (functional_dependency :vin_determines_owner + ([n::STRING car_id::INT person_id::INT v::STRING] + (and + (atom :ssn person_id n) + (atom :vin car_id v) + (atom :owns person_id car_id))) + (keys v) + (values n)) + (def :query2 + ([n::STRING fn::STRING ln::STRING v::STRING] + (exists [person_id::INT car_id::INT] + (and + (atom :ssn person_id n) + (atom :first_name person_id fn) + (atom :last_name person_id ln) + (atom :owns person_id car_id) + (atom :vin car_id v)))))))) + (reads + (output :output2 :query2)))) diff --git a/python-tools/tests/lqp_pretty_output/ffi.lqp b/python-tools/tests/lqp_pretty_output/ffi.lqp new file mode 100644 index 00000000..7c490d93 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/ffi.lqp @@ -0,0 +1,35 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def :numbers + ([v::INT] + (or + (primitive :rel_primitive_eq v 5) + (primitive :rel_primitive_eq v 12) + (primitive :rel_primitive_eq v 3)))) + (def :sorted_numbers + ([ord::INT v::INT] + (ffi :rel_primitive_sort + (args + ([x::INT] + (atom :numbers x))) + (terms ord v)))) + (def :limit_sorted_numbers + ([ord::INT v::INT] + (ffi :rel_primitive_top + (args + ([x::INT] + (atom :numbers x)) + ([limit::INT] + (primitive :rel_primitive_eq limit 2))) + (terms ord v))))))) + (reads + (output :numbers :numbers) + (output :limit_sorted_numbers :limit_sorted_numbers) + (output :sorted_numbers :sorted_numbers)))) diff --git a/python-tools/tests/lqp_pretty_output/loops.lqp b/python-tools/tests/lqp_pretty_output/loops.lqp new file mode 100644 index 00000000..a0777b1e --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/loops.lqp @@ -0,0 +1,94 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :edges + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 3) + (primitive :rel_primitive_eq b 4)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 5)) + (and + (primitive :rel_primitive_eq a 5) + (primitive :rel_primitive_eq b 3)) + (and + (primitive :rel_primitive_eq a 6) + (primitive :rel_primitive_eq b 5))))) + (algorithm :reachable + (script + (loop + (init + (assign :reachable + ([n::INT] + (primitive :rel_primitive_eq n 1)))) + (script + (assign :next + ([m::INT] + (or + (atom :reachable m) + (exists [n::INT] + (and + (atom :reachable n) + (atom :edges n m)))))) + (break :nothing_new + ([] + (ffi :rel_primitive_pairwise_equal + (args + ([n::INT] + (atom :reachable n)) + ([n::INT] + (atom :next n))) + (terms)))) + (assign :reachable + ([n::INT] + (atom :next n))))))) + (algorithm :frontier :reachable_2 + (script + (loop + (init + (assign :frontier + ([n::INT] + (primitive :rel_primitive_eq n 1))) + (assign :reachable_2 + ([_n::INT] + (or)))) + (script + (upsert :reachable_2 + ([n::INT] + (atom :frontier n))) + (assign :next + ([m::INT] + (exists [n::INT] + (and + (and + (atom :frontier n) + (atom :edges n m)) + (not + (atom :reachable_2 m)))))) + (assign :frontier + ([n::INT] + (atom :next n))) + (break :empty_frontier + ([] + (ffi :rel_primitive_all_empty + (args + ([n::INT] + (atom :frontier n))) + (terms))))))))))) + (reads + (output :reachable :reachable) + (output :reachable_2 :reachable_2)))) diff --git a/python-tools/tests/lqp_pretty_output/missing.lqp b/python-tools/tests/lqp_pretty_output/missing.lqp new file mode 100644 index 00000000..c0e98e84 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/missing.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :miss1 + ([v::MISSING] + (primitive :rel_primitive_eq missing v))) + (def :miss2 + ([v::STRING] + (primitive :rel_primitive_eq "missing" v)))))) + (reads + (output :miss1 :miss1) + (output :miss2 :miss2)))) diff --git a/python-tools/tests/lqp_pretty_output/monoid_monus.lqp b/python-tools/tests/lqp_pretty_output/monoid_monus.lqp new file mode 100644 index 00000000..55b8aaa8 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/monoid_monus.lqp @@ -0,0 +1,90 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm :R1 :R2 :R3 :R4 + (script + (loop + (init + (assign :R1 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign :R2 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 10)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 3))))) + (assign :R3 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20))))) + (assign :R4 + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 7)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 25))))) + (assign :U + ([x::INT y::INT] + (or + (and + (primitive :rel_primitive_eq x 1) + (primitive :rel_primitive_eq y 5)) + (and + (primitive :rel_primitive_eq x 2) + (primitive :rel_primitive_eq y 20)))) + (attrs + (attribute :function))) + (assign :always + ([] + (or)))) + (script + (monoid (min INT) :R1 + ([x::INT | y::INT] + (atom :U x y)) + (attrs + (attribute :function))) + (monoid (or) :R2 + ([x::INT y::INT] + (atom :U x y))) + (monus (or) :R3 + ([x::INT | y::INT] + (atom :U x y)) + (attrs + (attribute :function))) + (monus (sum INT) :R4 + ([x::INT | y::INT] + (atom :U x y)) + (attrs + (attribute :function))) + (break :always + ([] + (and)))))))))) + (reads + (output :R1 :R1) + (output :R2 :R2) + (output :R3 :R3) + (output :R4 :R4)))) diff --git a/python-tools/tests/lqp_pretty_output/multiple_export.lqp b/python-tools/tests/lqp_pretty_output/multiple_export.lqp new file mode 100644 index 00000000..e25ab59e --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/multiple_export.lqp @@ -0,0 +1,58 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :cola1 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def :cola2 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello")))) + (def :colb1 + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::FLOAT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 6.1)))) + (def :colb2 + ([row_1::STRING row_2::(DECIMAL 18 6) row_3::UINT128 row_4::FLOAT v::INT] + (and + (primitive :rel_primitive_eq row_1 "b") + (primitive :rel_primitive_parse_decimal #64 #6 "12.12" row_2) + (primitive :rel_primitive_eq row_3 0x123abc) + (primitive :rel_primitive_eq row_4 1.234) + (primitive :rel_primitive_eq v 123))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" :cola1) (column "col2name" :cola2)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""})) + (export + (export_csv_config + (path "wrong") + (columns (column "blahblah" :colb1) (column "foofoo" :colb2)) + { :compression "" + :partition_size 0 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_pretty_output/not.lqp b/python-tools/tests/lqp_pretty_output/not.lqp new file mode 100644 index 00000000..f755aa26 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/not.lqp @@ -0,0 +1,15 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :frag + (def :test + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) diff --git a/python-tools/tests/lqp_pretty_output/number_ids.lqp b/python-tools/tests/lqp_pretty_output/number_ids.lqp new file mode 100644 index 00000000..957f89eb --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/number_ids.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def 0x1056e0f555a18ebda7d15 + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v)))))) + (reads + (output :output 0x1056e0f555a18ebda7d15)))) diff --git a/python-tools/tests/lqp_pretty_output/outer.lqp b/python-tools/tests/lqp_pretty_output/outer.lqp new file mode 100644 index 00000000..7fb4f2ea --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/outer.lqp @@ -0,0 +1,48 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm :R + (script + (loop + (init + (assign :R + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign :U + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign :always + ([] + (or)))) + (script + (assign :always2 + ([] + (or))) + (loop + (init) + (script + (upsert :R + ([a::INT b::INT] + (atom :U a b))) + (break :always2 + ([] + (and))))) + (break :always + ([] + (and)))))))))) + (reads + (output :R :R)))) diff --git a/python-tools/tests/lqp_pretty_output/piece_of_q1.lqp b/python-tools/tests/lqp_pretty_output/piece_of_q1.lqp new file mode 100644 index 00000000..7d6e49b9 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/piece_of_q1.lqp @@ -0,0 +1,19 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :common + ([_lineitem::UINT128 _lineitem_l_returnflag::STRING _lineitem_l_linestatus::STRING] + (exists [_lineitem_l_shipdate::DATE _date_limit::DATE] + (and + (relatom :LineItem _lineitem) + (relatom :l_shipdate _lineitem _lineitem_l_shipdate) + (relatom :l_returnflag _lineitem _lineitem_l_returnflag) + (relatom :l_linestatus _lineitem _lineitem_l_linestatus) + (relatom :date_limit _date_limit) + (primitive :rel_primitive_lt_eq_monotype _lineitem_l_shipdate _date_limit)))))))))) diff --git a/python-tools/tests/lqp_pretty_output/pragma.lqp b/python-tools/tests/lqp_pretty_output/pragma.lqp new file mode 100644 index 00000000..7a9992ac --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/pragma.lqp @@ -0,0 +1,44 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :R + ([a::INT b::INT c::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq c 0)) + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq c 0))))) + (def :S + ([b::INT a::INT] + (or + (and + (primitive :rel_primitive_eq b 2) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 3) + (primitive :rel_primitive_eq a 1)) + (and + (primitive :rel_primitive_eq b 4) + (primitive :rel_primitive_eq a 1))))) + (def :foo + ([a::INT b::INT c::INT] + (and + (atom :R a b c) + (atom :S b a) + (pragma :rel_primitive_force_var_order c b a))))))) + (reads + (output :foo :foo)))) diff --git a/python-tools/tests/lqp_pretty_output/primitive_types.lqp b/python-tools/tests/lqp_pretty_output/primitive_types.lqp new file mode 100644 index 00000000..c94587e7 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/primitive_types.lqp @@ -0,0 +1,136 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :int + ([v::INT] + (primitive :rel_primitive_eq v 21))) + (def :int_n + ([v::INT] + (primitive :rel_primitive_eq v -21))) + (def :int128_s + ([v::INT128] + (primitive :rel_primitive_eq v 21i128))) + (def :int128_l + ([v::INT128] + (primitive :rel_primitive_eq v 85968058283706962486085i128))) + (def :int128_n + ([v::INT128] + (primitive :rel_primitive_eq v -5968058283706962486085i128))) + (def :uint128 + ([v::UINT128] + (primitive :rel_primitive_eq v 0x123456789abcdef12345))) + (def :float + ([v::FLOAT] + (primitive :rel_primitive_eq v 1.23))) + (def :float_inf + ([v::FLOAT] + (primitive :rel_primitive_eq v inf))) + (def :float_nan + ([v::FLOAT] + (primitive :rel_primitive_eq v nan))) + (def :date + ([v::DATE] + (primitive :rel_primitive_eq v (date 2025 8 1)))) + (def :datetime + ([v::DATETIME] + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)))) + (def :dec + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_eq v 123.456000d18))) + (def :str + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def :bool + ([v::BOOLEAN] + (primitive :rel_primitive_eq v true))) + (def :output_int + ([v::INT] + (and + (primitive :rel_primitive_eq v 21) + (atom :int 21)))) + (def :output_int_n + ([v::INT] + (and + (primitive :rel_primitive_eq v -21) + (atom :int_n -21)))) + (def :output_int128_s + ([v::INT128] + (and + (primitive :rel_primitive_eq v 21i128) + (atom :int128_s 21i128)))) + (def :output_int128_l + ([v::INT128] + (and + (primitive :rel_primitive_eq v 85968058283706962486085i128) + (atom :int128_l 85968058283706962486085i128)))) + (def :output_int128_n + ([v::INT128] + (and + (primitive :rel_primitive_eq v -5968058283706962486085i128) + (atom :int128_n -5968058283706962486085i128)))) + (def :output_uint128 + ([v::UINT128] + (and + (primitive :rel_primitive_eq v 0x123456789abcdef12345) + (atom :uint128 0x123456789abcdef12345)))) + (def :output_float + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v 1.23) + (atom :float 1.23)))) + (def :output_float_inf + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v inf) + (atom :float_inf inf)))) + (def :output_float_nan + ([v::FLOAT] + (and + (primitive :rel_primitive_eq v nan) + (atom :float_nan nan)))) + (def :output_dec + ([v::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_eq v 123.456000d18) + (atom :dec 123.456000d18)))) + (def :output_date + ([v::DATE] + (and + (primitive :rel_primitive_eq v (date 2025 8 1)) + (atom :date (date 2025 8 1))))) + (def :output_datetime + ([v::DATETIME] + (and + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (atom :datetime (datetime 2025 8 1 20 3 4 123000))))) + (def :output_str + ([v::STRING] + (and + (primitive :rel_primitive_eq v "hello") + (atom :str "hello")))) + (def :output_bool + ([v::BOOLEAN] + (and + (primitive :rel_primitive_eq v true) + (atom :bool true))))))) + (reads + (output :int :output_int) + (output :int_n :output_int_n) + (output :int128_s :output_int128_s) + (output :int128_l :output_int128_l) + (output :int128_n :output_int128_n) + (output :uint128 :output_uint128) + (output :float :output_float) + (output :float_inf :output_float_inf) + (output :float_nan :output_float_nan) + (output :dec :output_dec) + (output :date :output_date) + (output :datetime :output_datetime) + (output :str :output_str) + (output :bool :output_bool)))) diff --git a/python-tools/tests/lqp_pretty_output/primitives.lqp b/python-tools/tests/lqp_pretty_output/primitives.lqp new file mode 100644 index 00000000..fcfe6e0e --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/primitives.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :primitives + (def :date + ([v::DATE] + (primitive :rel_primitive_parse_date "1998-12-01" "Y-m-d" v))) + (def :decimal + ([v::(DECIMAL 18 6)] + (primitive :rel_primitive_parse_decimal #64 #6 "3.14" v)))))) + (reads + (output :date :date) + (output :decimal :decimal)))) diff --git a/python-tools/tests/lqp_pretty_output/quantifier.lqp b/python-tools/tests/lqp_pretty_output/quantifier.lqp new file mode 100644 index 00000000..162689fc --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/quantifier.lqp @@ -0,0 +1,207 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :model + (def :_intermediate_1 + ([person::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Alice" + "age" + 10 + person))) + (def :Person_1 + ([person::UINT128] + (atom :_intermediate_1 person))) + (def :name_1 + ([person::UINT128 cvar::STRING] + (and + (primitive :rel_primitive_eq cvar "Alice") + (atom :_intermediate_1 person)))) + (def :age_1 + ([person::UINT128 cvar_2::INT] + (and + (primitive :rel_primitive_eq cvar_2 10) + (atom :_intermediate_1 person)))) + (def :_intermediate_2 + ([person_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Bob" + "age" + 30 + person_2))) + (def :Person_2 + ([person_2::UINT128] + (atom :_intermediate_2 person_2))) + (def :name_2 + ([person_2::UINT128 cvar_3::STRING] + (and + (primitive :rel_primitive_eq cvar_3 "Bob") + (atom :_intermediate_2 person_2)))) + (def :age_2 + ([person_2::UINT128 cvar_4::INT] + (and + (primitive :rel_primitive_eq cvar_4 30) + (atom :_intermediate_2 person_2)))) + (def :_intermediate_3 + ([person_3::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3))) + (def :Person_3 + ([person_3::UINT128] + (atom :_intermediate_3 person_3))) + (def :name_3 + ([person_3::UINT128 cvar_5::STRING] + (and + (primitive :rel_primitive_eq cvar_5 "Charlie") + (atom :_intermediate_3 person_3)))) + (def :age_3 + ([person_3::UINT128 cvar_6::INT] + (and + (primitive :rel_primitive_eq cvar_6 50) + (atom :_intermediate_3 person_3)))) + (def :_intermediate_4 + ([pet::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet))) + (def :Pet_1 + ([pet::UINT128] + (atom :_intermediate_4 pet))) + (def :name_1_2 + ([pet::UINT128 cvar_7::STRING] + (and + (primitive :rel_primitive_eq cvar_7 "boots") + (atom :_intermediate_4 pet)))) + (def :age_1_2 + ([pet::UINT128 cvar_8::INT] + (and + (primitive :rel_primitive_eq cvar_8 1) + (atom :_intermediate_4 pet)))) + (def :_intermediate_5 + ([pet_2::UINT128] + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2))) + (def :Pet_2 + ([pet_2::UINT128] + (atom :_intermediate_5 pet_2))) + (def :name_2_2 + ([pet_2::UINT128 cvar_9::STRING] + (and + (primitive :rel_primitive_eq cvar_9 "fluffy") + (atom :_intermediate_5 pet_2)))) + (def :age_2_2 + ([pet_2::UINT128 cvar_10::INT] + (and + (primitive :rel_primitive_eq cvar_10 3) + (atom :_intermediate_5 pet_2)))) + (def :pets_1 + ([person_3::UINT128 pet::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "boots" + "age" + 1 + pet)))) + (def :pets_2 + ([person_3::UINT128 pet_2::UINT128] + (and + (primitive :rel_primitive_hash_tuple_uint128 + "Person" + "name" + "Charlie" + "age" + 50 + person_3) + (primitive :rel_primitive_hash_tuple_uint128 + "Pet" + "name" + "fluffy" + "age" + 3 + pet_2)))) + (def :Person + ([person_4::UINT128] + (or + (atom :Person_1 person_4) + (atom :Person_2 person_4) + (atom :Person_3 person_4)))) + (def :Pet + ([pet_3::UINT128] + (or + (atom :Pet_1 pet_3) + (atom :Pet_2 pet_3)))) + (def :pets + ([person_5::UINT128 pet_4::UINT128] + (or + (atom :pets_1 person_5 pet_4) + (atom :pets_2 person_5 pet_4)))) + (def :name + ([person_6::UINT128 name::STRING] + (or + (atom :name_1 person_6 name) + (atom :name_2 person_6 name) + (atom :name_3 person_6 name)))) + (def :name_4 + ([pet_5::UINT128 name_2::STRING] + (or + (atom :name_1_2 pet_5 name_2) + (atom :name_2_2 pet_5 name_2)))) + (def :age + ([person_7::UINT128 age::INT] + (or + (atom :age_1 person_7 age) + (atom :age_2 person_7 age) + (atom :age_3 person_7 age)))) + (def :age_4 + ([pet_6::UINT128 age_2::INT] + (or + (atom :age_1_2 pet_6 age_2) + (atom :age_2_2 pet_6 age_2)))))))) + (epoch + (writes + (define + (fragment :query + (def :output + ([cvar::STRING cvar_2::STRING person::UINT128 name::STRING] + (and + (primitive :rel_primitive_eq cvar "cols") + (primitive :rel_primitive_eq cvar_2 "col000") + (atom :name person name) + (not + (exists [pet::UINT128] + (atom :pets person pet))) + (atom :Person person))))))) + (reads + (output :output_0 :output)))) diff --git a/python-tools/tests/lqp_pretty_output/redefine_fragment.lqp b/python-tools/tests/lqp_pretty_output/redefine_fragment.lqp new file mode 100644 index 00000000..f7f01b2a --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/redefine_fragment.lqp @@ -0,0 +1,29 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :other + ([v::INT] + (primitive :rel_primitive_add_monotype 1 1 v))) + (def :output + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :output_0 :output) + (output :other_0 :other))) + (epoch + (writes + (undefine :f1) + (define + (fragment :f1 + (def :output + ([v::STRING] + (primitive :rel_primitive_eq v "hello")))))) + (reads + (output :output_1 :output) + (output :other_1 :other)))) diff --git a/python-tools/tests/lqp_pretty_output/simple_cast.lqp b/python-tools/tests/lqp_pretty_output/simple_cast.lqp new file mode 100644 index 00000000..8e171e6d --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/simple_cast.lqp @@ -0,0 +1,40 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :int_uint + ([v::UINT128] + (cast 123 v))) + (def :int_int + ([v::INT128] + (cast 123 v))) + (def :int_dec64 + ([v::(DECIMAL 18 6)] + (cast 1234 v))) + (def :dec64_int + ([v::INT] + (exists [d::(DECIMAL 18 6)] + (and + (primitive :rel_primitive_decimal #64 #6 7 d) + (cast d v))))) + (def :int_dec128 + ([v::(DECIMAL 38 10)] + (cast 12345 v))) + (def :dec128_int + ([v::INT] + (exists [d::(DECIMAL 38 10)] + (and + (primitive :rel_primitive_decimal #128 #10 5 d) + (cast d v)))))))) + (reads + (output :int_uint :int_uint) + (output :int_int :int_int) + (output :int_dec64 :int_dec64) + (output :dec64_int :dec64_int) + (output :int_dec128 :int_dec128) + (output :dec128_int :dec128_int)))) diff --git a/python-tools/tests/lqp_pretty_output/simple_export.lqp b/python-tools/tests/lqp_pretty_output/simple_export.lqp new file mode 100644 index 00000000..476e4259 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/simple_export.lqp @@ -0,0 +1,31 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :col1 + ([row::INT v::INT] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq 2 v)))) + (def :col2 + ([row::INT v::STRING] + (and + (primitive :rel_primitive_eq row 1) + (primitive :rel_primitive_eq v "hello"))))))) + (reads + (export + (export_csv_config + (path "wrong") + (columns (column "col1name" :col1) (column "col2name" :col2)) + { :compression "" + :partition_size 10 + :syntax_delim "," + :syntax_escapechar "\\" + :syntax_header_row 1 + :syntax_missing_string "" + :syntax_quotechar "\""}))))) diff --git a/python-tools/tests/lqp_pretty_output/simple_ic.lqp b/python-tools/tests/lqp_pretty_output/simple_ic.lqp new file mode 100644 index 00000000..14d57153 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/simple_ic.lqp @@ -0,0 +1,21 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :foo + ([] + (primitive :rel_primitive_eq 1 1))) + (def :abort + ([] + (atom :foo ))) + (def :output + ([] + (atom :foo )))))) + (reads + (output :result :output) + (abort :abort_1_eq_1 :abort)))) diff --git a/python-tools/tests/lqp_pretty_output/simple_recursion.lqp b/python-tools/tests/lqp_pretty_output/simple_recursion.lqp new file mode 100644 index 00000000..4e886134 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/simple_recursion.lqp @@ -0,0 +1,55 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :edge1 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "a") + (primitive :rel_primitive_eq y "b")))) + (def :edge2 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "c")))) + (def :edge3 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "b") + (primitive :rel_primitive_eq y "d")))) + (def :edge4 + ([x::STRING y::STRING] + (and + (primitive :rel_primitive_eq x "d") + (primitive :rel_primitive_eq y "e")))) + (def :edge + ([x::STRING y::STRING] + (or + (atom :edge1 x y) + (atom :edge2 x y) + (atom :edge3 x y) + (atom :edge4 x y)))) + (def :path1 + ([x::STRING y::STRING] + (atom :edge x y))) + (def :path2 + ([x::STRING z::STRING] + (exists [y::STRING] + (and + (atom :edge x y) + (atom :path y z))))) + (def :path + ([x::STRING y::STRING] + (or + (atom :path1 x y) + (atom :path2 x y)))) + (def :output + ([x::STRING y::STRING] + (atom :path x y)))))) + (reads + (output :result :output)))) diff --git a/python-tools/tests/lqp_pretty_output/simple_relatom.lqp b/python-tools/tests/lqp_pretty_output/simple_relatom.lqp new file mode 100644 index 00000000..5c84fdfe --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/simple_relatom.lqp @@ -0,0 +1,18 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :foo + ([x::INT] + (relatom :hello x))) + (def :bar + ([x::INT y::STRING] + (relatom :bar #"sp_str" x #123 y)))))) + (reads + (output :foo :foo) + (output :bar :bar)))) diff --git a/python-tools/tests/lqp_pretty_output/sum_with_groupby.lqp b/python-tools/tests/lqp_pretty_output/sum_with_groupby.lqp new file mode 100644 index 00000000..9563b45e --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/sum_with_groupby.lqp @@ -0,0 +1,48 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :foo + ([category::STRING amount::FLOAT] + (or + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 1.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 10.23)) + (and + (primitive :rel_primitive_eq category "food") + (primitive :rel_primitive_eq amount 13.0)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 6.34)) + (and + (primitive :rel_primitive_eq category "drink") + (primitive :rel_primitive_eq amount 2.82))))) + (def :sum + ([cat::STRING x::FLOAT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT] + (atom :foo cat num)) + (terms x)))) + (def :count + ([cat::STRING x::INT] + (reduce + ([a::FLOAT b::FLOAT c::FLOAT] + (primitive :rel_primitive_add_monotype a b c)) + ([num::FLOAT one::INT] + (and + (atom :foo cat num) + (primitive :rel_primitive_eq one 1))) + (terms x))))))) + (reads + (output :items_sum :sum) + (output :items_count :count)))) diff --git a/python-tools/tests/lqp_pretty_output/sync.lqp b/python-tools/tests/lqp_pretty_output/sync.lqp new file mode 100644 index 00000000..12888474 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/sync.lqp @@ -0,0 +1,14 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (sync :foo :bar) + (epoch + (writes + (define + (fragment :frag + (def :test + ([x::INT y::INT] + (not + (primitive :rel_primitive_eq x y))))))))) diff --git a/python-tools/tests/lqp_pretty_output/undefined_relation.lqp b/python-tools/tests/lqp_pretty_output/undefined_relation.lqp new file mode 100644 index 00000000..6b1373a2 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/undefined_relation.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :output + ([v::INT] + (atom :hello v)))))) + (reads + (output :epoch0 :output) + (output :nonexistent 0x7945bc2d6e4fd0a0))) + (epoch + (writes + (define + (fragment :f2 + (def :hello + ([v::INT] + (primitive :rel_primitive_eq v 101)))))) + (reads + (output :epoch1 :output)))) diff --git a/python-tools/tests/lqp_pretty_output/undefined_relation2.lqp b/python-tools/tests/lqp_pretty_output/undefined_relation2.lqp new file mode 100644 index 00000000..13361409 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/undefined_relation2.lqp @@ -0,0 +1,24 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f2 + (def :hello + ([v::INT] + (primitive :rel_primitive_eq v 101))))) + (define + (fragment :f1 + (def :output + ([v::INT] + (atom :hello v)))))) + (reads + (output :epoch0 :output))) + (epoch + (writes + (undefine :f2)) + (reads + (output :epoch1 :output)))) diff --git a/python-tools/tests/lqp_pretty_output/upsert.lqp b/python-tools/tests/lqp_pretty_output/upsert.lqp new file mode 100644 index 00000000..09442745 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/upsert.lqp @@ -0,0 +1,52 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (algorithm :R1 :R2 + (script + (loop + (init + (assign :R1 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign :R2 + ([a::INT b::INT] + (or + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 2)) + (and + (primitive :rel_primitive_eq a 2) + (primitive :rel_primitive_eq b 3))))) + (assign :U + ([a::INT b::INT] + (and + (primitive :rel_primitive_eq a 1) + (primitive :rel_primitive_eq b 3)))) + (assign :always + ([] + (or)))) + (script + (upsert :R1 + ([a::INT b::INT] + (atom :U a b))) + (upsert :R2 + ([a::INT | b::INT] + (atom :U a b))) + (break :always + ([] + (and)))))))))) + (reads + (output :R1 :R1) + (output :R2 :R2)))) diff --git a/python-tools/tests/lqp_pretty_output/value_types.lqp b/python-tools/tests/lqp_pretty_output/value_types.lqp new file mode 100644 index 00000000..630fe6c6 --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/value_types.lqp @@ -0,0 +1,26 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :output_decimal64 + ([v::(DECIMAL 18 6)] + (relatom :dec64 v))) + (def :output_decimal128 + ([v::(DECIMAL 38 10)] + (relatom :dec128 v))) + (def :output_date + ([v::DATE] + (relatom :date v))) + (def :output_datetime + ([v::DATETIME] + (relatom :datetime v)))))) + (reads + (output :dec64 :output_decimal64) + (output :dec128 :output_decimal128) + (output :date :output_date) + (output :datetime :output_datetime)))) diff --git a/python-tools/tests/lqp_pretty_output/values.lqp b/python-tools/tests/lqp_pretty_output/values.lqp new file mode 100644 index 00000000..bfe545ae --- /dev/null +++ b/python-tools/tests/lqp_pretty_output/values.lqp @@ -0,0 +1,79 @@ +(transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) + (epoch + (writes + (define + (fragment :f1 + (def :int + ([v::INT] + (or + (primitive :rel_primitive_eq v -9223372036854775808) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 0) + (primitive :rel_primitive_eq v 21) + (primitive :rel_primitive_eq v 9223372036854775807)))) + (def :int128 + ([v::INT128] + (or + (primitive :rel_primitive_eq v -170141183460469231731687303715884105728i128) + (primitive :rel_primitive_eq v -9223372036854775809i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 0i128) + (primitive :rel_primitive_eq v 21i128) + (primitive :rel_primitive_eq v 9223372036854775808i128) + (primitive :rel_primitive_eq v 170141183460469231731687303715884105727i128)))) + (def :uint128 + ([v::UINT128] + (or + (primitive :rel_primitive_eq v 0x0) + (primitive :rel_primitive_eq v 0x1) + (primitive :rel_primitive_eq v 0xffffffffffffffffffffffffffffffff)))) + (def :float + ([v::FLOAT] + (or + (primitive :rel_primitive_eq v -4.5) + (primitive :rel_primitive_eq v -4.4) + (primitive :rel_primitive_eq v 4.4) + (primitive :rel_primitive_eq v 4.5)))) + (def :date + ([v::DATE] + (or + (primitive :rel_primitive_eq v (date 1 1 1)) + (primitive :rel_primitive_eq v (date 2024 2 29)) + (primitive :rel_primitive_eq v (date 2025 8 1)) + (primitive :rel_primitive_eq v (date 9999 12 31))))) + (def :datetime + ([v::DATETIME] + (or + (primitive :rel_primitive_eq v (datetime 1 1 1 0 0 0 0)) + (primitive :rel_primitive_eq v (datetime 2024 2 29 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 2025 8 1 20 3 4 123000)) + (primitive :rel_primitive_eq v (datetime 9999 12 31 23 59 59 999000))))) + (def :dec + ([v::(DECIMAL 18 6)] + (or + (primitive :rel_primitive_eq v 0.000000d18) + (primitive :rel_primitive_eq v -123.456789d18) + (primitive :rel_primitive_eq v 123.456789d18) + (primitive :rel_primitive_eq v 123456789012.345678d18)))) + (def :str + ([v::STRING] + (primitive :rel_primitive_eq v "hello"))) + (def :bool + ([v::BOOLEAN] + (or + (primitive :rel_primitive_eq v true) + (primitive :rel_primitive_eq v false))))))) + (reads + (output :int :int) + (output :int128 :int128) + (output :uint128 :uint128) + (output :float :float) + (output :dec :dec) + (output :date :date) + (output :datetime :datetime) + (output :str :str) + (output :bool :bool)))) diff --git a/python-tools/tests/test_files/bin/config_flags.bin b/python-tools/tests/test_files/bin/config_flags.bin new file mode 100644 index 00000000..69f1e6cd Binary files /dev/null and b/python-tools/tests/test_files/bin/config_flags.bin differ diff --git a/python-tools/tests/test_files/bin/csv.bin b/python-tools/tests/test_files/bin/csv.bin new file mode 100644 index 00000000..2e36652c Binary files /dev/null and b/python-tools/tests/test_files/bin/csv.bin differ diff --git a/python-tools/tests/test_files/bin/edb.bin b/python-tools/tests/test_files/bin/edb.bin new file mode 100644 index 00000000..85beaefd Binary files /dev/null and b/python-tools/tests/test_files/bin/edb.bin differ diff --git a/python-tools/tests/test_files/bin/fd.bin b/python-tools/tests/test_files/bin/fd.bin new file mode 100644 index 00000000..89eb7c52 Binary files /dev/null and b/python-tools/tests/test_files/bin/fd.bin differ diff --git a/python-tools/tests/test_files/bin/ffi.bin b/python-tools/tests/test_files/bin/ffi.bin new file mode 100644 index 00000000..5a330c1d Binary files /dev/null and b/python-tools/tests/test_files/bin/ffi.bin differ diff --git a/python-tools/tests/test_files/bin/loops.bin b/python-tools/tests/test_files/bin/loops.bin new file mode 100644 index 00000000..d3909000 Binary files /dev/null and b/python-tools/tests/test_files/bin/loops.bin differ diff --git a/python-tools/tests/test_files/bin/missing.bin b/python-tools/tests/test_files/bin/missing.bin new file mode 100644 index 00000000..2505fdff Binary files /dev/null and b/python-tools/tests/test_files/bin/missing.bin differ diff --git a/python-tools/tests/test_files/bin/not.bin b/python-tools/tests/test_files/bin/not.bin new file mode 100644 index 00000000..e524af2c Binary files /dev/null and b/python-tools/tests/test_files/bin/not.bin differ diff --git a/python-tools/tests/test_files/bin/outer.bin b/python-tools/tests/test_files/bin/outer.bin new file mode 100644 index 00000000..ac0177bf Binary files /dev/null and b/python-tools/tests/test_files/bin/outer.bin differ diff --git a/python-tools/tests/test_files/bin/primitive_types.bin b/python-tools/tests/test_files/bin/primitive_types.bin new file mode 100644 index 00000000..85b90179 Binary files /dev/null and b/python-tools/tests/test_files/bin/primitive_types.bin differ diff --git a/python-tools/tests/test_files/bin/primitives.bin b/python-tools/tests/test_files/bin/primitives.bin new file mode 100644 index 00000000..4f7b8d97 Binary files /dev/null and b/python-tools/tests/test_files/bin/primitives.bin differ diff --git a/python-tools/tests/test_files/bin/quantifier.bin b/python-tools/tests/test_files/bin/quantifier.bin new file mode 100644 index 00000000..ead4e7aa Binary files /dev/null and b/python-tools/tests/test_files/bin/quantifier.bin differ diff --git a/python-tools/tests/test_files/bin/redefine_fragment.bin b/python-tools/tests/test_files/bin/redefine_fragment.bin new file mode 100644 index 00000000..d8e48837 Binary files /dev/null and b/python-tools/tests/test_files/bin/redefine_fragment.bin differ diff --git a/python-tools/tests/test_files/bin/simple_cast.bin b/python-tools/tests/test_files/bin/simple_cast.bin new file mode 100644 index 00000000..1a6cb371 Binary files /dev/null and b/python-tools/tests/test_files/bin/simple_cast.bin differ diff --git a/python-tools/tests/test_files/bin/simple_export.bin b/python-tools/tests/test_files/bin/simple_export.bin new file mode 100644 index 00000000..e7f31573 Binary files /dev/null and b/python-tools/tests/test_files/bin/simple_export.bin differ diff --git a/python-tools/tests/test_files/bin/simple_ic.bin b/python-tools/tests/test_files/bin/simple_ic.bin new file mode 100644 index 00000000..ff2c6381 --- /dev/null +++ b/python-tools/tests/test_files/bin/simple_ic.bin @@ -0,0 +1,21 @@ + +ñ +º +· +´ + +f15 +3 + Æÿhk´&,&$J" +rel_primitive_eq + + îŠ,ŠÛS: : + Æÿhk´&, + + _à…µ‹îà : + Æÿhk´&,5 + Æÿhk´&, + îŠ,ŠÛS: + _à…µ‹îàfooabortoutput +result _à…µ‹îà" + abort_1_eq_1 îŠ,ŠÛS: \ No newline at end of file diff --git a/python-tools/tests/test_files/bin/simple_recursion.bin b/python-tools/tests/test_files/bin/simple_recursion.bin new file mode 100644 index 00000000..63dfc8bc Binary files /dev/null and b/python-tools/tests/test_files/bin/simple_recursion.bin differ diff --git a/python-tools/tests/test_files/bin/simple_relatom.bin b/python-tools/tests/test_files/bin/simple_relatom.bin new file mode 100644 index 00000000..cd0c9464 Binary files /dev/null and b/python-tools/tests/test_files/bin/simple_relatom.bin differ diff --git a/python-tools/tests/test_files/bin/sync.bin b/python-tools/tests/test_files/bin/sync.bin new file mode 100644 index 00000000..664739da Binary files /dev/null and b/python-tools/tests/test_files/bin/sync.bin differ diff --git a/python-tools/tests/test_files/bin/undefined_relation.bin b/python-tools/tests/test_files/bin/undefined_relation.bin new file mode 100644 index 00000000..f22c5b6d Binary files /dev/null and b/python-tools/tests/test_files/bin/undefined_relation.bin differ diff --git a/python-tools/tests/test_files/bin/undefined_relation2.bin b/python-tools/tests/test_files/bin/undefined_relation2.bin new file mode 100644 index 00000000..89dd79db Binary files /dev/null and b/python-tools/tests/test_files/bin/undefined_relation2.bin differ diff --git a/python-tools/tests/test_files/bin/unicode.bin b/python-tools/tests/test_files/bin/unicode.bin new file mode 100644 index 00000000..8645b0a2 Binary files /dev/null and b/python-tools/tests/test_files/bin/unicode.bin differ diff --git a/python-tools/tests/test_files/bin/value_types.bin b/python-tools/tests/test_files/bin/value_types.bin new file mode 100644 index 00000000..78349e06 Binary files /dev/null and b/python-tools/tests/test_files/bin/value_types.bin differ diff --git a/sdks/go/src/lqp/v1/transactions.pb.go b/sdks/go/src/lqp/v1/transactions.pb.go index ee34b3c6..eb11a05b 100644 --- a/sdks/go/src/lqp/v1/transactions.pb.go +++ b/sdks/go/src/lqp/v1/transactions.pb.go @@ -73,6 +73,58 @@ func (MaintenanceLevel) EnumDescriptor() ([]byte, []int) { return file_relationalai_lqp_v1_transactions_proto_rawDescGZIP(), []int{0} } +type OptimizationLevel int32 + +const ( + OptimizationLevel_OPTIMIZATION_LEVEL_UNSPECIFIED OptimizationLevel = 0 + OptimizationLevel_OPTIMIZATION_LEVEL_DEFAULT OptimizationLevel = 1 + OptimizationLevel_OPTIMIZATION_LEVEL_CONSERVATIVE OptimizationLevel = 2 + OptimizationLevel_OPTIMIZATION_LEVEL_AGGRESSIVE OptimizationLevel = 3 +) + +// Enum value maps for OptimizationLevel. +var ( + OptimizationLevel_name = map[int32]string{ + 0: "OPTIMIZATION_LEVEL_UNSPECIFIED", + 1: "OPTIMIZATION_LEVEL_DEFAULT", + 2: "OPTIMIZATION_LEVEL_CONSERVATIVE", + 3: "OPTIMIZATION_LEVEL_AGGRESSIVE", + } + OptimizationLevel_value = map[string]int32{ + "OPTIMIZATION_LEVEL_UNSPECIFIED": 0, + "OPTIMIZATION_LEVEL_DEFAULT": 1, + "OPTIMIZATION_LEVEL_CONSERVATIVE": 2, + "OPTIMIZATION_LEVEL_AGGRESSIVE": 3, + } +) + +func (x OptimizationLevel) Enum() *OptimizationLevel { + p := new(OptimizationLevel) + *p = x + return p +} + +func (x OptimizationLevel) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (OptimizationLevel) Descriptor() protoreflect.EnumDescriptor { + return file_relationalai_lqp_v1_transactions_proto_enumTypes[1].Descriptor() +} + +func (OptimizationLevel) Type() protoreflect.EnumType { + return &file_relationalai_lqp_v1_transactions_proto_enumTypes[1] +} + +func (x OptimizationLevel) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use OptimizationLevel.Descriptor instead. +func (OptimizationLevel) EnumDescriptor() ([]byte, []int) { + return file_relationalai_lqp_v1_transactions_proto_rawDescGZIP(), []int{1} +} + type Transaction struct { state protoimpl.MessageState `protogen:"open.v1"` Epochs []*Epoch `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs,omitempty"` @@ -134,11 +186,12 @@ func (x *Transaction) GetSync() *Sync { } type Configure struct { - state protoimpl.MessageState `protogen:"open.v1"` - SemanticsVersion int64 `protobuf:"varint,1,opt,name=semantics_version,json=semanticsVersion,proto3" json:"semantics_version,omitempty"` - IvmConfig *IVMConfig `protobuf:"bytes,2,opt,name=ivm_config,json=ivmConfig,proto3" json:"ivm_config,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + SemanticsVersion int64 `protobuf:"varint,1,opt,name=semantics_version,json=semanticsVersion,proto3" json:"semantics_version,omitempty"` + IvmConfig *IVMConfig `protobuf:"bytes,2,opt,name=ivm_config,json=ivmConfig,proto3" json:"ivm_config,omitempty"` + OptimizationLevel OptimizationLevel `protobuf:"varint,3,opt,name=optimization_level,json=optimizationLevel,proto3,enum=relationalai.lqp.v1.OptimizationLevel" json:"optimization_level,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Configure) Reset() { @@ -185,6 +238,13 @@ func (x *Configure) GetIvmConfig() *IVMConfig { return nil } +func (x *Configure) GetOptimizationLevel() OptimizationLevel { + if x != nil { + return x.OptimizationLevel + } + return OptimizationLevel_OPTIMIZATION_LEVEL_UNSPECIFIED +} + type IVMConfig struct { state protoimpl.MessageState `protogen:"open.v1"` Level MaintenanceLevel `protobuf:"varint,1,opt,name=level,proto3,enum=relationalai.lqp.v1.MaintenanceLevel" json:"level,omitempty"` @@ -1392,202 +1452,218 @@ var file_relationalai_lqp_v1_transactions_proto_rawDesc = string([]byte{ 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x48, 0x00, 0x52, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x73, 0x79, - 0x6e, 0x63, 0x22, 0x77, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x12, - 0x2b, 0x0a, 0x11, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x73, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x73, 0x65, 0x6d, 0x61, - 0x6e, 0x74, 0x69, 0x63, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0a, - 0x69, 0x76, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, - 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x56, 0x4d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x09, 0x69, 0x76, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x48, 0x0a, 0x09, 0x49, - 0x56, 0x4d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, - 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x45, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x3d, 0x0a, - 0x09, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, - 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x52, 0x09, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x6c, 0x0a, 0x05, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x32, 0x0a, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x52, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x72, 0x65, 0x61, - 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x61, 0x64, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x73, 0x22, 0x86, 0x02, 0x0a, 0x05, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, - 0x65, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x75, - 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x6e, 0x63, 0x22, 0xce, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, + 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x73, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x73, 0x65, 0x6d, + 0x61, 0x6e, 0x74, 0x69, 0x63, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, + 0x0a, 0x69, 0x76, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, + 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x56, 0x4d, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x09, 0x69, 0x76, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x12, + 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x22, 0x48, 0x0a, 0x09, 0x49, 0x56, 0x4d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x3b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x25, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, + 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, + 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x45, 0x0a, + 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x3d, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x09, 0x66, 0x72, 0x61, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x22, 0x6c, 0x0a, 0x05, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x32, 0x0a, + 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x48, 0x00, 0x52, 0x08, - 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x48, 0x00, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x42, - 0x0c, 0x0a, 0x0a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, - 0x04, 0x10, 0x05, 0x22, 0x43, 0x0a, 0x06, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x12, 0x39, 0x0a, - 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, - 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, - 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x4c, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x0a, 0x66, 0x72, 0x61, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x3d, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x22, 0x86, 0x01, 0x0a, 0x0f, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x48, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, 0x08, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xc8, 0x05, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, - 0x43, 0x0a, 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x43, 0x53, 0x56, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x63, 0x73, 0x76, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x53, 0x56, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x63, 0x73, 0x76, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, - 0x0b, 0x64, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x0e, - 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, - 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, - 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, - 0x2f, 0x0a, 0x11, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x72, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x0f, 0x73, 0x79, - 0x6e, 0x74, 0x61, 0x78, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x6f, 0x77, 0x88, 0x01, 0x01, - 0x12, 0x37, 0x0a, 0x15, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x03, 0x52, 0x13, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x79, 0x6e, - 0x74, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x04, 0x52, 0x0b, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x44, 0x65, 0x6c, 0x69, 0x6d, 0x88, 0x01, - 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x71, 0x75, 0x6f, 0x74, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x73, - 0x79, 0x6e, 0x74, 0x61, 0x78, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x63, 0x68, 0x61, 0x72, 0x88, 0x01, - 0x01, 0x12, 0x30, 0x0a, 0x11, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x65, 0x73, 0x63, 0x61, - 0x70, 0x65, 0x63, 0x68, 0x61, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x10, - 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, - 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x77, 0x42, 0x18, 0x0a, 0x16, - 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, - 0x78, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x73, 0x79, 0x6e, 0x74, - 0x61, 0x78, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x63, 0x68, 0x61, 0x72, 0x42, 0x14, 0x0a, 0x12, - 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x22, 0x74, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, + 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x05, 0x72, 0x65, 0x61, + 0x64, 0x73, 0x22, 0x86, 0x02, 0x0a, 0x05, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x06, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x66, + 0x69, 0x6e, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x48, 0x00, 0x52, 0x08, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, + 0x12, 0x38, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, + 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x48, + 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x48, 0x00, 0x52, 0x08, 0x73, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x43, 0x0a, 0x06, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, + 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x22, 0x4c, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x12, 0x40, 0x0a, 0x0b, + 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, + 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x52, 0x0a, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x48, + 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3d, 0x0a, 0x09, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x09, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x0f, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, + 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x4c, 0x0a, 0x08, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x40, 0x0a, + 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, + 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, + 0xc8, 0x05, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x63, 0x6f, - 0x6c, 0x75, 0x6d, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x22, 0x52, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x07, - 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, - 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x22, 0xa9, 0x01, 0x0a, - 0x0f, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x67, 0x6e, 0x66, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x09, 0x63, 0x73, 0x76, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x0a, + 0x63, 0x73, 0x76, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, + 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x09, 0x63, 0x73, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x0c, 0x64, + 0x61, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, + 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, + 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0d, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x25, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x73, 0x79, 0x6e, 0x74, 0x61, + 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x02, 0x52, 0x0f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x52, 0x6f, 0x77, 0x88, 0x01, 0x01, 0x12, 0x37, 0x0a, 0x15, 0x73, 0x79, 0x6e, 0x74, + 0x61, 0x78, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x13, 0x73, 0x79, 0x6e, 0x74, 0x61, + 0x78, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x88, 0x01, + 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x6c, 0x69, + 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0b, 0x73, 0x79, 0x6e, 0x74, 0x61, + 0x78, 0x44, 0x65, 0x6c, 0x69, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x73, 0x79, 0x6e, + 0x74, 0x61, 0x78, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x63, 0x68, 0x61, 0x72, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x51, 0x75, 0x6f, + 0x74, 0x65, 0x63, 0x68, 0x61, 0x72, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, 0x73, 0x79, 0x6e, + 0x74, 0x61, 0x78, 0x5f, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x63, 0x68, 0x61, 0x72, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x10, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x45, 0x73, + 0x63, 0x61, 0x70, 0x65, 0x63, 0x68, 0x61, 0x72, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x0e, + 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x14, + 0x0a, 0x12, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x5f, 0x72, 0x6f, 0x77, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0f, + 0x0a, 0x0d, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x42, + 0x13, 0x0a, 0x11, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x5f, + 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x63, 0x68, 0x61, 0x72, 0x22, 0x74, 0x0a, 0x0f, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x40, + 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x44, 0x61, 0x74, 0x61, + 0x22, 0x52, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0a, - 0x67, 0x6e, 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, + 0x53, 0x56, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x67, 0x6e, 0x66, 0x5f, + 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x48, 0x00, - 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x73, - 0x76, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xa4, 0x02, 0x0a, 0x04, 0x52, 0x65, 0x61, - 0x64, 0x12, 0x35, 0x0a, 0x06, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, - 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, - 0x52, 0x06, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x35, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, - 0x36, 0x0a, 0x07, 0x77, 0x68, 0x61, 0x74, 0x5f, 0x69, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, - 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x68, 0x61, 0x74, 0x49, 0x66, 0x48, 0x00, 0x52, - 0x06, 0x77, 0x68, 0x61, 0x74, 0x49, 0x66, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x62, 0x6f, 0x72, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x62, 0x6f, - 0x72, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x65, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x4a, 0x0a, 0x06, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x0b, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, - 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, - 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x5e, 0x0a, 0x06, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, - 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, - 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x60, 0x0a, 0x06, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x45, 0x0a, 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x67, 0x6e, 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x48, 0x00, 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x44, + 0x65, 0x66, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x22, 0xa4, 0x02, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x35, 0x0a, 0x06, 0x64, 0x65, 0x6d, + 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, 0x56, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, - 0x00, 0x52, 0x09, 0x63, 0x73, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0f, 0x0a, 0x0d, - 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x52, 0x0a, - 0x06, 0x57, 0x68, 0x61, 0x74, 0x49, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, - 0x30, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x64, + 0x12, 0x35, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, + 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, + 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x36, 0x0a, 0x07, 0x77, 0x68, 0x61, 0x74, 0x5f, + 0x69, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x57, + 0x68, 0x61, 0x74, 0x49, 0x66, 0x48, 0x00, 0x52, 0x06, 0x77, 0x68, 0x61, 0x74, 0x49, 0x66, 0x12, + 0x32, 0x0a, 0x05, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, - 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x22, 0x5d, 0x0a, 0x05, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, - 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x2a, 0x87, 0x01, 0x0a, 0x10, 0x4d, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x1d, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, - 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x41, 0x49, 0x4e, - 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x4f, 0x46, - 0x46, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, - 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x02, 0x12, - 0x19, 0x0a, 0x15, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, - 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x03, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x41, 0x49, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x64, 0x6b, - 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x6c, 0x71, 0x70, 0x2f, 0x76, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x62, + 0x6f, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x48, 0x00, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x72, 0x65, + 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x4a, 0x0a, 0x06, 0x44, 0x65, 0x6d, 0x61, 0x6e, + 0x64, 0x12, 0x40, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x5e, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x60, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x45, 0x0a, + 0x0a, 0x63, 0x73, 0x76, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, + 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x53, + 0x56, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x09, 0x63, 0x73, 0x76, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0f, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x52, 0x0a, 0x06, 0x57, 0x68, 0x61, 0x74, 0x49, 0x66, 0x12, + 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x30, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x6f, + 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x5d, 0x0a, 0x05, 0x41, 0x62, 0x6f, + 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x61, 0x69, 0x2e, 0x6c, 0x71, 0x70, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x2a, 0x87, 0x01, 0x0a, 0x10, 0x4d, 0x61, 0x69, + 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, + 0x1d, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, + 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, + 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x4f, 0x46, 0x46, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x4d, + 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, + 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x41, 0x49, 0x4e, 0x54, + 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x41, 0x4c, 0x4c, + 0x10, 0x03, 0x2a, 0x9f, 0x01, 0x0a, 0x11, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x1e, 0x4f, 0x50, 0x54, 0x49, + 0x4d, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, + 0x4f, 0x50, 0x54, 0x49, 0x4d, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x56, + 0x45, 0x4c, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, + 0x4f, 0x50, 0x54, 0x49, 0x4d, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x56, + 0x45, 0x4c, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x52, 0x56, 0x41, 0x54, 0x49, 0x56, 0x45, 0x10, + 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x4f, 0x50, 0x54, 0x49, 0x4d, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x53, 0x53, 0x49, + 0x56, 0x45, 0x10, 0x03, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x49, 0x2f, + 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2d, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x64, 0x6b, 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x73, + 0x72, 0x63, 0x2f, 0x6c, 0x71, 0x70, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, }) var ( @@ -1602,76 +1678,78 @@ func file_relationalai_lqp_v1_transactions_proto_rawDescGZIP() []byte { return file_relationalai_lqp_v1_transactions_proto_rawDescData } -var file_relationalai_lqp_v1_transactions_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_relationalai_lqp_v1_transactions_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_relationalai_lqp_v1_transactions_proto_msgTypes = make([]protoimpl.MessageInfo, 21) var file_relationalai_lqp_v1_transactions_proto_goTypes = []any{ (MaintenanceLevel)(0), // 0: relationalai.lqp.v1.MaintenanceLevel - (*Transaction)(nil), // 1: relationalai.lqp.v1.Transaction - (*Configure)(nil), // 2: relationalai.lqp.v1.Configure - (*IVMConfig)(nil), // 3: relationalai.lqp.v1.IVMConfig - (*Sync)(nil), // 4: relationalai.lqp.v1.Sync - (*Epoch)(nil), // 5: relationalai.lqp.v1.Epoch - (*Write)(nil), // 6: relationalai.lqp.v1.Write - (*Define)(nil), // 7: relationalai.lqp.v1.Define - (*Undefine)(nil), // 8: relationalai.lqp.v1.Undefine - (*Context)(nil), // 9: relationalai.lqp.v1.Context - (*SnapshotMapping)(nil), // 10: relationalai.lqp.v1.SnapshotMapping - (*Snapshot)(nil), // 11: relationalai.lqp.v1.Snapshot - (*ExportCSVConfig)(nil), // 12: relationalai.lqp.v1.ExportCSVConfig - (*ExportCSVColumn)(nil), // 13: relationalai.lqp.v1.ExportCSVColumn - (*ExportCSVColumns)(nil), // 14: relationalai.lqp.v1.ExportCSVColumns - (*ExportCSVSource)(nil), // 15: relationalai.lqp.v1.ExportCSVSource - (*Read)(nil), // 16: relationalai.lqp.v1.Read - (*Demand)(nil), // 17: relationalai.lqp.v1.Demand - (*Output)(nil), // 18: relationalai.lqp.v1.Output - (*Export)(nil), // 19: relationalai.lqp.v1.Export - (*WhatIf)(nil), // 20: relationalai.lqp.v1.WhatIf - (*Abort)(nil), // 21: relationalai.lqp.v1.Abort - (*FragmentId)(nil), // 22: relationalai.lqp.v1.FragmentId - (*Fragment)(nil), // 23: relationalai.lqp.v1.Fragment - (*RelationId)(nil), // 24: relationalai.lqp.v1.RelationId - (*CSVConfig)(nil), // 25: relationalai.lqp.v1.CSVConfig + (OptimizationLevel)(0), // 1: relationalai.lqp.v1.OptimizationLevel + (*Transaction)(nil), // 2: relationalai.lqp.v1.Transaction + (*Configure)(nil), // 3: relationalai.lqp.v1.Configure + (*IVMConfig)(nil), // 4: relationalai.lqp.v1.IVMConfig + (*Sync)(nil), // 5: relationalai.lqp.v1.Sync + (*Epoch)(nil), // 6: relationalai.lqp.v1.Epoch + (*Write)(nil), // 7: relationalai.lqp.v1.Write + (*Define)(nil), // 8: relationalai.lqp.v1.Define + (*Undefine)(nil), // 9: relationalai.lqp.v1.Undefine + (*Context)(nil), // 10: relationalai.lqp.v1.Context + (*SnapshotMapping)(nil), // 11: relationalai.lqp.v1.SnapshotMapping + (*Snapshot)(nil), // 12: relationalai.lqp.v1.Snapshot + (*ExportCSVConfig)(nil), // 13: relationalai.lqp.v1.ExportCSVConfig + (*ExportCSVColumn)(nil), // 14: relationalai.lqp.v1.ExportCSVColumn + (*ExportCSVColumns)(nil), // 15: relationalai.lqp.v1.ExportCSVColumns + (*ExportCSVSource)(nil), // 16: relationalai.lqp.v1.ExportCSVSource + (*Read)(nil), // 17: relationalai.lqp.v1.Read + (*Demand)(nil), // 18: relationalai.lqp.v1.Demand + (*Output)(nil), // 19: relationalai.lqp.v1.Output + (*Export)(nil), // 20: relationalai.lqp.v1.Export + (*WhatIf)(nil), // 21: relationalai.lqp.v1.WhatIf + (*Abort)(nil), // 22: relationalai.lqp.v1.Abort + (*FragmentId)(nil), // 23: relationalai.lqp.v1.FragmentId + (*Fragment)(nil), // 24: relationalai.lqp.v1.Fragment + (*RelationId)(nil), // 25: relationalai.lqp.v1.RelationId + (*CSVConfig)(nil), // 26: relationalai.lqp.v1.CSVConfig } var file_relationalai_lqp_v1_transactions_proto_depIdxs = []int32{ - 5, // 0: relationalai.lqp.v1.Transaction.epochs:type_name -> relationalai.lqp.v1.Epoch - 2, // 1: relationalai.lqp.v1.Transaction.configure:type_name -> relationalai.lqp.v1.Configure - 4, // 2: relationalai.lqp.v1.Transaction.sync:type_name -> relationalai.lqp.v1.Sync - 3, // 3: relationalai.lqp.v1.Configure.ivm_config:type_name -> relationalai.lqp.v1.IVMConfig - 0, // 4: relationalai.lqp.v1.IVMConfig.level:type_name -> relationalai.lqp.v1.MaintenanceLevel - 22, // 5: relationalai.lqp.v1.Sync.fragments:type_name -> relationalai.lqp.v1.FragmentId - 6, // 6: relationalai.lqp.v1.Epoch.writes:type_name -> relationalai.lqp.v1.Write - 16, // 7: relationalai.lqp.v1.Epoch.reads:type_name -> relationalai.lqp.v1.Read - 7, // 8: relationalai.lqp.v1.Write.define:type_name -> relationalai.lqp.v1.Define - 8, // 9: relationalai.lqp.v1.Write.undefine:type_name -> relationalai.lqp.v1.Undefine - 9, // 10: relationalai.lqp.v1.Write.context:type_name -> relationalai.lqp.v1.Context - 11, // 11: relationalai.lqp.v1.Write.snapshot:type_name -> relationalai.lqp.v1.Snapshot - 23, // 12: relationalai.lqp.v1.Define.fragment:type_name -> relationalai.lqp.v1.Fragment - 22, // 13: relationalai.lqp.v1.Undefine.fragment_id:type_name -> relationalai.lqp.v1.FragmentId - 24, // 14: relationalai.lqp.v1.Context.relations:type_name -> relationalai.lqp.v1.RelationId - 24, // 15: relationalai.lqp.v1.SnapshotMapping.source_relation:type_name -> relationalai.lqp.v1.RelationId - 10, // 16: relationalai.lqp.v1.Snapshot.mappings:type_name -> relationalai.lqp.v1.SnapshotMapping - 15, // 17: relationalai.lqp.v1.ExportCSVConfig.csv_source:type_name -> relationalai.lqp.v1.ExportCSVSource - 25, // 18: relationalai.lqp.v1.ExportCSVConfig.csv_config:type_name -> relationalai.lqp.v1.CSVConfig - 13, // 19: relationalai.lqp.v1.ExportCSVConfig.data_columns:type_name -> relationalai.lqp.v1.ExportCSVColumn - 24, // 20: relationalai.lqp.v1.ExportCSVColumn.column_data:type_name -> relationalai.lqp.v1.RelationId - 13, // 21: relationalai.lqp.v1.ExportCSVColumns.columns:type_name -> relationalai.lqp.v1.ExportCSVColumn - 14, // 22: relationalai.lqp.v1.ExportCSVSource.gnf_columns:type_name -> relationalai.lqp.v1.ExportCSVColumns - 24, // 23: relationalai.lqp.v1.ExportCSVSource.table_def:type_name -> relationalai.lqp.v1.RelationId - 17, // 24: relationalai.lqp.v1.Read.demand:type_name -> relationalai.lqp.v1.Demand - 18, // 25: relationalai.lqp.v1.Read.output:type_name -> relationalai.lqp.v1.Output - 20, // 26: relationalai.lqp.v1.Read.what_if:type_name -> relationalai.lqp.v1.WhatIf - 21, // 27: relationalai.lqp.v1.Read.abort:type_name -> relationalai.lqp.v1.Abort - 19, // 28: relationalai.lqp.v1.Read.export:type_name -> relationalai.lqp.v1.Export - 24, // 29: relationalai.lqp.v1.Demand.relation_id:type_name -> relationalai.lqp.v1.RelationId - 24, // 30: relationalai.lqp.v1.Output.relation_id:type_name -> relationalai.lqp.v1.RelationId - 12, // 31: relationalai.lqp.v1.Export.csv_config:type_name -> relationalai.lqp.v1.ExportCSVConfig - 5, // 32: relationalai.lqp.v1.WhatIf.epoch:type_name -> relationalai.lqp.v1.Epoch - 24, // 33: relationalai.lqp.v1.Abort.relation_id:type_name -> relationalai.lqp.v1.RelationId - 34, // [34:34] is the sub-list for method output_type - 34, // [34:34] is the sub-list for method input_type - 34, // [34:34] is the sub-list for extension type_name - 34, // [34:34] is the sub-list for extension extendee - 0, // [0:34] is the sub-list for field type_name + 6, // 0: relationalai.lqp.v1.Transaction.epochs:type_name -> relationalai.lqp.v1.Epoch + 3, // 1: relationalai.lqp.v1.Transaction.configure:type_name -> relationalai.lqp.v1.Configure + 5, // 2: relationalai.lqp.v1.Transaction.sync:type_name -> relationalai.lqp.v1.Sync + 4, // 3: relationalai.lqp.v1.Configure.ivm_config:type_name -> relationalai.lqp.v1.IVMConfig + 1, // 4: relationalai.lqp.v1.Configure.optimization_level:type_name -> relationalai.lqp.v1.OptimizationLevel + 0, // 5: relationalai.lqp.v1.IVMConfig.level:type_name -> relationalai.lqp.v1.MaintenanceLevel + 23, // 6: relationalai.lqp.v1.Sync.fragments:type_name -> relationalai.lqp.v1.FragmentId + 7, // 7: relationalai.lqp.v1.Epoch.writes:type_name -> relationalai.lqp.v1.Write + 17, // 8: relationalai.lqp.v1.Epoch.reads:type_name -> relationalai.lqp.v1.Read + 8, // 9: relationalai.lqp.v1.Write.define:type_name -> relationalai.lqp.v1.Define + 9, // 10: relationalai.lqp.v1.Write.undefine:type_name -> relationalai.lqp.v1.Undefine + 10, // 11: relationalai.lqp.v1.Write.context:type_name -> relationalai.lqp.v1.Context + 12, // 12: relationalai.lqp.v1.Write.snapshot:type_name -> relationalai.lqp.v1.Snapshot + 24, // 13: relationalai.lqp.v1.Define.fragment:type_name -> relationalai.lqp.v1.Fragment + 23, // 14: relationalai.lqp.v1.Undefine.fragment_id:type_name -> relationalai.lqp.v1.FragmentId + 25, // 15: relationalai.lqp.v1.Context.relations:type_name -> relationalai.lqp.v1.RelationId + 25, // 16: relationalai.lqp.v1.SnapshotMapping.source_relation:type_name -> relationalai.lqp.v1.RelationId + 11, // 17: relationalai.lqp.v1.Snapshot.mappings:type_name -> relationalai.lqp.v1.SnapshotMapping + 16, // 18: relationalai.lqp.v1.ExportCSVConfig.csv_source:type_name -> relationalai.lqp.v1.ExportCSVSource + 26, // 19: relationalai.lqp.v1.ExportCSVConfig.csv_config:type_name -> relationalai.lqp.v1.CSVConfig + 14, // 20: relationalai.lqp.v1.ExportCSVConfig.data_columns:type_name -> relationalai.lqp.v1.ExportCSVColumn + 25, // 21: relationalai.lqp.v1.ExportCSVColumn.column_data:type_name -> relationalai.lqp.v1.RelationId + 14, // 22: relationalai.lqp.v1.ExportCSVColumns.columns:type_name -> relationalai.lqp.v1.ExportCSVColumn + 15, // 23: relationalai.lqp.v1.ExportCSVSource.gnf_columns:type_name -> relationalai.lqp.v1.ExportCSVColumns + 25, // 24: relationalai.lqp.v1.ExportCSVSource.table_def:type_name -> relationalai.lqp.v1.RelationId + 18, // 25: relationalai.lqp.v1.Read.demand:type_name -> relationalai.lqp.v1.Demand + 19, // 26: relationalai.lqp.v1.Read.output:type_name -> relationalai.lqp.v1.Output + 21, // 27: relationalai.lqp.v1.Read.what_if:type_name -> relationalai.lqp.v1.WhatIf + 22, // 28: relationalai.lqp.v1.Read.abort:type_name -> relationalai.lqp.v1.Abort + 20, // 29: relationalai.lqp.v1.Read.export:type_name -> relationalai.lqp.v1.Export + 25, // 30: relationalai.lqp.v1.Demand.relation_id:type_name -> relationalai.lqp.v1.RelationId + 25, // 31: relationalai.lqp.v1.Output.relation_id:type_name -> relationalai.lqp.v1.RelationId + 13, // 32: relationalai.lqp.v1.Export.csv_config:type_name -> relationalai.lqp.v1.ExportCSVConfig + 6, // 33: relationalai.lqp.v1.WhatIf.epoch:type_name -> relationalai.lqp.v1.Epoch + 25, // 34: relationalai.lqp.v1.Abort.relation_id:type_name -> relationalai.lqp.v1.RelationId + 35, // [35:35] is the sub-list for method output_type + 35, // [35:35] is the sub-list for method input_type + 35, // [35:35] is the sub-list for extension type_name + 35, // [35:35] is the sub-list for extension extendee + 0, // [0:35] is the sub-list for field type_name } func init() { file_relationalai_lqp_v1_transactions_proto_init() } @@ -1708,7 +1786,7 @@ func file_relationalai_lqp_v1_transactions_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_relationalai_lqp_v1_transactions_proto_rawDesc), len(file_relationalai_lqp_v1_transactions_proto_rawDesc)), - NumEnums: 1, + NumEnums: 2, NumMessages: 21, NumExtensions: 0, NumServices: 0, diff --git a/sdks/julia/LogicalQueryProtocol.jl/src/gen/relationalai/lqp/v1/transactions_pb.jl b/sdks/julia/LogicalQueryProtocol.jl/src/gen/relationalai/lqp/v1/transactions_pb.jl index c5f18bf0..ae6bfcf3 100644 --- a/sdks/julia/LogicalQueryProtocol.jl/src/gen/relationalai/lqp/v1/transactions_pb.jl +++ b/sdks/julia/LogicalQueryProtocol.jl/src/gen/relationalai/lqp/v1/transactions_pb.jl @@ -5,8 +5,8 @@ import ProtoBuf as PB using ProtoBuf: OneOf using ProtoBuf.EnumX: @enumx -export ExportCSVColumn, Demand, Undefine, MaintenanceLevel, Define, Context, Sync -export SnapshotMapping, Abort, Output, ExportCSVColumns, IVMConfig, Snapshot +export ExportCSVColumn, OptimizationLevel, Demand, Undefine, MaintenanceLevel, Define +export Context, Sync, SnapshotMapping, Abort, Output, ExportCSVColumns, IVMConfig, Snapshot export ExportCSVSource, Configure, Write, ExportCSVConfig, Export, Epoch, Read, Transaction export WhatIf abstract type var"##Abstract#Transaction" end @@ -52,6 +52,8 @@ function PB._encoded_size(x::ExportCSVColumn) return encoded_size end +@enumx OptimizationLevel OPTIMIZATION_LEVEL_UNSPECIFIED=0 OPTIMIZATION_LEVEL_DEFAULT=1 OPTIMIZATION_LEVEL_CONSERVATIVE=2 OPTIMIZATION_LEVEL_AGGRESSIVE=3 + struct Demand relation_id::Union{Nothing,RelationId} end @@ -462,37 +464,43 @@ end struct Configure semantics_version::Int64 ivm_config::Union{Nothing,IVMConfig} + optimization_level::OptimizationLevel.T end -Configure(;semantics_version = zero(Int64), ivm_config = nothing) = Configure(semantics_version, ivm_config) -PB.default_values(::Type{Configure}) = (;semantics_version = zero(Int64), ivm_config = nothing) -PB.field_numbers(::Type{Configure}) = (;semantics_version = 1, ivm_config = 2) +Configure(;semantics_version = zero(Int64), ivm_config = nothing, optimization_level = OptimizationLevel.OPTIMIZATION_LEVEL_UNSPECIFIED) = Configure(semantics_version, ivm_config, optimization_level) +PB.default_values(::Type{Configure}) = (;semantics_version = zero(Int64), ivm_config = nothing, optimization_level = OptimizationLevel.OPTIMIZATION_LEVEL_UNSPECIFIED) +PB.field_numbers(::Type{Configure}) = (;semantics_version = 1, ivm_config = 2, optimization_level = 3) function PB.decode(d::PB.AbstractProtoDecoder, ::Type{<:Configure}, _endpos::Int=0, _group::Bool=false) semantics_version = zero(Int64) ivm_config = Ref{Union{Nothing,IVMConfig}}(nothing) + optimization_level = OptimizationLevel.OPTIMIZATION_LEVEL_UNSPECIFIED while !PB.message_done(d, _endpos, _group) field_number, wire_type = PB.decode_tag(d) if field_number == 1 semantics_version = PB.decode(d, Int64) elseif field_number == 2 PB.decode!(d, ivm_config) + elseif field_number == 3 + optimization_level = PB.decode(d, OptimizationLevel.T) else Base.skip(d, wire_type) end end - return Configure(semantics_version, ivm_config[]) + return Configure(semantics_version, ivm_config[], optimization_level) end function PB.encode(e::PB.AbstractProtoEncoder, x::Configure) initpos = position(e.io) x.semantics_version != zero(Int64) && PB.encode(e, 1, x.semantics_version) !isnothing(x.ivm_config) && PB.encode(e, 2, x.ivm_config) + x.optimization_level != OptimizationLevel.OPTIMIZATION_LEVEL_UNSPECIFIED && PB.encode(e, 3, x.optimization_level) return position(e.io) - initpos end function PB._encoded_size(x::Configure) encoded_size = 0 x.semantics_version != zero(Int64) && (encoded_size += PB._encoded_size(x.semantics_version, 1)) !isnothing(x.ivm_config) && (encoded_size += PB._encoded_size(x.ivm_config, 2)) + x.optimization_level != OptimizationLevel.OPTIMIZATION_LEVEL_UNSPECIFIED && (encoded_size += PB._encoded_size(x.optimization_level, 3)) return encoded_size end diff --git a/sdks/julia/LogicalQueryProtocol.jl/test/explicit_imports_test.jl b/sdks/julia/LogicalQueryProtocol.jl/test/explicit_imports_test.jl index 7cb34907..6df23649 100644 --- a/sdks/julia/LogicalQueryProtocol.jl/test/explicit_imports_test.jl +++ b/sdks/julia/LogicalQueryProtocol.jl/test/explicit_imports_test.jl @@ -25,7 +25,7 @@ check_no_stale_explicit_imports( LogicalQueryProtocol; ignore=reexported_names, - allow_unanalyzable=(LogicalQueryProtocol.MaintenanceLevel,), + allow_unanalyzable=(LogicalQueryProtocol.OptimizationLevel,LogicalQueryProtocol.MaintenanceLevel,), ) check_all_explicit_imports_via_owners(LogicalQueryProtocol) check_all_qualified_accesses_via_owners( diff --git a/sdks/julia/generate_proto.jl b/sdks/julia/generate_proto.jl old mode 100644 new mode 100755 diff --git a/sdks/python/src/lqp/proto/v1/transactions_pb2.pyi b/sdks/python/src/lqp/proto/v1/transactions_pb2.pyi index b5b0dce0..b64314c4 100644 --- a/sdks/python/src/lqp/proto/v1/transactions_pb2.pyi +++ b/sdks/python/src/lqp/proto/v1/transactions_pb2.pyi @@ -15,10 +15,21 @@ class MaintenanceLevel(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): MAINTENANCE_LEVEL_OFF: _ClassVar[MaintenanceLevel] MAINTENANCE_LEVEL_AUTO: _ClassVar[MaintenanceLevel] MAINTENANCE_LEVEL_ALL: _ClassVar[MaintenanceLevel] + +class OptimizationLevel(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + OPTIMIZATION_LEVEL_UNSPECIFIED: _ClassVar[OptimizationLevel] + OPTIMIZATION_LEVEL_DEFAULT: _ClassVar[OptimizationLevel] + OPTIMIZATION_LEVEL_CONSERVATIVE: _ClassVar[OptimizationLevel] + OPTIMIZATION_LEVEL_AGGRESSIVE: _ClassVar[OptimizationLevel] MAINTENANCE_LEVEL_UNSPECIFIED: MaintenanceLevel MAINTENANCE_LEVEL_OFF: MaintenanceLevel MAINTENANCE_LEVEL_AUTO: MaintenanceLevel MAINTENANCE_LEVEL_ALL: MaintenanceLevel +OPTIMIZATION_LEVEL_UNSPECIFIED: OptimizationLevel +OPTIMIZATION_LEVEL_DEFAULT: OptimizationLevel +OPTIMIZATION_LEVEL_CONSERVATIVE: OptimizationLevel +OPTIMIZATION_LEVEL_AGGRESSIVE: OptimizationLevel class Transaction(_message.Message): __slots__ = ("epochs", "configure", "sync") @@ -31,12 +42,14 @@ class Transaction(_message.Message): def __init__(self, epochs: _Optional[_Iterable[_Union[Epoch, _Mapping]]] = ..., configure: _Optional[_Union[Configure, _Mapping]] = ..., sync: _Optional[_Union[Sync, _Mapping]] = ...) -> None: ... class Configure(_message.Message): - __slots__ = ("semantics_version", "ivm_config") + __slots__ = ("semantics_version", "ivm_config", "optimization_level") SEMANTICS_VERSION_FIELD_NUMBER: _ClassVar[int] IVM_CONFIG_FIELD_NUMBER: _ClassVar[int] + OPTIMIZATION_LEVEL_FIELD_NUMBER: _ClassVar[int] semantics_version: int ivm_config: IVMConfig - def __init__(self, semantics_version: _Optional[int] = ..., ivm_config: _Optional[_Union[IVMConfig, _Mapping]] = ...) -> None: ... + optimization_level: OptimizationLevel + def __init__(self, semantics_version: _Optional[int] = ..., ivm_config: _Optional[_Union[IVMConfig, _Mapping]] = ..., optimization_level: _Optional[_Union[OptimizationLevel, str]] = ...) -> None: ... class IVMConfig(_message.Message): __slots__ = ("level",) diff --git a/tests/lqp/config_flags.lqp b/tests/lqp/config_flags.lqp index a4eba530..a4de0139 100644 --- a/tests/lqp/config_flags.lqp +++ b/tests/lqp/config_flags.lqp @@ -1,6 +1,7 @@ (transaction (configure { :ivm.maintenance_level "auto" + :optimization_level "aggressive" :semantics_version 1}) (epoch (writes diff --git a/tests/lqp/csv.lqp b/tests/lqp/csv.lqp index 9e7763ec..929f2d2a 100644 --- a/tests/lqp/csv.lqp +++ b/tests/lqp/csv.lqp @@ -1,4 +1,8 @@ (transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) (epoch (writes (define diff --git a/tests/lqp/edb.lqp b/tests/lqp/edb.lqp index 5f0b9a84..c5b801d2 100644 --- a/tests/lqp/edb.lqp +++ b/tests/lqp/edb.lqp @@ -1,4 +1,8 @@ (transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) (epoch (writes (define diff --git a/tests/lqp/unicode.lqp b/tests/lqp/unicode.lqp index c9dab917..06657f51 100644 --- a/tests/lqp/unicode.lqp +++ b/tests/lqp/unicode.lqp @@ -1,5 +1,9 @@ ;; Test UTF-8 encoded content with international characters (transaction + (configure + { :ivm.maintenance_level "off" + :optimization_level "default" + :semantics_version 0}) (epoch (writes (define