code: func (statement *Statement) Join(joinOP string, tablename interface{}, condition string, args ...interface{}) *Statement {
  	var buf builder.StringBuilder
  	if len(statement.JoinStr) > 0 {
  		fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, joinOP)
  	} else {
  		fmt.Fprintf(&buf, "%v JOIN ", joinOP)
  	}
  
  	switch tp := tablename.(type) {
  	case builder.Builder:
  		subSQL, subQueryArgs, err := tp.ToSQL()
  		if err != nil {
  			statement.lastError = err
  			return statement
  		}
  		tbs := strings.Split(tp.TableName(), ".")
  		var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr())
  		fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition)
  		statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
  	case *builder.Builder:
  		subSQL, subQueryArgs, err := tp.ToSQL()
  		if err != nil {
  			statement.lastError = err
  			return statement
  		}
  		tbs := strings.Split(tp.TableName(), ".")
  		var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr())
  		fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition)
  		statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
  	default:
  		tbName := statement.Engine.TableName(tablename, true)
  		fmt.Fprintf(&buf, "%s ON %v", tbName, condition)
  	}
  
  	statement.JoinStr = buf.String()
  	statement.joinArgs = append(statement.joinArgs, args...)
  	return statement
  }
docs: // Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN