code: public static SelectClauseVisitor clauseVisitor(final Appendable appendable) {
  
  		final SafeAppendable sb = new SafeAppendable(appendable);
  		
  		SimpleClauseVisitor cv = new SimpleClauseVisitor() {
  			
  			AtomicBoolean first = new AtomicBoolean(true);
  			
  			/*
  			 * TODO take care of multiples and order.
  			 */
  			
  			@Override
  			protected void doVisit(SqlSelectClause<?> clause) {
  				if (! appendStart(clause)) return;
  				sb.append(clause.getSql());
  			}
  			
  			@Override
  			public void visit(SelectWhereClauseBuilder<?> whereClauseBuilder) {
  				if (! appendStart(whereClauseBuilder)) return;
  				whereClauseBuilder.getCondition().accept(ConditionVisitors.conditionVisitor(sb.getAppendable()));
  			}
  			
  			@Override
  			public void visit(OrderByClauseBuilder<?> orderClauseBuilder) {
  				if ( ! appendStart(orderClauseBuilder) ) return;
  				if (nullToEmpty(orderClauseBuilder.getSql()).trim().isEmpty())
  					OrderByPartialVisitors.visitor(sb.getAppendable()).visit(orderClauseBuilder.getOrderByPartial());
  				else
  					sb.append(orderClauseBuilder.getSql());
  			}
  
  			private boolean appendStart(SelectClause<?> k) {
  				if (k.isNoOp()) return false;
  				if (first.get() ) {
  					first.set(false);
  				}
  				else {
  					sb.append(" ");
  				}
  				if (k.getType() != SelectClauseType.CUSTOM) {
  					sb.append(k.getType().getSql());
  					if (k.getType() != SelectClauseType.FORUPDATE && 
  							k.getType() != SelectClauseType.FORSHARE)
  						sb.append(" ");
  				}
  				return true;
  			}
  
  		};
  		return cv;
  	}
docs: /*
  TODO move this to writer package.