Problems with "do shell script" and sqlite

set thePath to "/Users/me/Library/Application Support/Snippit/snippitDB.db"
set theQuery to ".separator '&|&'"
set theResult to do shell script ("sqlite3 " & quoted form of thePath & space & quoted form of theQuery)
return theResult

It doesn’t produce an error, but when I check it, the mode hasn’t changed.

I’ve tried running this directly from the shell too, and it fails.

The only way it seems to work is if I enter the sqlite3 program in terminal and type it from there (.separator “&|&”), just seems to have problems with being run from outside the sqlite3 program…

Does anyone know of a workaround for this, without having to manually enter the sqlite3 program via the terminal?

On a sidenote, this is my first post on these forums, though I’ve been an avid reader of the tutorials, so hi!

Regards,
Alison.

Update:
Some of the other things I’ve tried, with no success.

.read file.txt
(where file contains “.separator &|&”) – again, works in sqlite3 program but not in shell script, no errors returned
<<EOF .separator &|& EOF – again, works in sqlite3 program but not in shell script, no errors returned

It’s probably something blindingly obvious, but I’m not seeing it.

See if this helps.

set thePath to "~/Library/Application\\ Support/Snippit/snippitDB.db"
set theQuery to ".separator '&|&'"
set theResult to do shell script ("sqlite3 " & quoted form of thePath & space & quoted form of theQuery)
return theResult

Tom

Browser: Safari 525.13
Operating System: Mac OS X (10.4)

Afraid not :frowning:

Ahhh! I’ve got it! (And this is really poorly documented)

It needs to go in this format:

set theQuery to "sqlite3 -separator &|& " & pathToDatabase

Thanks for trying to help! Much appreciated :slight_smile:

You mostly worked it out before the time I finished writing this out. Be sure to use quoted form of for all your variable command line arguments (like if you plan on using different separators; even that one with ampersands should still need it since ampersands are special to the shell).

I assume you want to do a query after setting the separator. You might want to try one of these methods:

set thePath to "/Users/me/Library/Application Support/Snippit/snippitDB.db"
set theQuery to ".separator '&|&'"

set thePath to "/tmp/foo.db"
set theSeparator to "&|&"
set theQuery to "select * from bar;"

-- Use -separator to set the separator.
set a to do shell script ("sqlite3 -separator " & quoted form of theSeparator & space & quoted form of thePath & space & quoted form of theQuery)

-- Use echo and create a multiple lines of input for the sqlite3 program.
set b to do shell script "(echo .separator " & quoted form of my quoteForDotSeparator(theSeparator) & ";echo " & quoted form of theQuery & ")|sqlite3 " & quoted form of thePath

set theCmdFilePOSIXPath to "/tmp/foo.sql"
set myLF to ASCII character 10 -- can use linefeed in OS 10.5

-- Put .separator in init file. Do query on command line.
".separator " & my quoteForDotSeparator(theSeparator) & myLF
my createFile(theCmdFilePOSIXPath, result)
set c to do shell script "sqlite3 -init " & quoted form of theCmdFilePOSIXPath & space & quoted form of thePath & space & quoted form of theQuery

-- Put .separator and query in init file.
".separator " & my quoteForDotSeparator(theSeparator) & myLF & theQuery & myLF
my createFile(theCmdFilePOSIXPath, result)
set d to do shell script "sqlite3 -init " & quoted form of theCmdFilePOSIXPath & space & quoted form of thePath

{a = b, a = c, a = d, a, b, c, d} -- test that results are identical

to replace(s, orig, new)
	-- Adapted From: http://bbs.applescript.net/viewtopic.php?pid=41257#p41257
	-- By: kai, Nigel Garvey
	
	set {otid, text item delimiters} to {text item delimiters, {orig}}
	set s to text items of s
	set text item delimiters to {new}
	tell s to set s to beginning & ({""} & rest)
	set text item delimiters to otid
	s
end replace

to quoteForDotSeparator(s)
	-- "quoted form of" is not sufficient for this purpose
	my replace(s, "\"", "\\\"")
	my replace(result, "'", "\\'")
end quoteForDotSeparator

to createFile(pp, s)
	set f to POSIX file pp
	set r to open for access f with write permission
	set eof of r to 0
	write s to r starting at 0 as «class utf8» -- At least it is not UTF-16.
	close access f
