Class: BetterAuth::Adapters::SQL

Inherits:
Base
  • Object
show all
Defined in:
lib/better_auth/adapters/sql.rb

Direct Known Subclasses

MSSQL, MySQL, Postgres, SQLite

Instance Attribute Summary collapse

Attributes inherited from Base

#options

Instance Method Summary collapse

Constructor Details

#initialize(options, connection:, dialect:) ⇒ SQL

Returns a new instance of SQL.



11
12
13
14
15
# File 'lib/better_auth/adapters/sql.rb', line 11

def initialize(options, connection:, dialect:)
  super(options)
  @connection = connection
  @dialect = dialect.to_sym
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



9
10
11
# File 'lib/better_auth/adapters/sql.rb', line 9

def connection
  @connection
end

#dialectObject (readonly)

Returns the value of attribute dialect.



9
10
11
# File 'lib/better_auth/adapters/sql.rb', line 9

def dialect
  @dialect
end

Instance Method Details

#count(model:, where: nil) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/better_auth/adapters/sql.rb', line 110

def count(model:, where: nil)
  model = model.to_s
  params = []
  where_sql = build_where(model, where || [], params)
  sql = +"SELECT COUNT(*) AS count FROM "
  sql << quote(table_for(model))
  sql << " WHERE #{where_sql}" unless where_sql.empty?
  row = execute(sql, params).first || {}
  (row["count"] || row[:count] || 0).to_i
end

#create(model:, data:, force_allow_id: false) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/better_auth/adapters/sql.rb', line 17

def create(model:, data:, force_allow_id: false)
  model = model.to_s
  input = transform_input(model, data, "create", force_allow_id)
  table = table_for(model)
  columns = input.keys.map { |field| storage_field(model, field) }
  params = input.keys.map { |field| input[field] }
  placeholders = params.each_index.map { |index| placeholder(index + 1) }
  returning = (dialect == :postgres) ? " RETURNING *" : ""
  sql = "INSERT INTO #{quote(table)} (#{columns.map { |column| quote(column) }.join(", ")}) VALUES (#{placeholders.join(", ")})#{returning}"
  rows = execute(sql, params)
  row = rows.first
  return normalize_record(model, row) if row

  find_one(model: model, where: [{field: "id", value: input.fetch("id")}])
end

#delete(model:, where:) ⇒ Object



94
95
96
97
# File 'lib/better_auth/adapters/sql.rb', line 94

def delete(model:, where:)
  delete_many(model: model, where: where)
  nil
end

#delete_many(model:, where:) ⇒ Object



99
100
101
102
103
104
105
106
107
108
# File 'lib/better_auth/adapters/sql.rb', line 99

def delete_many(model:, where:)
  model = model.to_s
  params = []
  where_sql = build_where(model, where || [], params)
  sql = +"DELETE FROM "
  sql << quote(table_for(model))
  sql << " WHERE #{where_sql}" unless where_sql.empty?
  result = execute(sql, params)
  affected_rows(result)
end

#find_many(model:, where: [], sort_by: nil, limit: nil, offset: nil, select: nil, join: nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/better_auth/adapters/sql.rb', line 41

def find_many(model:, where: [], sort_by: nil, limit: nil, offset: nil, select: nil, join: nil)
  model = model.to_s
  params = []
  sql = +"SELECT "
  sql << "TOP (#{Integer(limit)}) " if dialect == :mssql && limit && !offset
  sql << select_sql(model, select, join)
  sql << " FROM "
  sql << quote(table_for(model))
  sql << join_sql(model, join)
  where_sql = build_where(model, where || [], params)
  sql << " WHERE #{where_sql}" unless where_sql.empty?
  sql << order_sql(model, sort_by) if sort_by
  append_pagination_sql(sql, model, sort_by, limit, offset)

  records = execute(sql, params).map { |row| normalize_record(model, row, join: join) }
  collection_join?(model, join) ? aggregate_collection_joins(model, records, join) : records
end

#find_one(model:, where: [], select: nil, join: nil) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/better_auth/adapters/sql.rb', line 33

def find_one(model:, where: [], select: nil, join: nil)
  if collection_join?(model.to_s, join)
    find_many(model: model, where: where, select: select, join: join).first
  else
    find_many(model: model, where: where, select: select, join: join, limit: 1).first
  end
end

#transactionObject



121
122
123
124
125
126
127
128
129
# File 'lib/better_auth/adapters/sql.rb', line 121

def transaction
  execute("BEGIN", [])
  result = yield self
  execute("COMMIT", [])
  result
rescue
  execute("ROLLBACK", [])
  raise
end

#update(model:, where:, update:) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/better_auth/adapters/sql.rb', line 59

def update(model:, where:, update:)
  model = model.to_s
  if dialect == :postgres
    records = update_many(model: model, where: where, update: update, returning: true)
    return records.is_a?(Array) ? records.first : records
  end

  existing = find_one(model: model, where: where, select: ["id"])
  return nil unless existing

  update_many(model: model, where: where, update: update)
  find_one(model: model, where: [{field: "id", value: existing.fetch("id")}])
end

#update_many(model:, where:, update:, returning: false) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/better_auth/adapters/sql.rb', line 73

def update_many(model:, where:, update:, returning: false)
  model = model.to_s
  data = transform_input(model, update, "update", true)
  params = []
  assignments = data.each_key.map do |field|
    params << data[field]
    "#{quote(storage_field(model, field))} = #{placeholder(params.length)}"
  end
  where_sql = build_where(model, where || [], params)
  sql = +"UPDATE "
  sql << quote(table_for(model))
  sql << " SET "
  sql << assignments.join(", ")
  sql << " WHERE #{where_sql}" unless where_sql.empty?
  sql << " RETURNING *" if dialect == :postgres
  rows = execute(sql, params).map { |row| normalize_record(model, row) }
  return rows if returning || dialect == :postgres

  nil
end