0
class Admin::UploadController < ApplicationController
0
before_filter :login_required
0
layout 'admin/admin.rhtml'
0
@@ -13,12 +15,12 @@ class Admin::UploadController < ApplicationController
0
# entry in the hash contains a list of all the library versions
0
- unless @libraries[l.name] then @libraries[l.name] = Array.new end
0
- @libraries[l.name].push(l)
0
+ unless @libraries[l.name] then @libraries[l.name] = Array.new end
0
+ @libraries[l.name].push(l)
0
- # delete
a library and all of its contents
0
+ # delete
libraries and all of their associated contents
0
library_ids = @params[:id]
0
@@ -29,20 +31,33 @@ class Admin::UploadController < ApplicationController
0
library = RaLibrary.find(library_id)
0
- RaCodeObject.connection.delete("DELETE ra_code_objects FROM ra_code_objects, ra_containers WHERE ra_code_objects.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
- RaInFile.connection.delete("DELETE ra_in_files FROM ra_in_files, ra_containers WHERE ra_in_files.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
- RaSourceCode.connection.delete("DELETE ra_source_codes FROM ra_source_codes, ra_methods, ra_containers WHERE ra_source_codes.id = ra_methods.ra_source_code_id AND ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
- RaComment.connection.delete("DELETE ra_comments FROM ra_comments, ra_methods, ra_containers WHERE ra_comments.id = ra_methods.ra_comment_id AND ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
- RaMethod.connection.delete("DELETE ra_methods FROM ra_methods, ra_containers WHERE ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
- RaComment.connection.delete("DELETE ra_comments FROM ra_comments, ra_containers WHERE ra_comments.id = ra_containers.ra_comment_id AND ra_containers.ra_library_id =" + library_id)
0
- RaContainer.connection.delete("DELETE FROM ra_containers WHERE ra_library_id = " + library_id)
0
- RaLibrary.connection.delete("DELETE FROM ra_libraries WHERE id =" + library_id)
0
+ # ok this really should be more activerecord'ish
0
+ # but I didn't have enough time to do that, so for now we know it works on
0
+ # two DBs, mysql and postgres
0
+ RaCodeObject.connection.delete("DELETE ra_code_objects FROM ra_code_objects, ra_containers WHERE ra_code_objects.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
+ RaInFile.connection.delete("DELETE ra_in_files FROM ra_in_files, ra_containers WHERE ra_in_files.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
+ RaSourceCode.connection.delete("DELETE ra_source_codes FROM ra_source_codes, ra_methods, ra_containers WHERE ra_source_codes.id = ra_methods.ra_source_code_id AND ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
+ RaComment.connection.delete("DELETE ra_comments FROM ra_comments, ra_methods, ra_containers WHERE ra_comments.id = ra_methods.ra_comment_id AND ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
+ RaMethod.connection.delete("DELETE ra_methods FROM ra_methods, ra_containers WHERE ra_methods.ra_container_id = ra_containers.id AND ra_containers.ra_library_id = " + library_id)
0
+ RaComment.connection.delete("DELETE ra_comments FROM ra_comments, ra_containers WHERE ra_comments.id = ra_containers.ra_comment_id AND ra_containers.ra_library_id =" + library_id)
0
+ RaContainer.connection.delete("DELETE FROM ra_containers WHERE ra_library_id = " + library_id)
0
+ RaLibrary.connection.delete("DELETE FROM ra_libraries WHERE id =" + library_id)
0
+ RaCodeObject.connection.delete("DELETE FROM ra_code_objects WHERE id IN (SELECT ra.id FROM ra_code_objects AS ra, ra_containers AS rc, ra_libraries AS rl WHERE ra.ra_container_id = rc.id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaInFile.connection.delete("DELETE FROM ra_in_files WHERE id in (SELECT ra.id FROM ra_in_files AS ra, ra_containers AS rc, ra_libraries AS rl WHERE ra.ra_container_id = rc.id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaSourceCode.connection.delete("DELETE FROM ra_source_codes WHERE id IN (SELECT rs.id FROM ra_source_codes AS rs, ra_methods AS rm, ra_containers AS rc, ra_libraries AS rl WHERE rs.id = rm.ra_source_code_id AND rm.ra_container_id = rc.id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaComment.connection.delete("DELETE FROM ra_comments WHERE id IN (SELECT rs.id FROM ra_comments AS rs, ra_methods AS rm, ra_containers AS rc, ra_libraries AS rl WHERE rs.id = rm.ra_comment_id AND rm.ra_container_id = rc.id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaMethod.connection.delete("DELETE FROM ra_methods WHERE id IN (SELECT ra.id FROM ra_methods AS ra, ra_containers AS rc, ra_libraries AS rl WHERE ra.ra_container_id = rc.id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaComment.connection.delete("DELETE FROM ra_comments WHERE id IN (SELECT rs.id FROM ra_comments AS rs, ra_containers AS rc, ra_libraries AS rl WHERE rs.id = rc.ra_comment_id AND rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
+ RaContainer.connection.delete("DELETE FROM ra_containers WHERE id IN (SELECT rc.id FROM ra_containers AS rc, ra_libraries AS rl WHERE rc.ra_library_id = rl.id AND rl.id =" + library_id + ")")
0
# make sure that the highest library version is still marked as the current version
0
libraries = RaLibrary.find(:all, :conditions => ["name = ?", name])
0
libraries.each do |lib|
0
if(lib.version > max_ver)
0
@@ -60,139 +75,179 @@ class Admin::UploadController < ApplicationController
0
redirect_to :action => :list
0
- # Try and avoid errors for PostgreSQL and maybe other databases too.
0
- # If it fails, we log an exception instead of putting up an error page
0
- # because we can still complete the mission, just slower?
0
- def autocommit(state=true)
0
- ActiveRecord::Base.connection.execute( 'SET AUTOCOMMIT=' + state ? '1' : '0' )
0
- ActiveRecord::Base.connection.execute( state ? 'BEGIN' : 'COMMIT' )
0
- logger.info "Oops. #{e.to_s}\n" + e.backtrace.join + "\n"
0
+ # given a directory import all files from that directory
0
+ dir = params[:directory]
0
+ files = Dir.glob(dir + "/*.out")
0
+ @success << "failed: " + file + " " + @error
0
+ @success << "failed: " + file + " " + @error
0
+ @success << "success: " + file
0
+ render :action => :create
0
+ # import a single file
0
- @connection = ActiveRecord::Base.connection
0
+ do_import(params['doc_file'], true)
0
+ @success = ["success: " + params['doc_file'].original_filename]
0
+ render :action => :create
0
- if(@connection.class.to_s =~ /mysql/i)
0
- # check to see if the connection is MySQL, if so then we have created some
0
- # optimizations for MySql inserts
0
- @connection_type = "mysql"
0
- @connection_type = "other"
0
- # Lookup hash used to map ids in the YAML file to database IDs
0
+ # import a single library into the database
0
+ def do_import(file, tempfile = false)
0
+ @connection = ActiveRecord::Base.connection
0
+ if(@connection.class.to_s =~ /mysql/i)
0
+ # check to see if the connection is MySQL, if so then we have created some
0
+ # optimizations for MySql inserts
0
+ @connection_type = "mysql"
0
+ @connection_type = "other"
0
- # Lookup hash used to keep columns around so that they do not need to be
0
+ # Lookup hash used to map ids in the YAML file to database IDs
0
- file_name = @params['doc_file'].original_filename
0
- match = /([a-zA-Z]+)-([0-9]+)\.([0-9]+)\.([0-9]+)\.out/.match(file_name)
0
- @error = "File name must have the format name-major.minor.release.out, ex: rails-1.2.1.out"
0
- render :action => :index
0
+ # Lookup hash used to keep columns around so that they do not need to be
0
+ # should we be reading the file passed in, or is it a file stream already
0
+ file_name = file.original_filename
0
+ match = /([a-zA-Z0-9]+)-([0-9]+)\.([0-9]+)\.([0-9]+)\.out/.match(file_name)
0
+ @error = "File name must have the format name-major.minor.release.out, ex: rails-1.2.1.out"
0
- ActiveRecord::Base.connection.transaction do
0
- # Create a new library object
0
- @library = RaLibrary.new({:name => match[1], :major => match[2], :minor => match[3], :release => match[4]})
0
- @library.current = false
0
- @library.date = DateTime.now
0
- if(@library.find_lib == nil)
0
+ # measure the time it takes to do the DB inserts
0
+ # Set the logging level to ERROR so that we do not output SQL when we are debugging
0
+ # that really slows things down
0
+ loglevel = logger.level
0
+ logger.level = Logger::ERROR
0
+ ActiveRecord::Base.connection.transaction do
0
+ # Create a new library object
0
+ @library = RaLibrary.new({:name => match[1], :major => match[2], :minor => match[3], :release => match[4]})
0
+ @library.current = false
0
+ @library.date = DateTime.now
0
+ if(@library.find_lib == nil)
0
+ # ok now we need to see if the library version that we uploaded is the most recent version of this library
0
+ higher_version = RaLibrary.find(:first, :conditions => ["name = ? AND version > ?", @library.name, @library.version])
0
+ if(higher_version == nil)
0
+ # if our version is the most recent remove the current status from all the current entries
0
+ currents = RaLibrary.find(:all, :conditions => ["name = ? AND current = ?", @library.name, true])
0
+ # now set the status of this library to be most recent and save it
0
+ @library.current = true
0
- # ok now we need to see if the library version that we uploaded is the most recent version of this library
0
- higher_version = RaLibrary.find(:first, :conditions => ["name = ? AND version > ?", @library.name, @library.version])
0
- if(higher_version == nil)
0
- # if our version is the most recent remove the current status from all the current entries
0
- currents = RaLibrary.find(:all, :conditions => ["name = ? AND current = ?", @library.name, true])
0
- # now set the status of this library to be most recent and save it
0
- @library.current = true
0
- # measure the time it takes to do the DB inserts
0
+ @error = "Could not import library " + file_name + " already exists"
0
+ # Read in the YAML file
0
+ file = File.open(file)
0
+ yp = YAML::load_documents( file ) { |doc|
0
+ # if this is a library record then merge the attributes
0
+ # with our library and save it (can provide more information)
0
+ if(doc.class.to_s == RaLibrary.to_s)
0
+ # if there is a 'main' attribute it will be the name of the
0
+ # file that should be displayed as the home page for this library
0
+ # this should be translated to the container id
0
+ if(doc.attributes['home_page'] != nil)
0
+ home_page = RaContainer.find(:first, :conditions => ["full_name = ? AND ra_library_id = ?", doc.home_page, @library.id])
0
+ @library.main_container_id = home_page.id
0
+ attr.delete("home_page")
0
+ @library.update_attributes(attr)
0
+ # Each record has a unique id. This id changes though when we insert it into the
0
+ # database. This would not be a problem except that all of the records are associated
0
+ # by these ids so when a record is inserted into the DB we need to make sure the associations are
0
+ # updated. get_ids takes care of this updating.
0
+ # IMPORTANT NOTE: This requires that the YAML is written out in the correct order so that we always insert
0
+ # a record before we need its id for an association
0
+ lookup[id] = insert_object(doc)
0
- # Set the logging level to ERROR so that we do not output SQL when we are debugging
0
- # that really slows things down
0
- loglevel = logger.level
0
- logger.level = Logger::ERROR
0
- # Read in the YAML file
0
- yp = YAML::load_documents( @params['doc_file'] ) { |doc|
0
- # Each record has a unique id. This id changes though when we insert it into the
0
- # database. This would not be a problem except that all of the records are associated
0
- # by these ids so when a record is inserted into the DB we need to make sure the associations are
0
- # updated. get_ids takes care of this updating.
0
- # IMPORTANT NOTE: This requires that the YAML is written out in the correct order so that we always insert
0
- # a record before we need its id for an association.
0
- lookup[id] = insert_object(doc)
0
- @total_time = Time.now - start
0
- logger.level = loglevel
0
- @error = "Could not import library, already exists"
0
- render :action => :create
0
- # Insert an active record object into the DB
0
- def insert_object(obj)
0
- if(@connection_type == "mysql")
0
- # We don't want to use the ActiveRecord::Base.save method because it is slow
0
- # ~1300 inserts on a MySQL DB MyIASM table on windows is 5.7 seconds with this method
0
- # and 17.5 seconds using .save
0
- unless(@col_hash[obj.class.to_s])
0
- @col_hash[obj.class.to_s] = column_list(obj.attributes.keys)
0
- columns = @col_hash[obj.class.to_s]
0
- values = value_list(obj.attributes.values)
0
- val = @connection.insert "INSERT INTO #{obj.class.table_name} (#{columns}) VALUES (#{values})"
0
- # slower but works on PostgreSQL and other DBs where they cannot have a NULL id in the insert
0
+ logger.level = loglevel
0
+ @total_time = Time.now - start
0
+ def insert_object(obj)
0
+ # We don't want to use the ActiveRecord::Base.save method because it is slow
0
+ # ~1300 inserts on a MySQL DB MyIASM table on windows is 5.7 seconds with this method
0
+ # and 17.5 seconds using .save
0
+ unless(@col_hash[obj.class.to_s])
0
+ @col_hash[obj.class.to_s] = column_list(obj.attributes.keys.reject! { |key| key =~ /^id$/ })
0
+ columns = @col_hash[obj.class.to_s]
0
+ attributes = obj.attributes
0
+ attributes.delete('id') # remove the id column
0
+ values = value_list(attributes.values) if attributes
0
+ val = @connection.insert "INSERT INTO #{obj.class.table_name} (#{columns}) VALUES (#{values})" if values
0
# Create a list of column names from an array of strings
0
@@ -202,36 +257,60 @@ private
0
# Create a list of insertable values from an array of strings
0
- values.map { |v| ActiveRecord::Base.connection.quote(v).gsub('\
\n', "\n").gsub('\\r', "\r") }.join(", ")
0
+ values.map { |v| ActiveRecord::Base.connection.quote(v).gsub('\
n', "\\n").gsub('\r', "\\r") }.join(", ")
0
# Lookup the database ids for all the associations for this type of object
0
- def get_ids(doc, lookup)
0
+ def get_ids(doc, lookup)
0
case(doc.class.superclass.to_s)
0
doc.ra_container_id = lookup[doc.ra_container_id]
0
+ doc.file_id = lookup[doc.file_id]
0
doc.parent_id = lookup[doc.parent_id]
0
doc.ra_comment_id = lookup[doc.ra_comment_id]
0
- doc.ra_library_id = @library.id
0
+ doc.ra_library_id = @library.id
0
+ puts "#{doc.class.to_s} - #{doc.id}"
0
+ doc.file_id = lookup[doc.file_id]
0
+ doc.file_id = lookup[doc.file_id]
0
doc.ra_container_id = lookup[doc.ra_container_id]
0
doc.ra_comment_id = lookup[doc.ra_comment_id]
0
doc.ra_source_code_id = lookup[doc.ra_source_code_id]
0
+ doc.file_id = lookup[doc.file_id]
0
doc.ra_container_id = lookup[doc.ra_container_id]
0
- # if none of these classes has been previously used then the
0
- # YAML load will fail because it will not find the class to be able to
0
- # instantiate it, not sure why this happens, but this here fixes that issue
0
- # by creating an instance of each class needed
0
+ # Try and avoid errors for PostgreSQL and maybe other databases too.
0
+ # If it fails, we log an exception instead of putting up an error page
0
+ # because we can still complete the mission, just slower?
0
+ def autocommit(state=true)
0
+ ActiveRecord::Base.connection.execute('SET AUTOCOMMIT = ' + (state ? '1' : '0') )
0
+ ActiveRecord::Base.connection.execute( state ? 'BEGIN' : 'COMMIT' )
0
+ logger.info "Oops. #{e.to_s}\n" + e.backtrace.join + "\n"
0
+ # if none of these classes has been previously used then the
0
+ # YAML load will fail because it will not find the class to be able to
0
+ # instantiate it, not sure why this happens, but this here fixes that issue
0
+ # by creating an instance of each class needed