371

I have a pretty long sqlite query:

const char *sql_query = "SELECT statuses.word_id FROM lang1_words, statuses WHERE statuses.word_id = lang1_words.word_id ORDER BY lang1_words.word ASC";

How can I break it in a number of lines to make it easier to read? If I do the following:

const char *sql_query = "SELECT word_id
                        FROM table1, table2
                        WHERE table2.word_id = table1.word_id
                        ORDER BY table1.word ASC";

I am getting an error.

Is there a way to write queries in multiple lines?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Ilya Suzdalnitski
  • 52,598
  • 51
  • 134
  • 168

9 Answers9

644

There are two ways to split strings over multiple lines:

  1. Each string on its own line. Works only with strings:

    • Plain C:

      char *my_string = "Line 1 "
                        "Line 2";
      
    • Objective-C:

      NSString *my_string = @"Line1 "
                             "Line2";    // the second @ is optional
      
  2. Using \ - can be used for any expression:

    • Plain C:

      char *my_string = "Line 1 \
                         Line 2";
      
    • Objective-C:

      NSString *my_string = @"Line1 \
                              Line2";
      

The first approach is better, because there isn't a lot of whitespace included. For a SQL query however, both are possible.

NOTE: With a #define, you have to add an extra \ to concatenate the two strings:

Plain C:

#define kMyString "Line 1"\
                  "Line 2"
Neuron
  • 5,141
  • 5
  • 38
  • 59
Georg Schölly
  • 124,188
  • 49
  • 220
  • 267
  • 27
    Both of these are the same as in and C and C++. The latter solution is preferred because former one embeds a _lot_ of useless white space into the program which will also be transmitted to the DB server. – Alnitak Apr 28 '09 at 11:34
  • You're missing an @ at the start of line 2 in the better Objective-C example. – Redwood Jun 15 '10 at 23:27
  • Do you have a link to a spec documenting the optionality of the second `@`? – Heath Borders Jun 05 '12 at 18:10
  • @HeathBorders: Not right here, but I've looked it up when I wrote the answer. – Georg Schölly Jun 05 '12 at 18:15
  • 12
    Another advantage of the better approach is, that you can put // comments after each line. – fishinear Dec 02 '13 at 13:37
  • 2
    Does the second approach insert either `\n` or `\r\n` between the lines? – Charles W Aug 14 '17 at 23:09
  • @Charles: No, the strings are simply concatenated. – Georg Schölly Aug 15 '17 at 06:41
  • @PeterCordes: It's not a bug to use " " instead of "\n" at the end of a string. The language not only supports it, it is useful in many cases. For example long strings of text that are dynamically wrapped based on available display space, large constants (huge numbers in hex), etc. – Brad Jul 23 '21 at 03:36
  • @Brad: Probably when I commented, I had been looking for a Q&A about writing a multi-line string literal that *did* need to include newlines (probably for a GNU inline asm template string). But that's not what the question actually asked for; space and newline were interchangeable for its purposes. So you're right, it's not buggy if that's not what you need, it just defines a different string than the 2nd code block from the question. Deleted my previous comment. If you want embedded newlines use `\n` with this, or see Ciro's answer using `R"(foo bar)"` for literal newlines. – Peter Cordes Jul 23 '21 at 03:57
131

There's a trick you can do with the pre-processor.
It has the potential down sides that it will collapse white-space, and could be confusing for people reading the code.
But, it has the up side that you don't need to escape quote characters inside it.

#define QUOTE(...) #__VA_ARGS__
const char *sql_query = QUOTE(
    SELECT word_id
    FROM table1, table2
    WHERE table2.word_id = table1.word_id
    ORDER BY table1.word ASC
);

the preprocessor turns this into:

const char *sql_query = "SELECT word_id FROM table1, table2 WHERE table2.word_id = table1.word_id ORDER BY table1.word ASC";

I've used this trick when I was writing some unit tests that had large literal strings containing JSON. It meant that I didn't have to escape every quote character \".

