diff --git a/lib/plsql/package.rb b/lib/plsql/package.rb index 261120d7..be1d58bd 100644 --- a/lib/plsql/package.rb +++ b/lib/plsql/package.rb @@ -2,28 +2,34 @@ module PLSQL module PackageClassMethods #:nodoc: def find(schema, package) - if schema.select_first( - "SELECT object_name FROM all_objects - WHERE owner = :owner - AND object_name = :package - AND object_type = 'PACKAGE'", - schema.schema_name, package.to_s.upcase) - new(schema, package) - # search for synonym - elsif (row = schema.select_first( - "SELECT o.owner, o.object_name - FROM all_synonyms s, all_objects o - WHERE s.owner IN (:owner, 'PUBLIC') - AND s.synonym_name = :synonym_name - AND o.owner = s.table_owner - AND o.object_name = s.table_name - AND o.object_type = 'PACKAGE' - ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0)", - schema.schema_name, package.to_s.upcase)) - new(schema, row[1], row[0]) - else - nil - end + package_name = package.to_s.upcase + find_in_schema(schema, package_name) || find_by_synonym(schema, package_name) + end + + def find_in_schema(schema, package_name) + row = schema.select_first(<<-SQL, schema.schema_name, package_name) + SELECT object_name + FROM all_objects + WHERE owner = :owner + AND object_name = :package + AND object_type = 'PACKAGE' + SQL + new(schema, package_name) if row + end + + def find_by_synonym(schema, package_name) + row = schema.select_first(<<-SQL, schema.schema_name, package_name) + SELECT o.object_name, o.owner + FROM all_synonyms s, + all_objects o + WHERE s.owner IN (:owner, 'PUBLIC') + AND s.synonym_name = :synonym_name + AND o.owner = s.table_owner + AND o.object_name = s.table_name + AND o.object_type = 'PACKAGE' + ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0) + SQL + new(schema, row[0], row[1]) if row end end @@ -41,29 +47,41 @@ def procedure_defined?(name) PLSQL::Procedure.find(@schema, name, @package) ? true : false end + def [](object_name) + object_name = object_name.to_s.downcase + @package_objects[object_name] ||= [Procedure, Variable].inject(nil) do |res, object_type| + res || object_type.find(@schema, object_name, @package, @override_schema_name) + end + end + private - + def method_missing(method, *args, &block) - if assignment = (method.to_s[-1,1] == '=') - method = method.to_s.chop.to_sym - end - object = (@package_objects[method] ||= - Procedure.find(@schema, method, @package, @override_schema_name) || - Variable.find(@schema, method, @package, @override_schema_name)) - case object - when Procedure - raise ArgumentError, "Cannot assign value to package procedure '#{method.to_s.upcase}'" if assignment - object.exec(*args, &block) - when Variable - if assignment - raise ArgumentError, "Just one value can be assigned to package variable '#{method.to_s.upcase}'" unless args.size == 1 && block == nil - object.value = args[0] + method = method.to_s + method.chop! if (assignment = method[/=$/]) + + case (object = self[method]) + when Procedure + if assignment + raise ArgumentError, "Cannot assign value to package procedure '#{method.upcase}'" + end + object.exec(*args, &block) + when Variable + if assignment + unless args.size == 1 && block.nil? + raise ArgumentError, "Just one value can be assigned " \ + "to package variable '#{method.upcase}'" + end + object.value = args[0] + else + unless args.size == 0 && block.nil? + raise ArgumentError, "Cannot pass arguments when getting " \ + "package variable '#{method.upcase}' value" + end + object.value + end else - raise ArgumentError, "Cannot pass arguments when getting package variable '#{method.to_s.upcase}' value" unless args.size == 0 && block == nil - object.value - end - else - raise ArgumentError, "No PL/SQL procedure or variable '#{method.to_s.upcase}' found" + raise ArgumentError, "No PL/SQL procedure or variable '#{method.upcase}' found" end end diff --git a/spec/plsql/package_spec.rb b/spec/plsql/package_spec.rb index 71a38247..df748f07 100644 --- a/spec/plsql/package_spec.rb +++ b/spec/plsql/package_spec.rb @@ -55,6 +55,18 @@ expect(plsql.test_package.procedure_defined?(:inexistent_procedure)).to be_falsey end + it "should search objects via []" do + package = PLSQL::Package.find(plsql, :test_package) + + [:Test_Procedure, :test_procedure, 'test_procedure', 'TEST_PROCEDURE'].each do |name_variant| + expect(package[name_variant]).to be_a PLSQL::Procedure + end + + [:Test_Variable, :test_variable, 'test_variable', 'TEST_VARIABLE'].each do |name_variant| + expect(package[name_variant]).to be_a PLSQL::Variable + end + end + describe "variables" do it "should set and get package variable value" do plsql.test_package.test_variable = 1