简体   繁体   中英

MySQL function using Rails/ActiveRecord

I have a problem in using Rails / ActiveRecord.

I want to insert record with MySQL function, for example GeomFromText('POINT(1 1)') . Using ActiveRecord normally, these functions are quoted automatically. I want not to quote these values.

Model.create(geo: GeomFromText('POINT(1 1)'))

this ActiveRecord statement will generate following SQL

INSERT INTO `Model` (`geo`) VALUES ('GeomFromText(\'POINT(1 1)\')')

It may be easy to use raw SQL, but I want to use ActiveRecord because my Model set several callbacks include self table.

How can use MySQL function with ActiveRecord statement?

Summary

You can't by design; this behavior is important for preventing SQL injection attacks. You would need to explicitly execute raw SQL in conjunction with ActiveRecord.

Details

As you saw, the SQL statement gets interpolated as a string by design, which doesn't do what you want (Rails ~> 4.0):

> Country.create(name: 'LOWER("CANADA")')
  => SQL (0.3ms)  INSERT INTO `Country` (`Name`) VALUES ('LOWER(\"CANADA\")')

Nor can you use the same tricks that would work for the .where method:

> Country.create(["name = LOWER(:country)", { country: 'CANADA' }])
  => ArgumentError: When assigning attributes, you must pass a hash as an argument.

You would need to execute arbitrary SQL first to get the proper value, then make another SQL call via ActiveRecord to achieve your callback:

> Country.create( name: ActiveRecord::Base.connection.execute(%q{ SELECT LOWER('CANADA') }).first[0] )
  =>     (0.3ms)  SELECT LOWER('CANADA')
  => SQL (0.3ms)  INSERT INTO `Country` (`Name`) VALUES ('canada')

That said, it's probably cleaner to re-implement the SQL function at the application layer instead of the DB layer (unless you've got a really complex SQL function).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM