github.com/Bio-core/jtree@v0.0.0-20190705165106-1d7a7e7d6272/database/query_builder.go (about)

     1  package database
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	strings "strings"
     8  
     9  	"github.com/Bio-core/jtree/models"
    10  )
    11  
    12  //Map for types
    13  var Map map[string]string
    14  
    15  //BuildQuery takes a Query object and returns a string of the query
    16  func BuildQuery(query models.Query) string {
    17  	if len(query.SelectedFields) == 1 && query.SelectedFields[0] == "*" {
    18  		query.SelectedFields = GetColumns(query.SelectedTables)
    19  	}
    20  	fields := printFields(query.SelectedFields)
    21  	query.SelectedTables = orderTablesByHigharch(query.SelectedTables)
    22  	query.SelectedTables = detemineMissingTablesLinks(query.SelectedTables)
    23  	tables := printTables(query.SelectedTables)
    24  	queryString := "SELECT " + fields + " FROM " + tables
    25  	if len(query.SelectedCondition) != 0 {
    26  		if len(query.SelectedCondition[0]) != 0 {
    27  			conditions := printConditions(query.SelectedCondition)
    28  			queryString += " WHERE (" + conditions + ")"
    29  		}
    30  	}
    31  	return queryString
    32  }
    33  
    34  // Print comma separated selected fields
    35  func printFields(selectedFields []string) string {
    36  	var str = ""
    37  	for i := 0; i < len(selectedFields); i++ {
    38  		str += selectedFields[i] + " AS '" + selectedFields[i] + "', "
    39  	}
    40  	str = str[0 : len(str)-2]
    41  	return str
    42  }
    43  
    44  func printTables(selectedTables []string) string {
    45  	var str = ""
    46  	for i := 0; i < len(selectedTables); i++ {
    47  		if i == 0 {
    48  			str += selectedTables[i]
    49  		} else {
    50  			str += " JOIN " + selectedTables[i] + " ON " + selectedTables[i-1] + "." + joinMap[selectedTables[i-1]][selectedTables[i]] + "=" + selectedTables[i] + "." + joinMap[selectedTables[i-1]][selectedTables[i]]
    51  		}
    52  
    53  	}
    54  	return str
    55  }
    56  
    57  func printConditions(SelectedCondition [][]string) string {
    58  	var str = ""
    59  	for i := 0; i < len(SelectedCondition); i++ {
    60  		SelectedCondition[i][3] = escapeChars(SelectedCondition[i][3])
    61  		SelectedCondition[i] = formatCondition(SelectedCondition[i])
    62  		if SelectedCondition[i] == nil {
    63  			return "0=1"
    64  		}
    65  		str += SelectedCondition[i][0] + " " + SelectedCondition[i][1] + SelectedCondition[i][2]
    66  		if Map[SelectedCondition[i][1]] == "*string" || Map[SelectedCondition[i][1]] == "*time.Time" {
    67  			str += "\"" + SelectedCondition[i][3] + "\" "
    68  		} else if Map[SelectedCondition[i][1]] == "*float32" || Map[SelectedCondition[i][1]] == "*bool" || Map[SelectedCondition[i][1]] == "*int64" {
    69  			str += SelectedCondition[i][3] + " "
    70  
    71  		}
    72  	}
    73  
    74  	str = str[4 : len(str)-1]
    75  	return str
    76  }
    77  
    78  //GetColumns returns colums based off of table names
    79  func GetColumns(tables []string) []string {
    80  	var columns []string
    81  	for _, tableName := range tables {
    82  		rows, err := DBSelect.Query("Select * from " + tableName + " where 0=1")
    83  		defer rows.Close()
    84  		if err != nil {
    85  			fmt.Println(err)
    86  			return nil
    87  		}
    88  		columnsSet, err := rows.Columns()
    89  		if err != nil {
    90  			fmt.Println(err)
    91  			return nil
    92  		}
    93  		for _, j := range columnsSet {
    94  			columns = append(columns, tableName+"."+j)
    95  		}
    96  	}
    97  	return columns
    98  }
    99  
   100  //GetTables gets all of the tables in the db
   101  func GetTables() []string {
   102  	var tables []string
   103  	rows, err := DBSelect.Query("Show Tables")
   104  	defer rows.Close()
   105  	if err != nil {
   106  		fmt.Println(err)
   107  		return nil
   108  	}
   109  	for rows.Next() {
   110  		var tname string
   111  		rows.Scan(&tname)
   112  		tables = append(tables, strings.ToLower(tname))
   113  	}
   114  	return tables
   115  }
   116  
   117  func formatCondition(condition []string) []string {
   118  	switch condition[2] {
   119  	case "Equal to":
   120  		if Map[condition[1]] != "*string" && Map[condition[1]] != "*float32" && Map[condition[1]] != "*bool" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   121  			condition[2] = ""
   122  			return nil
   123  		}
   124  		condition[2] = "="
   125  		break
   126  	case "Not equal to":
   127  		if Map[condition[1]] != "*string" && Map[condition[1]] != "*float32" && Map[condition[1]] != "*bool" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   128  			condition[2] = ""
   129  			return nil
   130  		}
   131  		condition[2] = "<>"
   132  
   133  		break
   134  	case "Greater than":
   135  		if Map[condition[1]] != "*float32" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   136  			condition[2] = ""
   137  			return nil
   138  		}
   139  		condition[2] = ">"
   140  		break
   141  	case "Less than":
   142  		if Map[condition[1]] != "*float32" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   143  			condition[2] = ""
   144  			return nil
   145  		}
   146  		condition[2] = "<"
   147  		break
   148  	case "Greater or equal to":
   149  		if Map[condition[1]] != "*float32" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   150  			condition[2] = ""
   151  			return nil
   152  		}
   153  		condition[2] = ">="
   154  		break
   155  	case "Less or equal to":
   156  		if Map[condition[1]] != "*float32" && Map[condition[1]] != "*int64" && Map[condition[1]] != "*time.Time" {
   157  			condition[2] = ""
   158  			return nil
   159  		}
   160  		condition[2] = "<="
   161  		break
   162  	case "Begins with":
   163  		if Map[condition[1]] != "*string" {
   164  			condition[2] = ""
   165  			return nil
   166  		}
   167  		condition[2] = " LIKE "
   168  		condition[3] += "%"
   169  		break
   170  	case "Not begins with":
   171  		if Map[condition[1]] != "*string" {
   172  			condition[2] = ""
   173  			return nil
   174  		}
   175  		condition[0] += " NOT"
   176  		condition[2] = " LIKE "
   177  		condition[3] += "%"
   178  		break
   179  	case "Ends with":
   180  		if Map[condition[1]] != "*string" {
   181  			condition[2] = ""
   182  			return nil
   183  		}
   184  		condition[2] = " LIKE "
   185  		condition[3] = "%" + condition[3]
   186  		break
   187  	case "Not ends with":
   188  		if Map[condition[1]] != "*string" {
   189  			condition[2] = ""
   190  			return nil
   191  		}
   192  		condition[0] += " NOT"
   193  		condition[2] = " LIKE "
   194  		condition[3] = "%" + condition[3]
   195  		break
   196  	case "Contains":
   197  		if Map[condition[1]] != "*string" {
   198  			condition[2] = ""
   199  			return nil
   200  		}
   201  		condition[2] = " LIKE "
   202  		condition[3] = "%" + condition[3] + "%"
   203  		break
   204  	case "Not contains":
   205  		if Map[condition[1]] != "*string" {
   206  			condition[2] = ""
   207  			return nil
   208  		}
   209  		condition[0] += " NOT"
   210  		condition[2] = " LIKE "
   211  		condition[3] = "%" + condition[3] + "%"
   212  		break
   213  	default:
   214  		return nil
   215  	}
   216  	return condition
   217  }
   218  
   219  //MapSuper makes a map
   220  func MapSuper() map[string]string {
   221  	m := make(map[string]string)
   222  	v := reflect.ValueOf(models.Patient{})
   223  
   224  	for i := 0; i < v.NumField(); i++ {
   225  		tag := string(reflect.TypeOf(models.Patient{}).Field(i).Tag)
   226  		runes := []rune(tag)
   227  		j := strings.Index(tag, ":")
   228  		k := strings.Index(tag, "omit")
   229  		tag = string(runes[j+2 : k-1])
   230  		varType := reflect.TypeOf(models.Patient{}).Field(i).Type.String()
   231  		m[tag] = varType
   232  	}
   233  	v = reflect.ValueOf(models.Sample{})
   234  
   235  	for i := 0; i < v.NumField(); i++ {
   236  		tag := string(reflect.TypeOf(models.Sample{}).Field(i).Tag)
   237  		runes := []rune(tag)
   238  		j := strings.Index(tag, ":")
   239  		k := strings.Index(tag, "omit")
   240  		tag = string(runes[j+2 : k-1])
   241  		varType := reflect.TypeOf(models.Sample{}).Field(i).Type.String()
   242  		m[tag] = varType
   243  	}
   244  	v = reflect.ValueOf(models.Experiment{})
   245  
   246  	for i := 0; i < v.NumField(); i++ {
   247  		tag := string(reflect.TypeOf(models.Experiment{}).Field(i).Tag)
   248  		runes := []rune(tag)
   249  		j := strings.Index(tag, ":")
   250  		k := strings.Index(tag, "omit")
   251  		tag = string(runes[j+2 : k-1])
   252  		varType := reflect.TypeOf(models.Experiment{}).Field(i).Type.String()
   253  		m[tag] = varType
   254  	}
   255  	v = reflect.ValueOf(models.Result{})
   256  
   257  	for i := 0; i < v.NumField(); i++ {
   258  		tag := string(reflect.TypeOf(models.Result{}).Field(i).Tag)
   259  		runes := []rune(tag)
   260  		j := strings.Index(tag, ":")
   261  		k := strings.Index(tag, "omit")
   262  		tag = string(runes[j+2 : k-1])
   263  		varType := reflect.TypeOf(models.Result{}).Field(i).Type.String()
   264  		m[tag] = varType
   265  	}
   266  
   267  	v = reflect.ValueOf(models.Resultdetails{})
   268  
   269  	for i := 0; i < v.NumField(); i++ {
   270  		tag := string(reflect.TypeOf(models.Resultdetails{}).Field(i).Tag)
   271  		runes := []rune(tag)
   272  		j := strings.Index(tag, ":")
   273  		k := strings.Index(tag, "omit")
   274  		tag = string(runes[j+2 : k-1])
   275  		varType := reflect.TypeOf(models.Resultdetails{}).Field(i).Type.String()
   276  		m[tag] = varType
   277  	}
   278  
   279  	return m
   280  }
   281  
   282  func orderTablesByHigharch(selectedTables []string) []string {
   283  	order := []string{"patients", "samples", "experiments", "results", "resultdetails"}
   284  	newTables := make([]string, 0)
   285  	for _, o := range order {
   286  		for i := range selectedTables {
   287  			if selectedTables[i] == o {
   288  				newTables = append(newTables, o)
   289  			}
   290  		}
   291  	}
   292  	return newTables
   293  }
   294  
   295  func detemineMissingTablesLinks(selectedTables []string) []string {
   296  	order := []string{"patients", "samples", "experiments", "results", "resultdetails"}
   297  	if selectedTables[len(selectedTables)-1] == order[4] {
   298  		if len(selectedTables) == 5 {
   299  			return selectedTables
   300  		}
   301  		return order
   302  	}
   303  	if selectedTables[len(selectedTables)-1] == order[3] {
   304  		if len(selectedTables) == 4 {
   305  			return selectedTables
   306  		}
   307  		return order[:4]
   308  	}
   309  	if selectedTables[len(selectedTables)-1] == order[2] {
   310  		if len(selectedTables) == 3 {
   311  			return selectedTables
   312  		}
   313  		return order[:3]
   314  	}
   315  	if selectedTables[len(selectedTables)-1] == order[1] {
   316  		if len(selectedTables) == 2 {
   317  			return selectedTables
   318  		}
   319  		return order[:2]
   320  	}
   321  	return selectedTables
   322  }