datamapperでfind(:select => '')みたいなことはできない
dm-core (0.9.11)の話
ARだと、
User.find( :all, :select => 'DISTINCT mail_addr' )
のように、select文を直接書くことができるけど、これはdatamapperではできないらしい。
SQL文を生成しているのはdata_objects_adapter.rbに書かれているread_statementで,fields_statementがSELECTの中身を生成している。
def read_statement(query) statement = "SELECT #{fields_statement(query)}" statement << " FROM #{quote_table_name(query.model.storage_name(query.repository.name))}" statement << links_statement(query) if query.links.any? statement << " WHERE #{conditions_statement(query)}" if query.conditions.any? statement << " GROUP BY #{group_by_statement(query)}" if query.unique? && query.fields.any? { |p| p.kind_of?(Property) } statement << " ORDER BY #{order_statement(query)}" if query.order.any? statement << " LIMIT #{quote_column_value(query.limit)}" if query.limit statement << " OFFSET #{quote_column_value(query.offset)}" if query.offset && query.offset > 0 statement rescue => e DataMapper.logger.error("QUERY INVALID: #{query.inspect} (#{e})") raise e end
こんなふうに。
def fields_statement(query) qualify = query.links.any? query.fields.map { |p| property_to_column_name(query.repository, p, qualify) } * ', ' end
def property_to_column_name(repository, property, qualify) table_name = property.model.storage_name(repository.name) if property && property.respond_to?(:model) if table_name && qualify # <- qualifyはlinksが存在するかどうか "#{quote_table_name(table_name)}.#{quote_column_name(property.field(repository.name))}" else quote_column_name(property.field(repository.name)) end end
property_to_column_nameはrepositoryとpropertyとを受け取ってそれをカラム名にする。カラム名としてはpropertyのfieldが使われる。そして、property.fieldはクオートされる。
だから無理矢理property :foo , :field => 'var + baz as foo'としても、クオートされるのでSQLが通らない。
なので、 SELECT var + baz as foo from ...というSQL文は書けない。