end createFile

As far as I know, the separator is only set per SQLite process, not per database. As soon as the sqlite3 process exits (do shell script won’t have much to return until the sqlite3 process exits), the setting is “lost”. The .separator command is not an SQL command/query, but an SQLite-specific meta-command (that is why it starts with a dot).

It seems that one can only issue one “command” via the sqlite3 command-line. Since the SQLite meta-commands cannot be strung together with other commands via semicolons it prevents one from appending an actual query in addition to setting the separator. Above I show four different ways of setting the separator and running a query (-separator and command-line SQL, .separator and query on stdin (via echo), .separator in init file and query on command line, .separator and query in init file). There are other permutations available, too (.separator in init file and query on command line), but those should give you an idea.

I think I prefer the first for simplicity.

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 3.0.4 (523.12)
Operating System: Mac OS X (10.4)

Wow, thanks for that reply :slight_smile: Duly bookmarked.
I’ve been sort of going along the lines of your first example.
What I’m actually trying to do is make a mini app using Applescript studio to perform sqlite queries. It’s been going really well so far till I got stuck on making that one mode-changing panel. I had the text field set to perform the separator change on end editing, so it obviously just changed it, then changed it right back again… hence the lack of error messages.
Sigh…
So it’s been working all along, but I was laboring under the belief that the separator mode was sticky! Doh!

This is what I’ve got now (minus the on end editing!) and it works… finally.

on doQuery(query, unixPath)
	set theSeparator to (contents of text field "sepfield" of box "box" of view "advancedview" of tab view "outertabview" of window "main")
	try
		if theSeparator is "" then
			set contents of text field "sepfield" of box "box" of view "advancedview" of tab view "outertabview" of window "main" to "|"
			set theSeparator to "|"
		end if
		set theQuery to ("sqlite3 -separator " & quoted form of theSeparator & space & quoted form of unixPath & space & "<<EOF " & (ASCII character 10) & query & (ASCII character 10) & "EOF")
		set theResult to (do shell script theQuery)
		return theResult
	on error errStr number errorNumber
		return errStr
	end try
end doQuery

That looks pretty good. If you want to use the “here-doc” (<<EOF) to pass it the main SQL statements, you should probably use something like <<‘EOF’ (put quote (single or double, it does not matter) around the EOF word). That will prevent the shell from doing various expansions and substitutions. This is akin to using quoted form of for command-line parameters. It is especially important if any part of the here-doc data (the query in your case) comes from outside the script (user input, reading a file, etc.).

set myLF to ASCII character 10 -- Mac OS X 10.5 can use the linefeed property instead of myLF

set cmd to "cat"
set hereDocFooter to "EOF"
set unquotedHereDoc to "<<EOF"
set quotedHereDoc to "<<'EOF'"
set hereDocData to "UID: $UID" & myLF & "Hostname: $(hostname)" & myLF & "pwd: `pwd`" & myLF & "1+2: $((1+2))" & myLF -- The hostname and pwd commands will be run unless the here-doc word is quoted. Imagine if someone arranged it so that the included text cause the execution of something dangerous or descructive.

-- without altering line endings prevents do shell script from changing the linefeeds (normal UNIX EOL) in the output to carraige returns (classic Mac EOL) in the result value. This is important if we want the orig=quoted result to be true. Otherwise it might be insignificant for a given task.
set unquotedResult to do shell script cmd & unquotedHereDoc & myLF & hereDocData & hereDocFooter without altering line endings
set quotedResult to do shell script cmd & quotedHereDoc & myLF & hereDocData & hereDocFooter without altering line endings

{orig:hereDocData, |orig=unquoted|:hereDocData = unquotedResult, unquoted:unquotedResult, |orig=quoted|:hereDocData = quotedResult, quoted:quotedResult}
(* --> My result:
{orig:"UID: $UID
Hostname: $(hostname)
pwd: `pwd`
1+2: $((1+2))
", |orig=unquoted|:false, unquoted:"UID: 501
Hostname: Blinky.local
pwd: /
1+2: 3
", |orig=quoted|:true, quoted:"UID: $UID
Hostname: $(hostname)
pwd: `pwd`
1+2: $((1+2))
"}
*)

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 3.0.4 (523.12)
Operating System: Mac OS X (10.4)

From “sqlite3: A command-line access program for SQLite databases”: