intersys 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/Makefile +9 -9
 - data/lib/callable.rb +86 -0
 - data/lib/database.c +21 -1
 - data/lib/extconf.rb +33 -9
 - data/lib/global.c +66 -0
 - data/lib/intersys.c +24 -3
 - data/lib/intersys.h +29 -2
 - data/lib/intersys.rb +59 -350
 - data/lib/intersys_adapter.rb +132 -0
 - data/lib/object.rb +163 -0
 - data/lib/query.c +143 -3
 - data/lib/reflection.rb +113 -0
 - data/lib/sql_include/iodbcunix.h +149 -0
 - data/lib/sql_include/sql.h +1189 -0
 - data/lib/sql_include/sqlext.h +2566 -0
 - data/lib/sql_include/sqltypes.h +421 -0
 - data/lib/sql_include/sqlucode.h +812 -0
 - data/test/adapter.rb +19 -0
 - data/test/global.rb +12 -0
 - data/test/query.rb +5 -0
 - data/test/reflection.rb +7 -6
 - data/test/strings.rb +2 -1
 - metadata +15 -3
 - data/lib/test.rb +0 -30
 
| 
         @@ -0,0 +1,132 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author/Maintainer: Max Lapshin <max@maxidoors.ru>
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_gem 'activerecord'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'active_record/connection_adapters/abstract_adapter'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 9 
     | 
    
         
            +
              class Base
         
     | 
| 
      
 10 
     | 
    
         
            +
                def self.intersys_connection(config)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  config = config.symbolize_keys
         
     | 
| 
      
 12 
     | 
    
         
            +
                  require 'intersys'
         
     | 
| 
      
 13 
     | 
    
         
            +
                  intersys = Intersys::Database.new(config)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  ConnectionAdapters::IntersysAdapter.new(intersys, logger, config)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 19 
     | 
    
         
            +
                class IntersysAdapter < AbstractAdapter
         
     | 
| 
      
 20 
     | 
    
         
            +
                  attr_reader :config
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize(database, logger, config)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    super(database, logger)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @config = config
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def adapter_name #:nodoc:
         
     | 
| 
      
 27 
     | 
    
         
            +
                    'Intersys Caché'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def supports_migrations? #:nodoc:
         
     | 
| 
      
 31 
     | 
    
         
            +
                    false
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def active?
         
     | 
| 
      
 35 
     | 
    
         
            +
                    warn "IntersysAdapter#active? not implemented"
         
     | 
| 
      
 36 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @connection.query "select 1"
         
     | 
| 
      
 38 
     | 
    
         
            +
                  rescue Intersys::IntersysException
         
     | 
| 
      
 39 
     | 
    
         
            +
                    false
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  
         
     | 
| 
      
 42 
     | 
    
         
            +
                  def disconnect!
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @connection.close! rescue nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def reconnect!
         
     | 
| 
      
 47 
     | 
    
         
            +
                    disconnect!
         
     | 
| 
      
 48 
     | 
    
         
            +
                    connect
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  
         
     | 
| 
      
 51 
     | 
    
         
            +
                  def begin_db_transaction
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @connection.start
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  def commit_db_transaction
         
     | 
| 
      
 55 
     | 
    
         
            +
                    @connection.commit
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def rollback_db_transaction
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @connection.rollback
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  
         
     | 
| 
      
 61 
     | 
    
         
            +
                  def add_limit_offset!(sql, options)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    sql << " LIMIT #{limit}" if limit = options[:limit]
         
     | 
| 
      
 63 
     | 
    
         
            +
                    sql << " OFFSET #{offset}" if offset = options[:offset]
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def select_all(sql, name = nil) #:nodoc:
         
     | 
| 
      
 67 
     | 
    
         
            +
                    select(sql, name)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def select_one(sql, name = nil) #:nodoc:
         
     | 
| 
      
 71 
     | 
    
         
            +
                    result = select(sql, name)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    result.nil? ? nil : result.first
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         
     | 
