code: func compareCandidates(lhs, rhs *candidatePath) int {
  	setsResult, comparable := compareColumnSet(lhs.columnSet, rhs.columnSet)
  	if !comparable {
  		return 0
  	}
  	scanResult := compareBool(lhs.isSingleScan, rhs.isSingleScan)
  	matchResult := compareBool(lhs.isMatchProp, rhs.isMatchProp)
  	sum := setsResult + scanResult + matchResult
  	if setsResult >= 0 && scanResult >= 0 && matchResult >= 0 && sum > 0 {
  		return 1
  	}
  	if setsResult <= 0 && scanResult <= 0 && matchResult <= 0 && sum < 0 {
  		return -1
  	}
  	return 0
  }
docs: // compareCandidates is the core of skyline pruning. It compares the two candidate paths on three dimensions:
  // (1): the set of columns that occurred in the access condition,
  // (2): whether or not it matches the physical property
  // (3): does it require a double scan.
  // If `x` is not worse than `y` at all factors,
  // and there exists one factor that `x` is better than `y`, then `x` is better than `y`.