diff mysql.R @ 0:e66bb061af06 draft

planemo upload for repository https://github.com/workflow4metabolomics/lcmsmatching.git commit 3529b25417f8e1a5836474c9adec4b696d35099d-dirty
author prog
date Tue, 12 Jul 2016 12:02:37 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mysql.R	Tue Jul 12 12:02:37 2016 -0400
@@ -0,0 +1,207 @@
+library(RMySQL, quietly = TRUE)
+
+#############
+# RUN QUERY #
+#############
+
+# conn              The connection to the database.
+# queries           A query or a list of queries.
+# close             Close query with a ';' if not already done.
+# RETURN            The last query result.
+run_query <- function(conn, queries, close = TRUE) {
+
+	for (query in queries) {
+
+		# Append ';'
+		if (close) {
+			n <- nchar(query)
+			if (substr(query, n, n) != ';')
+				query <- paste0(query, ';')
+		}
+
+		# Send query
+		result <- dbSendQuery(conn, query)
+
+		# Test that everything went right
+#		if ( ! dbHasCompleted(result))
+#			stop("Can't run the following query : ", query)
+	}
+
+	# Return result
+	return(invisible(result))
+}
+
+################
+# RUN SQL FILE #
+################
+
+# conn  The connection to the DBMS.
+# file  The path to the SQL file.
+run_sql_file <- function(conn, file) {
+
+	# Split SQL into single queries and put them into a list
+	queries <- character()
+	query <- ""
+	for (line in readLines(file)) {
+		line <- sub('^(.*)\\s*--.*$', '\\1', line, perl = TRUE) # remove one line comment
+		if (grepl("^\\s*$", line)) next # empty line
+		query <- paste(query, line)
+		if (grepl(";\\s*$", line, perl = TRUE)) {
+			query <- gsub("\t", " ", query, perl = TRUE) # replace tabulation by spaces
+			query <- gsub("/\\*.*\\*/", "", query, perl = TRUE) # remove multiline comments
+			queries <- c(queries, query)
+			query <- ""
+		}
+	}
+
+	# Run queries
+	invisible(run_query(conn, queries))
+}
+
+#################
+# DROP DATABASE #
+#################
+
+# conn                  The connection to the DBMS.
+# db                    The name of the database to drop.
+# fail_if_doesnt_exist  Fails if database doesn't exist.
+drop_database <- function(conn, db, fail_if_doesnt_exist = FALSE) {
+	invisible(run_query(conn, paste("drop database", if (fail_if_doesnt_exist) "" else "if exists", db)))
+}
+
+###################
+# CREATE DATABASE #
+###################
+
+# conn      The connection to the DBMS.
+# db        The name of the database to create.
+# drop      Drop/erase existing database.
+# encoding  Set the character set encoding to use as default for the database.
+# use       If true, switch to the newly created database.
+create_database <- function(conn, db, drop = FALSE, encoding = 'utf8', use = TRUE) {
+
+	# Drop database
+	if (drop) drop_database(conn, db)
+
+	# Create database
+	enc <- if (is.null(encoding) || is.na(encoding)) "" else paste("character set", encoding)
+	run_query(conn, paste("create database", db, enc))
+
+	# Switch to database
+	invisible(run_query(conn, paste("use", db)))
+}
+
+##############################
+# CONVERT VALUE TO SQL VALUE #
+##############################
+
+to_sql_value <- function(x) {
+
+	# NA or NULL
+	if (length(x) == 0 || is.na(x) || is.null(x))
+		return('null')
+
+	# String
+	if (is.character(x))
+		return(paste0('"', as.character(x), '"'))
+
+	return(x)
+}
+
+####################
+# MAKE INSERT LINE #
+####################
+
+make_insert_line <- function(values) {
+	values <- lapply(values, to_sql_value)
+	return(paste0("(", paste(values, collapse=','), ")"))
+}
+
+##########
+# INSERT #
+##########
+
+# Run a insert query on a MySQL database.
+# conn      Connection to a database.
+# table     Table name.
+# fields    List of field names.
+# values    List of list of values. NA values will be translated as NULL.
+insert <- function(conn, table, fields, values) {
+
+	# Do nothing if no values
+	if (length(values) == 0 ) return
+
+	# Build header
+	h <- paste("insert into", table)
+	h <- paste0(h, "(", paste(fields, collapse = ','), ")")
+	h <- paste(h, "values")
+
+	qr <- paste(h, paste0(lapply(values, make_insert_line), collapse=','), ';')
+
+	# Send query
+	run_query(conn, qr)
+}
+
+########
+# JOIN #
+########
+
+Join <- setRefClass("Join", fields = list(table = "character", left_field = "character", right_field = "character", outer = "character"))
+
+Join$methods( initialize = function(table, left_field, right_field, outer = NA_character_) {
+	table <<- table
+	left_field <<- left_field
+	right_field <<- right_field
+	outer <<- outer
+})
+
+Join$methods( getStatement = function() {
+	type <- 'INNER JOIN'
+	if ( ! is.na(outer))
+		switch(tolower(outer),
+		       left  = type <- 'LEFT OUTER JOIN',
+		       right = type <- 'RIGHT OUTER JOIN',
+		       stop('Error in join outer type. "', outer ,'" is unknown. You must choose between "LEFT" and "RIGHT".')
+		      )
+
+	return(paste(type, .self$table, 'ON', .self$left_field, '=', .self$right_field))
+})
+
+##########
+# SELECT #
+##########
+
+# Run a select query on a MySQL database. Returns the dataframe of results.
+# conn      Connection to a database.
+select <- function(conn, fields, from, joins = NULL , where = NULL, orderby = NULL) {
+
+	# Select/from
+	rq <- paste("SELECT ", paste(fields, collapse = ', '), 'FROM', from)
+
+	# Joins
+	if ( ! is.null(joins) && length(joins) > 0)
+		rq <- paste(rq, paste(lapply(joins, function (x) x$getStatement() ), collapse = ' '))
+
+	# Where
+	if ( ! is.null(where)) rq <- paste(rq, 'WHERE', where)
+
+	# Order by
+	if ( ! is.null(orderby)) rq <- paste(rq, 'ORDER BY', orderby)
+
+	# End request, send it and get results
+	rq <- paste0(rq, ';')
+	res <- try(dbSendQuery(conn, rq))
+	data <- fetch(res, n=-1)
+
+	return(data)
+}
+
+#######################
+# SELECT SINGLE FIELD #
+#######################
+
+select_single_field <- function(conn, field, from, where = NULL) {
+	values <- select(conn, fields = field, from = from, where = where)
+	val <- if (field %in% colnames(values) && length(values[field][[1]]) > 0) values[field][[1]] else NA_character_
+	return(val)
+}