| 
      
 76 
     | 
    
         
            +
                    execute(sql, name = nil)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    id_value || @connection.insert_id
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def update(sql, name = nil) #:nodoc:
         
     | 
| 
      
 81 
     | 
    
         
            +
                    execute(sql, name)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    @connection.affected_rows
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  alias_method :delete, :update #:nodoc:
         
     | 
| 
      
 86 
     | 
    
         
            +
                    
         
     | 
| 
      
 87 
     | 
    
         
            +
                  
         
     | 
| 
      
 88 
     | 
    
         
            +
                  
         
     | 
| 
      
 89 
     | 
    
         
            +
                  def columns(table_name, name = nil)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @cdef = Intersys::Reflection::ClassDefinition.open("User.#{table_name.camelize}")
         
     | 
| 
      
 91 
     | 
    
         
            +
                    result = [IntersysColumn.new("id", "", "int")]
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @cdef.properties.each do |prop|
         
     | 
| 
      
 93 
     | 
    
         
            +
                      result << IntersysColumn.new(prop.sql_field_name, prop.initial_expression, prop.Type.gsub("%","").underscore, prop.required)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                    result
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                  def native_database_types
         
     | 
| 
      
 99 
     | 
    
         
            +
                    {
         
     | 
| 
      
 100 
     | 
    
         
            +
                      :primary_key => 'int generated by default as identity (start with 42) primary key',
         
     | 
| 
      
 101 
     | 
    
         
            +
                      :string      => { :name => 'varchar', :limit => 255 },
         
     | 
| 
      
 102 
     | 
    
         
            +
                      :text        => { :name => 'clob', :limit => 32768 },
         
     | 
| 
      
 103 
     | 
    
         
            +
                      :integer     => { :name => 'int' },
         
     | 
| 
      
 104 
     | 
    
         
            +
                      :float       => { :name => 'float' },
         
     | 
| 
      
 105 
     | 
    
         
            +
                      :datetime    => { :name => 'timestamp' },
         
     | 
| 
      
 106 
     | 
    
         
            +
                      :timestamp   => { :name => 'timestamp' },
         
     | 
| 
      
 107 
     | 
    
         
            +
                      :time        => { :name => 'time' },
         
     | 
| 
      
 108 
     | 
    
         
            +
                      :date        => { :name => 'date' },
         
     | 
| 
      
 109 
     | 
    
         
            +
                      :binary      => { :name => 'blob', :limit => 32768 },
         
     | 
| 
      
 110 
     | 
    
         
            +
                      :boolean     => { :name => 'decimal', :limit => 1 }
         
     | 
| 
      
 111 
     | 
    
         
            +
                    }
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  
         
     | 
| 
      
 114 
     | 
    
         
            +
                protected
         
     | 
| 
      
 115 
     | 
    
         
            +
                  # :nodoc
         
     | 
| 
      
 116 
     | 
    
         
            +
                  def connect
         
     | 
| 
      
 117 
     | 
    
         
            +
                    @connection = Intersys::Database.new(config)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  
         
     | 
| 
      
 120 
     | 
    
         
            +
                  def select(sql, name = nil)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    @connection.query(sql)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  def execute(sql, name = nil)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    @connection.execute(sql)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
                
         
     | 
| 
      
 129 
     | 
    
         
            +
                class IntersysColumn < Column
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
              end
         
     | 
| 
      
 132 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/object.rb
    ADDED
    
    | 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intersys
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Basic class for all classes, through which is performed access to Cache classes
         
     | 
| 
      
 3 
     | 
    
         
            +
            # For each Cache class must be created ruby class, inherited from Intersys::Object
         
     | 
| 
      
 4 
     | 
    
         
            +
            # 
         
     | 
| 
      
 5 
     | 
    
         
            +
            # By default prefix "User" is selected. If Cache class has another prefix, it must
         
     | 
| 
      
 6 
     | 
    
         
            +
            # be provided explicitly via method "prefix":
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   class List < Intersys::Object
         
     | 
