1

I have a handful of SQL queries in my objective-c project. Is there any way I can store these in separate files query1.sql, query2.sql, in my tree and sub them in at compile time?

Motivating this is the fact that my queries are either copy-pastable but unreadable (no whitespace):

NSString* query = @"SELECT A.a, B.* from myTable A INNER JOIN otherTable B ON ...

Or readable but littered with line splices:

NSString* query = @"SELECT A.a, B.* \
FROM myTable A 
INNER JOIN \
...

I am aware of .strings files for objective c, but thought they were more for localization. Is that right?

EDIT: I could have been more clear: I want to store my individual sql statements in separate text files that 1.) are valid SQL independently, and 2.) can be imported at compile time.

Paul Orland
  • 542
  • 4
  • 16
  • You might prefer using a macro for a multiline string as in this answer: http://stackoverflow.com/a/17996915/3737 – Jesse Rusak Mar 14 '14 at 02:08

3 Answers3

0

you can try this

NSString* query = 
@"SELECT A.a, B.* "
"FROM myTable A "
"INNER JOIN "
"..."

or move the sql string to file query1.sql

"SELECT A.a, B.* "
"FROM myTable A "
"INNER JOIN "
"..."

and

NSString *query= @(
#include "query1.sql"
);
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
  • Any variant of this solution where query1.sql is valid SQL? – Paul Orland Mar 14 '14 at 01:55
  • @orlandpm you can use some script translate valid sql to c string by appending quotes on each line and include the translated file. you need an extra build step to auto generate `#incldue`able sql file – Bryan Chen Mar 14 '14 at 01:56
0

I'm going to say "no", but we'll see if anyone disagrees!

If you are prepared to forgo the compile time inclusion just have the sql files copied into your bundle and read them in. This is of course a runtime cost on each run, but that probably isn't significant, but YMMV!

Another, more involve approach - but you only need to write it once - is to develop a script, say in Ruby, which transforms your SQL files into Objective-C source and include it as build phase. Apple has an example somewhere of doing this (using Ruby, hence the suggestion of Ruby - start with Apple's sample and edit it) to run the preprocessor over strings files. The approach does work very well, but you need to put the effort in first and then can reuse it in all your projects.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
0

The other recommendations for macros or multi-line strings are good, but if you want to put them in .strings files, that's fine. Just use NSLocalizedStringFromTable so that you can specify a different strings table than your localized strings. And of course, don't localize the SQL.

But I'd probably build something custom that read the file and cached its contents. Building exactly what you want would probably take about fifteen minutes, and there's no harm in it if it makes development simpler.

If you want to store all your select queries in their own files (like you say), just use NSBundle to load find your resource file by some token. Something like:

NSString * SQL(NSString *key) {
  NSString *path = [[NSBundle mainBundle] pathForResource:key ofType:@"sql"];
  return [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
}

NSString * const SELECT_EM = @"SELECT_EM";

NSString *select_query = SQL(SELECT_EM);

Then you'd have a file called SELECT_EM.sql in your resources directory.

Again, lots of choices; they're all fine. If you're calling SQL a lot, you should probably add an NSDictionary cache for them so you don't have to load the string every time.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610