Nicholas Daley-Okoye
  • 2,267
  • 1
  • 18
  • 12
  • 8
    Perfect! Now I just need to give this a few more hundred upvotes, and get it where it belongs... – Mike Oct 22 '14 at 12:29
  • I was reacting the same way, but this is not without issues. I just tried doing a heredoc this way with a special Unicode character and got an error about non-ASCII characters not being allowed outside of literals. – philipkd Jan 04 '17 at 13:42
  • +1 but for the record I´m having trouble with the compiler (MSVC) or editor (QtCreator) not (re)compiling the expression as it should on change. It is like change is not detected... Hitting Rebuild instead of Build does the trick. – Andreas Oct 11 '17 at 18:57
  • Thank you for this Chicken Nugget of information. It does exactly what I needed to do without all the extra garbage. – FishGuy876 Aug 23 '19 at 13:55
  • This unfortunately doesn't work if you have literal quotation marks in the string. Well, it kind of works, in that it generates a warning. But my codebase is -Werror... – AnilRedshift May 30 '20 at 03:11
25

I am having this problem all the time, so I made a tiny tool to convert text to an escaped multi-line Objective-C string:

http://multilineobjc.herokuapp.com/

Hope this saves you some time.

Flaviu
  • 6,240
  • 4
  • 35
  • 33
25

You could also go into XCode -> Preferences, select the Indentation tab, and turn on Line Wrapping.

That way, you won't have to type anything extra, and it will work for the stuff you already wrote. :-)

One annoying thing though is...

if (you're long on indentation
    && short on windows) {
            then your code will
                end up squished
                     against th
                         e side
                             li
                              k
                              e

                              t
                              h
                              i
                              s
}
DenverCoder9
  • 3,635
  • 3
  • 31
  • 57
  • 2
    @YoYoYonnY I agree, but I also appreciate it. It strikes me that this comment would not have been truly possible as a comment, hence the use of the answer format. This seems like a limitation of S/O, that you can't write particularly rich comments (as far as I am aware). – Max von Hippel Sep 27 '16 at 11:01
20

Extending the Quote idea for Objective-C:

#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

NSString *sql = NSStringMultiline(
    SELECT name, age
    FROM users
    WHERE loggedin = true
);
Community
  • 1
  • 1
Berik
  • 7,816
  • 2
  • 32
  • 40
8

One more solution for the pile, change your .m file to .mm so that it becomes Objective-C++ and use C++ raw literals, like this:

const char *sql_query = R"(SELECT word_id
                           FROM table1, table2
                           WHERE table2.word_id = table1.word_id
                           ORDER BY table1.word ASC)";

Raw literals ignore everything until the termination sequence, which in the default case is parenthesis-quote.

If the parenthesis-quote sequence has to appear in the string somewhere, you can easily specify a custom delimiter too, like this:

const char *sql_query = R"T3RM!N8(
                                  SELECT word_id
                                  FROM table1, table2
                                  WHERE table2.word_id = table1.word_id
                                  ORDER BY table1.word ASC
                         )T3RM!N8";
John Stephen
  • 7,625
  • 2
  • 31
  • 45
  • I've also found that GCC adds C++ raw string literals as an extension to the C language: https://stackoverflow.com/questions/797318/how-to-split-a-string-literal-across-multiple-lines-in-c-objective-c/54576129#54576129 – Ciro Santilli OurBigBook.com Feb 07 '19 at 14:57
5

GCC adds C++ multiline raw string literals as a C extension

C++11 has raw string literals as mentioned at: https://stackoverflow.com/a/44337236/895245

However, GCC also adds them as a C extension, you just have to use -std=gnu99 instead of -std=c99. E.g.:

main.c

#include <assert.h>
#include <string.h>

int main(void) {
    assert(strcmp(R"(
a
b
)", "\na\nb\n") == 0);
}

Compile and run:

gcc -o main -pedantic -std=gnu99 -Wall -Wextra main.c
./main

This can be used for example to insert multiline inline assembly into C code: How to write multiline inline assembly code in GCC C++?

Now you just have to lay back, and wait for it to be standardized on C20XY.

C++ was asked at: C++ multiline string literal

Tested on Ubuntu 16.04, GCC 6.4.0, binutils 2.26.1.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
4

You can also do:

NSString * query = @"SELECT * FROM foo "
                   @"WHERE "
                     @"bar = 42 "
                     @"AND baz = datetime() "
                   @"ORDER BY fizbit ASC";
Georg Schölly
  • 124,188
  • 49
  • 220
  • 267
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
0

An alternative is to use any tool for removing line breaks. Write your string using any text editor, once you finished, paste your text here and copy it again in xcode.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
  • 2
    No really a long term solution. What if you have to change it again later. Get's annoying fast, better to use the multi line techniqies already mentioned and format it directly in the file. – Schwarzie2478 Feb 06 '20 at 16:43