WriteTo writes contents of a fact store to the writer. It only calls the ListPredicates and GetFacts methods on the store. Flushing or closing the writer is is the caller's responsibility.
(store ReadOnlyFactStore, w io.Writer)
| 238 | // calls the ListPredicates and GetFacts methods on the store. |
| 239 | // Flushing or closing the writer is is the caller's responsibility. |
| 240 | func (sc SimpleColumn) WriteTo(store ReadOnlyFactStore, w io.Writer) error { |
| 241 | preds := store.ListPredicates() |
| 242 | if len(preds) > maxNumPreds { |
| 243 | return ErrTooManyPreds |
| 244 | } |
| 245 | if sc.Deterministic { |
| 246 | sort.Slice(preds, func(i, j int) bool { |
| 247 | a := preds[i] |
| 248 | b := preds[j] |
| 249 | return a.Arity < b.Arity || a.Arity == b.Arity && a.Symbol < b.Symbol |
| 250 | }) |
| 251 | } |
| 252 | predFactCount := make([]int, len(preds)) |
| 253 | for i, p := range preds { |
| 254 | if p.Arity > maxArity { |
| 255 | return fmt.Errorf("pred %v: %w", p, ErrUnsupportedArity) |
| 256 | } |
| 257 | var numFacts int |
| 258 | if err := store.GetFacts(ast.NewQuery(p), func(a ast.Atom) error { |
| 259 | numFacts++ |
| 260 | return nil |
| 261 | }); err != nil { |
| 262 | return err |
| 263 | } |
| 264 | if numFacts > maxFactsPerPredicate { |
| 265 | return fmt.Errorf("pred %v: %w", p, ErrTooManyFacts) |
| 266 | } |
| 267 | predFactCount[i] = numFacts |
| 268 | } |
| 269 | if err := sc.writeHeader(preds, predFactCount, w); err != nil { |
| 270 | return err |
| 271 | } |
| 272 | // for each predicate p with arity > 0: |
| 273 | for _, p := range preds { |
| 274 | if p.Arity == 0 { |
| 275 | continue |
| 276 | } |
| 277 | var facts []ast.Atom |
| 278 | if err := store.GetFacts(ast.NewQuery(p), func(a ast.Atom) error { |
| 279 | facts = append(facts, a) |
| 280 | return nil |
| 281 | }); err != nil { |
| 282 | return err |
| 283 | } |
| 284 | if sc.Deterministic { |
| 285 | sort.Slice(facts, func(i, j int) bool { |
| 286 | h1, h2 := facts[i].Hash(), facts[j].Hash() |
| 287 | if h1 == h2 { |
| 288 | return facts[i].String() < facts[j].String() |
| 289 | } |
| 290 | return h1 < h2 |
| 291 | }) |
| 292 | } |
| 293 | for i := 0; i < p.Arity; i++ { |
| 294 | for _, f := range facts { |
| 295 | if len(f.Args) != p.Arity { |
| 296 | return fmt.Errorf("malformed fact: %v predicate arity %d: %w", f, p.Arity, ErrWrongArgument) |
| 297 | } |