File: trilogy.rb

package info (click to toggle)
ruby-sequel 5.97.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,188 kB
  • sloc: ruby: 123,115; makefile: 3
file content (116 lines) | stat: -rw-r--r-- 2,979 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# frozen-string-literal: true

require 'trilogy'
require_relative 'shared/mysql'

module Sequel
  module Trilogy
    class Database < Sequel::Database
      include Sequel::MySQL::DatabaseMethods

      QUERY_FLAGS = ::Trilogy::QUERY_FLAGS_CAST | ::Trilogy::QUERY_FLAGS_CAST_BOOLEANS
      LOCAL_TIME_QUERY_FLAGS = QUERY_FLAGS | ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE

      set_adapter_scheme :trilogy
      
      # Connect to the database.  See Trilogy documentation for options.
      def connect(server)
        opts = server_opts(server)
        opts[:username] ||= opts.delete(:user)
        opts[:found_rows] = true
        conn = ::Trilogy.new(opts)
        mysql_connection_setting_sqls.each{|sql| log_connection_yield(sql, conn){conn.query(sql)}}
        conn
      end

      def disconnect_connection(c)
        c.discard!
      rescue ::Trilogy::Error
        nil
      end

      # Execute the given SQL on the given connection and yield the result.
      def execute(sql, opts)
        r = synchronize(opts[:server]) do |conn|
          log_connection_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql, conn) do
            conn.query_with_flags(sql, timezone.nil? || timezone == :local ? LOCAL_TIME_QUERY_FLAGS : QUERY_FLAGS)
          end
        end
        yield r
      rescue ::Trilogy::Error => e
        raise_error(e)
      end

      def execute_dui(sql, opts=OPTS)
        execute(sql, opts, &:affected_rows)
      end

      def execute_insert(sql, opts=OPTS)
        execute(sql, opts, &:last_insert_id)
      end

      def freeze
        server_version
        super
      end

      # Return the version of the MySQL server to which we are connecting.
      def server_version(_server=nil)
        @server_version ||= super()
      end

      private

      def database_specific_error_class(exception, opts)
        if exception.error_code == 1205
          DatabaseLockTimeout
        else
          super
        end
      end

      def connection_execute_method
        :query
      end

      def database_error_classes
        [::Trilogy::Error]
      end

      def dataset_class_default
        Dataset
      end

      # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
      def schema_column_type(db_type)
        db_type.start_with?("tinyint(1)") ? :boolean : super
      end
    end

    class Dataset < Sequel::Dataset
      include Sequel::MySQL::DatasetMethods

      def fetch_rows(sql)
        execute(sql) do |r|
          self.columns = r.fields.map!{|c| output_identifier(c.to_s)}
          r.each_hash{|h| yield h}
        end
        self
      end
      
      private

      def execute(sql, opts=OPTS)
        opts = Hash[opts]
        opts[:type] = :select
        super
      end

      # Handle correct quoting of strings using ::Trilogy#escape.
      def literal_string_append(sql, v)
        sql << "'" << db.synchronize(@opts[:server]){|c| c.escape(v)} << "'"
      end
    end
  end
end