| 
      
 8 
     | 
    
         
            +
            #     prefix "%Library"
         
     | 
| 
      
 9 
     | 
    
         
            +
            #   end
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # By default name of Cache class is taken the same as name of ruby class.
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Thus in this example this class List will be marshalled to Cache class 
         
     | 
| 
      
 13 
     | 
    
         
            +
            # %Library.List
         
     | 
| 
      
 14 
     | 
    
         
            +
            #
         
     | 
| 
      
 15 
     | 
    
         
            +
            class Object
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 18 
     | 
    
         
            +
              protected      
         
     | 
| 
      
 19 
     | 
    
         
            +
                def class_names
         
     | 
| 
      
 20 
     | 
    
         
            +
                  common_get_or_set("@class_names", {})
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def prefix=(name)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @prefix = name
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @class_name = @prefix + "." + (@class_name ? @class_name.split(".").last : self.to_s)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  register_name!
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def class_name=(name)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  if name.index(".")
         
     | 
| 
      
 31 
     | 
    
         
            +
                    self.prefix = name.split(".").first
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @class_name = name
         
     | 
| 
      
 33 
     | 
    
         
            +
                  else
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @class_name = self.prefix + "." + name
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  register_name!
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Register class name of current class in global list
         
     | 
| 
      
 40 
     | 
    
         
            +
                def register_name!
         
     | 
| 
      
 41 
     | 
    
         
            +
                  if i = class_names.index(self)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    class_names.delete(i)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  class_names[class_name] = self
         
     | 
| 
      
 45 
     | 
    
         
            +
                  class_name
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
                
         
     | 
| 
      
 48 
     | 
    
         
            +
              public
         
     | 
| 
      
 49 
     | 
    
         
            +
                # Nice function, that generates description of Cache class, looking just as C++ one
         
     | 
| 
      
 50 
     | 
    
         
            +
                # Maybe, later, it will be possible even to generate IDL, using this code
         
     | 
| 
      
 51 
     | 
    
         
            +
                def intersys_description
         
     | 
| 
      
 52 
     | 
    
         
            +
                  "class #{class_name} { \n" + intersys_reflector.all_methods.map do |mtd| 
         
     | 
| 
      
 53 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 54 
     | 
    
         
            +
                      "\t"+intersys_method(mtd).description+";\n"
         
     | 
| 
      
 55 
     | 
    
         
            +
                    rescue
         
     | 
| 
      
 56 
     | 
    
         
            +
                      "\tundefined #{mtd}\n"
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end.join("") + "};"
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # Help to work with instance variables of Intersys::Object class
         
     | 
| 
      
 62 
     | 
    
         
            +
                # required, because list of registered descendants of Intersys::Object,
         
     | 
| 
      
 63 
     | 
    
         
            +
                # database connection etc. should be in one place
         
     | 
| 
      
 64 
     | 
    
         
            +
                def common_get_or_set(name, default_value = nil)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  unless var = Intersys::Object.instance_variable_get(name)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    default = block_given? ? yield : default_value
         
     | 
| 
      
 67 
     | 
    
         
            +
                    var = Intersys::Object.instance_variable_set(name, default)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                  var
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                # Takes Cache class name and try to resolve it to Ruby class
         
     | 
