; docformat = 'rst rst'
;
;+
; :Author: Paulo Penteado (http://www.ppenteado.net), Apr/2015
;-
;+
; :Description:
; Helper function, to return the mysql variable type corresponding to an IDL
; variable type.
;
; :Params:
; var: in, required
; The IDL variable whose mysql type is desired.
;
; :Keywords:
; minlen: in, optional
; If the type is a string, by default the mysql type will have the length of
; the longest string in `var`. If minlen is provided, the mysql length will be
; the greatest among minlen and the longest string in `var`.
; maxlen: in, optional
; If the type is a string, by default the mysql type will have the length of
; the longest string in `var`. If maxlen is provided, the mysql length will be
; the smallest among maxlen and the longest string in `var`.
;
;
; :Author: Paulo Penteado (http://www.ppenteado.net), Apr 2015
;-
function pp_structtomysql__typename,var,minlen=minlen,maxlen=maxlen
compile_opt idl2,logical_predicate,hidden
if isa(var,'struct') && pp_in('TYPE',tag_names(var)) && pp_in('VALUE',tag_names(var)) then begin
return,var.type
endif
ret=typename(var)
case ret of
'BYTE': ret='TINYINT UNSIGNED'
'INT' : ret='SMALLINT'
'UINT': ret='SMALLINT UNSIGNED'
'LONG': ret='INT'
'ULONG': ret='INT UNSIGNED'
'LONG64': ret='BIGINT'
'ULONG64': ret='BIGINT UNSIGNED'
'FLOAT' : ret='FLOAT'
'DOUBLE': ret='DOUBLE'
else: begin
len=max(strlen(var))
if keyword_set(minlen) then len=len>minlen
if keyword_set(maxlen) then len=len<maxlen
len=1>len
ret='VARCHAR('+strtrim(len,2)+')'
end
endcase
return,ret
end
;+
; :Description:
; Creates a table in a mysql server, from an IDL array of structures.
; Each element of the array becomes a row in the table. The column names are
; the structure field names, with a '_' appended (to avoid mysql reserved words).
; The mysql server information (address, login, password, etc) is taken from ~/.my.conf.
; This is handled by Marc Buie's `openmysql`
; (`http://www.boulder.swri.edu/~buie/idl/pro/openmysql.html <http://www.boulder.swri.edu/~buie/idl/pro/openmysql.html>`).
;
; :Params:
; struct: in, required
; The structure containing the data to be inserted in the mysql table.
; tablename: in, required, type=string
; The name of the table to be created.
;
; :Keywords:
; dbname: in, required, type=string
; The name of the database where the table is to be created.
; username: in, optional, type=string
; The username to use in mysql. Defaults to the current user.
; verbose: in, optional
; If set, the mysql commands get printed to the terminal.
; primary_key: in, optional, type=string
; If set, determines which key will be the table's primary key.
; nodeletecsv: in, optional
; During injection, the data is put into a csv file in the current directory
; (pp_structtomysql_tmpfile.csv). If this keyword is set, the file is not deleted
; at the end.
; nodroptable: in, optional
; By default, if the table to be created already exists, it is dropped, then
; created with the data provided. If this keyword is set, dropping the table is
; skipped, and this procedure will just attempt to insert the data into the table.
;
; generate_code_only: out, optional
; If provided, this variable will contain a string array with the commands that
; would have been issued to mysql. No mysql commands are executed.
;
; :Examples:
; Create a table in a mysql server (server parameters set in ~/.my.conf), then retrieve
; the data from it. In this case, assuming that there is a database named pp_structtomysql,
; and that the user has write access to it::
;
; outstruct=replicate({a:1,b:2d0,c:'def'},4)
; outstruct.a=indgen(4)
; outstruct.b=dindgen(4)^2
; outstruct.c+='_'+strtrim(indgen(4),2)
; print,outstruct
; ;{ 0 0.0000000 def_0}
; ;{ 1 1.0000000 def_1}
; ;{ 2 4.0000000 def_2}
; ;{ 3 9.0000000 def_3}
; pp_structtomysql,outstruct,'pp_structtomysql_example',primary_key='c_',dbname='pp_structtomysql'
; openmysql,lun,'pp_structtomysql'
; instruct=pp_mysqlquery(lun,'select * from pp_structtomysql_example;')
; print,instruct
; ;{ 0 0 def_0}
; ;{ 1 1 def_1}
; ;{ 2 4 def_2}
; ;{ 3 9 def_3}
; free_lun,lun
;
; :Requires: `openmysql`, `mysqlquery`, from Marc Buie's library
; (`http://www.boulder.swri.edu/~buie/idl/ <http://www.boulder.swri.edu/~buie/idl/>`).
;
; :Author: Paulo Penteado (http://www.ppenteado.net), Apr 2015
;-
pro pp_structtomysql,struct,tablename,dbname=dbname,username=username,$
verbose=verbose,primary_key=primary_key,nodeletecsv=nodeletecsv,nodroptable=nodroptable,$
generate_code_only=gencode
compile_opt idl2,logical_predicate
verbose=keyword_set(verbose)
codeonly=arg_present(gencode)
;open mysql connection
if ~codeonly then openmysql,lun,dbname,user=username
;delete table if it exists
if ~codeonly then begin
mysqlquery,lun,"show tables like '"+tablename+"';",res,verbose=verbose
if (res && (~keyword_set(nodroptable))) then mysqlquery,lun,'drop table '+tablename+';',/cmd,verbose=verbose
mysqlquery,lun,"show tables like '"+tablename+"';",res,verbose=verbose
endif
if codeonly || (~res) then begin
;create table
mcomm='create table '+tablename+' ('
foreach tn,tag_names(struct[0]),itn do begin
mcomm+=(itn eq 0 ? '' : ', ')+strupcase(tn)+'_ '+pp_structtomysql__typename(struct.(itn))
endforeach
if keyword_set(primary_key) then mcomm+=', primary key ( '+primary_key+') '
mcomm+=');'
if verbose then print,mcomm
if ~codeonly then mysqlquery,lun,mcomm,/cmd,verbose=verbose else gencode=mcomm
endif
if codeonly then return
structs={}
foreach tag,tag_names(struct),itag do begin
var=struct.(itag)
if isa(var,'struct') && pp_in('TYPE',tag_names(var)) && pp_in('VALUE',tag_names(var)) then begin
structs=create_struct(structs,tag,strjoin(var.value,string(10B)))
endif else structs=create_struct(structs,tag,var)
endforeach
fn='pp_structtomysql_tmpfile.csv'
write_csv_pp,fn,structs,/titles
mcomm="LOAD DATA LOCAL INFILE '"+fn+"' INTO TABLE "+tablename
mcomm+=" FIELDS TERMINATED BY ',' ENCLOSED BY '"+'"'+"'"
mcomm+=" LINES TERMINATED BY '\n'"
mcomm+=" IGNORE 1 LINES;"
if verbose then print,mcomm
mysqlquery,lun,mcomm,/cmd
if (~keyword_set(nodeletecsv)) then file_delete,fn
free_lun,lun
end