| 
      
 73 
     | 
    
         
            +
                def lookup(class_name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  class_names[class_name] || raise(UnMarshallError, "Couldn't find registered class with Cache name '#{class_name}'")
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              
         
     | 
| 
      
 77 
     | 
    
         
            +
                # Each Cache class has prefix before it's name: namespace.
         
     | 
| 
      
 78 
     | 
    
         
            +
                # this method set's prefix for current class is provided,
         
     | 
| 
      
 79 
     | 
    
         
            +
                # or just returns current prefix
         
     | 
| 
      
 80 
     | 
    
         
            +
                def prefix(name = nil)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  self.prefix = name if name
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @prefix ||= "User"
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                # Returns Cache class name, if called without parameters, or sets one, if passed
         
     | 
| 
      
 86 
     | 
    
         
            +
                def class_name(name = nil)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  self.class_name = name if name
         
     | 
| 
      
 88 
     | 
    
         
            +
                  self.class_name = (prefix + "." + to_s) unless @class_name
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @class_name 
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                # Returns database, if called without parameters, or sets one, if passed
         
     | 
| 
      
 93 
     | 
    
         
            +
                # Once established, it is not possible now to connect to another database
         
     | 
| 
      
 94 
     | 
    
         
            +
                def database(db_options = {})
         
     | 
| 
      
 95 
     | 
    
         
            +
                  common_get_or_set("@database") do
         
     | 
| 
      
 96 
     | 
    
         
            +
                    Intersys::Database.new({:user => "_SYSTEM", :password => "SYS", :namespace => "User"}.merge(db_options))
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
                
         
     | 
| 
      
 100 
     | 
    
         
            +
                # This method takes block and executes it between
         
     | 
| 
      
 101 
     | 
    
         
            +
                # START TRANSACTION and COMMIT TRANSACTION
         
     | 
| 
      
 102 
     | 
    
         
            +
                #
         
     | 
| 
      
 103 
     | 
    
         
            +
                # In case of exception ROLLBACK TRANSACTION is called
         
     | 
| 
      
 104 
     | 
    
         
            +
                def transaction
         
     | 
| 
      
 105 
     | 
    
         
            +
                  return unless block_given?
         
     | 
| 
      
 106 
     | 
    
         
            +
                  database.start
         
     | 
| 
      
 107 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 108 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 109 
     | 
    
         
            +
                    database.commit
         
     | 
| 
      
 110 
     | 
    
         
            +
                  rescue StandardError => e
         
     | 
| 
      
 111 
     | 
    
         
            +
                    database.rollback
         
     | 
| 
      
 112 
     | 
    
         
            +
                    raise e
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                # :nodoc
         
     | 
| 
      
 117 
     | 
    
         
            +
                def inherited(klass)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  class_names[klass.class_name] = klass
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
              
         
     | 
| 
      
 121 
     | 
    
         
            +
                # Look into Cache documentation for what is concurrency. I don't know
         
     | 
| 
      
 122 
     | 
    
         
            +
                def concurrency
         
     | 
| 
      
 123 
     | 
    
         
            +
                  1
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
              
         
     | 
| 
      
 126 
     | 
    
         
            +
                # timeout for connection
         
     | 
| 
      
 127 
     | 
    
         
            +
                def timeout
         
     | 
| 
      
 128 
     | 
    
         
            +
                  5
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
              
         
     | 
| 
      
 131 
     | 
    
         
            +
                # Nice method, that deletes all instances of class. 
         
     | 
| 
      
 132 
     | 
    
         
            +
                # You can just Person.delete_extent, but Person.delete_all looks more like ActiveRecord
         
     | 
| 
      
 133 
     | 
    
         
            +
                def delete_all
         
     | 
| 
      
 134 
     | 
    
         
            +
                  intersys_call("%DeleteExtent")
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
              
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
              
         
     | 
| 
      
 139 
     | 
    
         
            +
              # You can ask for database from instance
         
     | 
| 
      
 140 
     | 
    
         
            +
              def database
         
     | 
| 
      
 141 
     | 
    
         
            +
                self.class.database
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
              
         
     | 
| 
      
 144 
     | 
    
         
            +
              # You can ask from instance it's Cache class name
         
     | 
| 
      
 145 
     | 
    
         
            +
              def class_name
         
     | 
| 
      
 146 
     | 
    
         
            +
                self.class.class_name
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
              
         
     | 
| 
      
 149 
     | 
    
         
            +
              # Returns id of current object.
         
     | 
| 
      
 150 
     | 
    
         
            +
              # You can remove this method and You will get string ID, so leave it here
         
     | 
| 
      
 151 
     | 
    
         
            +
              # However, if You ask reflector for id, it will give incorrect answer,
         
     | 
| 
      
 152 
     | 
    
         
            +
              # because Cache allows id to be string
         
     | 
| 
      
 153 
     | 
    
         
            +
              def id
         
     | 
| 
      
 154 
     | 
    
         
            +
                intersys_call("%Id").to_i
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
              
         
     | 
| 
      
 157 
     | 
    
         
            +
              # Destroys current object
         
     | 
| 
      
 158 
     | 
    
         
            +
              def destroy
         
     | 
| 
      
 159 
     | 
    
         
            +
                self.class.intersys_call("%DeleteId", id)
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
              
         
     | 
| 
      
 162 
     | 
    
         
            +
            end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/query.c
    CHANGED
    
    | 
         @@ -1,4 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include "intersys.h"
         
     | 
| 
      
 2 
     | 
    
         
            +
            #ifdef HAVE_SQL_H
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       2 
4 
     | 
    
         
             
            #ifdef __CYGWIN__
         
     | 
| 
       3 
5 
     | 
    
         
             
            #include <windef.h>
         
     | 
| 
       4 
6 
     | 
    
         
             
            #endif
         
     | 
| 
         @@ -31,8 +33,97 @@ VALUE intersys_query_initialize(VALUE self, VALUE database, VALUE sql_query) { 
     | 
|
| 
       31 
33 
     | 
    
         
             
            	int sql_code;
         
     | 
| 
       32 
34 
     | 
    
         
             
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
       33 
35 
     | 
    
         
             
            	Data_Get_Struct(database, struct rbDatabase, base);
         
     | 
| 
      
 36 
     | 
    
         
            +
            	rb_iv_set(self, "@database", database);
         
     | 
| 
      
 37 
     | 
    
         
            +
            	query->limit = -1;
         
     | 
| 
       34 
38 
     | 
    
         
             
            	RUN(cbind_alloc_query(base->database, &query->query));
         
     | 
| 
       35 
     | 
    
         
            -
            	RUN(cbind_prepare_gen_query(query->query, WCHARSTR(sql_query), &sql_code));
         
     | 
| 
      
 39 
     | 
    
         
            +
            	RUN(cbind_prepare_gen_query(query->query, WCHARSTR(TOWCHAR(sql_query)), &sql_code));
         
     | 
| 
      
 40 
     | 
    
         
            +
            	return self;
         
     | 
| 
      
 41 
     | 
    
         
            +
            }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            static void query_bind_one_param(h_query query, int index, VALUE obj) {
         
     | 
| 
      
 44 
     | 
    
         
            +
            	int sql_type;
         
     | 
| 
      
 45 
     | 
    
         
            +
                RUN(cbind_query_get_par_sql_type(query, index, &sql_type));
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                switch (sql_type) {
         
     | 
| 
      
 48 
     | 
    
         
            +
                    case SQL_CHAR:
         
     | 
| 
      
 49 
     | 
    
         
            +
                    case SQL_VARCHAR:
         
     | 
| 
      
 50 
     | 
    
         
            +
                    case SQL_LONGVARCHAR: {
         
     | 
| 
      
 51 
     | 
    
         
            +
            			VALUE str = rb_funcall(obj, rb_intern("to_s"), 0);
         
     | 
| 
      
 52 
     | 
    
         
            +
                        RUN(cbind_query_set_mb_str_par(query, index, STR(str), LEN(str)));
         
     | 
| 
      
 53 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 54 
     | 
    
         
            +
                    }
         
     | 
| 
      
 55 
     | 
    
         
            +
                    case SQL_BINARY:
         
     | 
| 
      
 56 
     | 
    
         
            +
                    case SQL_LONGVARBINARY:
         
     | 
| 
      
 57 
     | 
    
         
            +
                    case SQL_VARBINARY: {
         
     | 
| 
      
 58 
     | 
    
         
            +
            			VALUE str = rb_funcall(obj, rb_intern("to_s"), 0);
         
     | 
| 
      
 59 
     | 
    
         
            +
                        RUN(cbind_query_set_bin_par(query, index, STR(str), LEN(str)));
         
     | 
| 
      
 60 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 61 
     | 
    
         
            +
                    }
         
     | 
| 
      
 62 
     | 
    
         
            +
                    case SQL_TINYINT:
         
     | 
| 
      
 63 
     | 
    
         
            +
                    case SQL_SMALLINT:
         
     | 
| 
      
 64 
     | 
    
         
            +
                    case SQL_INTEGER:
         
     | 
| 
      
 65 
     | 
    
         
            +
                    case SQL_BIGINT:
         
     | 
| 
      
 66 
     | 
    
         
            +
                    case SQL_BIT:
         
     | 
| 
      
 67 
     | 
    
         
            +
                    {
         
     | 
| 
      
 68 
     | 
    
         
            +
            			VALUE num = rb_funcall(obj, rb_intern("to_i"), 0);
         
     | 
| 
      
 69 
     | 
    
         
            +
                        RUN(cbind_query_set_int_par(query, index, NUM2INT(num)));
         
     | 
| 
      
 70 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
      
 72 
     | 
    
         
            +
                    case SQL_FLOAT:
         
     | 
| 
      
 73 
     | 
    
         
            +
                    case SQL_DOUBLE:
         
     | 
| 
      
 74 
     | 
    
         
            +
                    case SQL_REAL:
         
     | 
| 
      
 75 
     | 
    
         
            +
                    case SQL_NUMERIC:
         
     | 
| 
      
 76 
     | 
    
         
            +
                    case SQL_DECIMAL:
         
     | 
| 
      
 77 
     | 
    
         
            +
                    {
         
     | 
| 
      
 78 
     | 
    
         
            +
            			VALUE f = rb_funcall(obj, rb_intern("to_f"), 0);
         
     | 
| 
      
 79 
     | 
    
         
            +
                        RUN(cbind_query_set_double_par(query, index, RFLOAT(f)->value));
         
     | 
| 
      
 80 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 81 
     | 
    
         
            +
                    }
         
     | 
| 
      
 82 
     | 
    
         
            +
                    case SQL_TIME:
         
     | 
| 
      
 83 
     | 
    
         
            +
                    {
         
     | 
| 
      
 84 
     | 
    
         
            +
            			int hour = NUM2INT(CALL(obj, "hour"));
         
     | 
| 
      
 85 
     | 
    
         
            +
            			int minute = NUM2INT(CALL(obj, "min"));
         
     | 
| 
      
 86 
     | 
    
         
            +
            			int second = NUM2INT(CALL(obj, "sec"));
         
     | 
| 
      
 87 
     | 
    
         
            +
            			RUN(cbind_query_set_time_par(query, index, hour, minute, second));
         
     | 
| 
      
 88 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 89 
     | 
    
         
            +
                    }
         
     | 
| 
      
 90 
     | 
    
         
            +
                    case SQL_DATE:
         
     | 
| 
      
 91 
     | 
    
         
            +
                    {
         
     | 
| 
      
 92 
     | 
    
         
            +
            			int year = NUM2INT(CALL(obj, "year"));
         
     | 
| 
      
 93 
     | 
    
         
            +
            			int month = NUM2INT(CALL(obj, "month"));
         
     | 
| 
      
 94 
     | 
    
         
            +
            			int day = NUM2INT(CALL(obj, "day"));
         
     | 
| 
      
 95 
     | 
    
         
            +
            			RUN(cbind_query_set_date_par(query, index, year, month, day));
         
     | 
| 
      
 96 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 97 
     | 
    
         
            +
                    }
         
     | 
| 
      
 98 
     | 
    
         
            +
                    case SQL_TIMESTAMP:
         
     | 
| 
      
 99 
     | 
    
         
            +
                    {
         
     | 
| 
      
 100 
     | 
    
         
            +
            			int year = NUM2INT(CALL(obj, "year"));
         
     | 
| 
      
 101 
     | 
    
         
            +
            			int month = NUM2INT(CALL(obj, "month"));
         
     | 
| 
      
 102 
     | 
    
         
            +
            			int day = NUM2INT(CALL(obj, "day"));
         
     | 
| 
      
 103 
     | 
    
         
            +
            			int hour = NUM2INT(CALL(obj, "hour"));
         
     | 
| 
      
 104 
     | 
    
         
            +
            			int minute = NUM2INT(CALL(obj, "min"));
         
     | 
| 
      
 105 
     | 
    
         
            +
            			int second = NUM2INT(CALL(obj, "sec"));
         
     | 
| 
      
 106 
     | 
    
         
            +
            			int fraction = 0;
         
     | 
| 
      
 107 
     | 
    
         
            +
            		  	RUN(cbind_query_set_timestamp_par(query, index, 
         
     | 
| 
      
 108 
     | 
    
         
            +
            					year, month, day, hour, minute, second, fraction));
         
     | 
| 
      
 109 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 110 
     | 
    
         
            +
                    }
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                    default:
         
     | 
| 
      
 113 
     | 
    
         
            +
                        rb_raise(cMarshallError, "unknown sql type %d for parameter N %d", sql_type, index);
         
     | 
| 
      
 114 
     | 
    
         
            +
                }
         
     | 
| 
      
 115 
     | 
    
         
            +
            }
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            VALUE intersys_query_bind_params(VALUE self, VALUE params) {
         
     | 
| 
      
 119 
     | 
    
         
            +
            	int i;
         
     | 
| 
      
 120 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 121 
     | 
    
         
            +
            	Check_Type(params, T_ARRAY);
         
     | 
| 
      
 122 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            	for(i = 0; i < RARRAY(params)->len; i++) {
         
     | 
| 
      
 125 
     | 
    
         
            +
            		query_bind_one_param(query->query, i, RARRAY(params)->ptr[i]);
         
     | 
| 
      
 126 
     | 
    
         
            +
            	}
         
     | 
| 
       36 
127 
     | 
    
         
             
            	return self;
         
     | 
| 
       37 
128 
     | 
    
         
             
            }
         
     | 
| 
       38 
129 
     | 
    
         | 
| 
         @@ -47,6 +138,7 @@ VALUE intersys_query_execute(VALUE self) { 
     | 
|
| 
       47 
138 
     | 
    
         
             
            	return self;
         
     | 
| 
       48 
139 
     | 
    
         
             
            }
         
     | 
| 
       49 
140 
     | 
    
         | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
       50 
142 
     | 
    
         
             
            VALUE intersys_query_get_data(VALUE self, VALUE index) {
         
     | 
| 
       51 
143 
     | 
    
         
             
            	struct rbQuery* query;
         
     | 
| 
       52 
144 
     | 
    
         
             
            	int type = 0;
         
     | 
| 
         @@ -129,7 +221,7 @@ VALUE intersys_query_column_name(VALUE self, VALUE i) { 
     | 
|
| 
       129 
221 
     | 
    
         | 
| 
       130 
222 
     | 
    
         
             
            VALUE intersys_query_fetch(VALUE self) {
         
     | 
| 
       131 
223 
     | 
    
         
             
            	struct rbQuery* query;
         
     | 
| 
       132 
     | 
    
         
            -
            	VALUE data;
         
     | 
| 
      
 224 
     | 
    
         
            +
            	VALUE data = Qnil;
         
     | 
| 
       133 
225 
     | 
    
         
             
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
       134 
226 
     | 
    
         
             
            	int num_cols = 0;
         
     | 
| 
       135 
227 
     | 
    
         
             
            	int i = 0;
         
     | 
| 
         @@ -153,13 +245,61 @@ VALUE intersys_query_fetch(VALUE self) { 
     | 
|
| 
       153 
245 
     | 
    
         
             
            	for(i = 0; i < num_cols; i++) {
         
     | 
| 
       154 
246 
     | 
    
         
             
            		rb_ary_push(data, rb_funcall(self, rb_intern("get_data"), 1, INT2FIX(i+1)));
         
     | 
| 
       155 
247 
     | 
    
         
             
            	}
         
     | 
| 
       156 
     | 
    
         
            -
            	rb_funcall(self, rb_intern("close"), 0);
         
     | 
| 
       157 
248 
     | 
    
         
             
            	return data;
         
     | 
| 
       158 
249 
     | 
    
         
             
            }
         
     | 
| 
       159 
250 
     | 
    
         | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
            VALUE intersys_query_each(VALUE self) {
         
     | 
| 
      
 253 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 254 
     | 
    
         
            +
            	int i;
         
     | 
| 
      
 255 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 256 
     | 
    
         
            +
            	if(query->offset > 0) {
         
     | 
| 
      
 257 
     | 
    
         
            +
            		RUN(cbind_query_skip(query->query, query->offset));
         
     | 
| 
      
 258 
     | 
    
         
            +
            	}
         
     | 
| 
      
 259 
     | 
    
         
            +
            	for(i = query->offset; i < query->offset + query->limit; i++) {
         
     | 
| 
      
 260 
     | 
    
         
            +
            		VALUE row = intersys_query_fetch(self);
         
     | 
| 
      
 261 
     | 
    
         
            +
            		if(row == Qnil || RARRAY(row)->len == 0) {
         
     | 
| 
      
 262 
     | 
    
         
            +
            			break;
         
     | 
| 
      
 263 
     | 
    
         
            +
            		}
         
     | 
| 
      
 264 
     | 
    
         
            +
            		rb_yield(row);
         
     | 
| 
      
 265 
     | 
    
         
            +
            	}
         
     | 
| 
      
 266 
     | 
    
         
            +
            	query_close(query);
         
     | 
| 
      
 267 
     | 
    
         
            +
            	return self;
         
     | 
| 
      
 268 
     | 
    
         
            +
            }
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
       160 
272 
     | 
    
         
             
            VALUE intersys_query_close(VALUE self) {
         
     | 
| 
       161 
273 
     | 
    
         
             
            	struct rbQuery* query;
         
     | 
| 
       162 
274 
     | 
    
         
             
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
       163 
275 
     | 
    
         
             
            	query_close(query);
         
     | 
| 
       164 
276 
     | 
    
         
             
            	return self;
         
     | 
| 
       165 
277 
     | 
    
         
             
            }
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
            VALUE intersys_query_set_limit(VALUE self, VALUE limit) {
         
     | 
| 
      
 281 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 282 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 283 
     | 
    
         
            +
            	query->limit = NUM2INT(rb_funcall(limit, rb_intern("to_i"), 0));
         
     | 
| 
      
 284 
     | 
    
         
            +
            	return limit;
         
     | 
| 
      
 285 
     | 
    
         
            +
            }
         
     | 
| 
      
 286 
     | 
    
         
            +
            VALUE intersys_query_get_limit(VALUE self) {
         
     | 
| 
      
 287 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 288 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 289 
     | 
    
         
            +
            	return INT2FIX(query->limit);
         
     | 
| 
      
 290 
     | 
    
         
            +
            }
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
            VALUE intersys_query_set_offset(VALUE self, VALUE offset) {
         
     | 
| 
      
 293 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 294 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 295 
     | 
    
         
            +
            	query->offset = NUM2INT(rb_funcall(offset, rb_intern("to_i"), 0));
         
     | 
| 
      
 296 
     | 
    
         
            +
            	return offset;
         
     | 
| 
      
 297 
     | 
    
         
            +
            }
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
            VALUE intersys_query_get_offset(VALUE self) {
         
     | 
| 
      
 300 
     | 
    
         
            +
            	struct rbQuery* query;
         
     | 
| 
      
 301 
     | 
    
         
            +
            	Data_Get_Struct(self, struct rbQuery, query);
         
     | 
| 
      
 302 
     | 
    
         
            +
            	return INT2FIX(query->offset);
         
     | 
| 
      
 303 
     | 
    
         
            +
            }
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
            #endif /* HAVE_SQL_H */
         
     |