Android/App개발2010. 4. 13. 10:44

Command Line Shell For SQLite

The SQLite library includes a simple command-line utility named sqlite3 (or sqlite3.exe on windows) that allows the user to manually enter and execute SQL commands against an SQLite database. This document provides a brief introduction on how to use the sqlite3 program.

Getting Started

To start the sqlite3 program, just type "sqlite3" followed by the name the file that holds the SQLite database. If the file does not exist, a new one is created automatically. The sqlite3 program will then prompt you to enter SQL. Type in SQL statements (terminated by a semicolon), press "Enter" and the SQL will be executed.

For example, to create a new SQLite database named "ex1" with a single table named "tbl1", you might do this:

$ sqlite3 ex1
SQLite version 3.6.11
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table tbl1(one varchar(10), two smallint);
sqlite> insert into tbl1 values('hello!',10);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>

You can terminate the sqlite3 program by typing your systems End-Of-File character (usually a Control-D). Use the interrupt character (usually a Control-C) to stop a long-running SQL statement.

Make sure you type a semicolon at the end of each SQL command! The sqlite3 program looks for a semicolon to know when your SQL command is complete. If you omit the semicolon, sqlite3 will give you a continuation prompt and wait for you to enter more text to be added to the current SQL command. This feature allows you to enter SQL commands that span multiple lines. For example:

sqlite> CREATE TABLE tbl2 (
   ...>   f1 varchar(30) primary key,
   ...>   f2 text,
   ...>   f3 real
   ...> );
sqlite>

Aside: Querying the SQLITE_MASTER table

The database schema in an SQLite database is stored in a special table named "sqlite_master". You can execute "SELECT" statements against the special sqlite_master table just like any other table in an SQLite database. For example:

$ sqlite3 ex1
SQLite vresion 3.6.11
Enter ".help" for instructions
sqlite> select * from sqlite_master;
    type = table
    name = tbl1
tbl_name = tbl1
rootpage = 3
     sql = create table tbl1(one varchar(10), two smallint)
sqlite>

But you cannot execute DROP TABLE, UPDATE, INSERT or DELETE against the sqlite_master table. The sqlite_master table is updated automatically as you create or drop tables and indices from the database. You can not make manual changes to the sqlite_master table.

The schema for TEMPORARY tables is not stored in the "sqlite_master" table since TEMPORARY tables are not visible to applications other than the application that created the table. The schema for TEMPORARY tables is stored in another special table named "sqlite_temp_master". The "sqlite_temp_master" table is temporary itself.

Special commands to sqlite3

Most of the time, sqlite3 just reads lines of input and passes them on to the SQLite library for execution. But if an input line begins with a dot ("."), then that line is intercepted and interpreted by the sqlite3 program itself. These "dot commands" are typically used to change the output format of queries, or to execute certain prepackaged query statements.

For a listing of the available dot commands, you can enter ".help" at any time. For example:

sqlite> .help
.backup ?DB? FILE      Backup DB (default "main") to FILE
.bail ON|OFF           Stop after hitting an error.  Default OFF
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.
.genfkey ?OPTIONS?     Options are:
                         --no-drop: Do not drop old fkey triggers.
                         --ignore-errors: Ignore tables with fkey errors
                         --exec: Execute generated SQL immediately
                       See file tool/genfkey.README in the source 
                       distribution for further information.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices TABLE         Show names of all indices on TABLE
.iotrace FILE          Enable I/O diagnostic logging to FILE
.load FILE ?ENTRY?     Load an extension library
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Print STRING in place of NULL values
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.schema ?TABLE?        Show the CREATE statements
.separator STRING      Change separator used by output mode and .import
.show                  Show the current values for various settings
.tables ?PATTERN?      List names of tables matching a LIKE pattern
.timeout MS            Try opening locked tables for MS milliseconds
.timer ON|OFF          Turn the CPU timer measurement on or off
.width NUM NUM ...     Set column widths for "column" mode
sqlite>

Changing Output Formats

The sqlite3 program is able to show the results of a query in eight different formats: "csv", "column", "html", "insert", "line", "list", "tabs", and "tcl". You can use the ".mode" dot command to switch between these output formats.

The default output mode is "list". In list mode, each record of a query result is written on one line of output and each column within that record is separated by a specific separator string. The default separator is a pipe symbol ("|"). List mode is especially useful when you are going to send the output of a query to another program (such as AWK) for additional processing.

sqlite> .mode list
sqlite> select * from tbl1;
hello|10
goodbye|20
sqlite>

You can use the ".separator" dot command to change the separator for list mode. For example, to change the separator to a comma and a space, you could do this:

sqlite> .separator ", "
sqlite> select * from tbl1;
hello, 10
goodbye, 20
sqlite>

In "line" mode, each column in a row of the database is shown on a line by itself. Each line consists of the column name, an equal sign and the column data. Successive records are separated by a blank line. Here is an example of line mode output:

sqlite> .mode line
sqlite> select * from tbl1;
one = hello
two = 10

one = goodbye
two = 20
sqlite>

In column mode, each record is shown on a separate line with the data aligned in columns. For example:

sqlite> .mode column
sqlite> select * from tbl1;
one         two       
----------  ----------
hello       10        
goodbye     20        
sqlite>

By default, each column is at least 10 characters wide. Data that is too wide to fit in a column is truncated. You can adjust the column widths using the ".width" command. Like this:

sqlite> .width 12 6
sqlite> select * from tbl1;
one           two   
------------  ------
hello         10    
goodbye       20    
sqlite>

The ".width" command in the example above sets the width of the first column to 12 and the width of the second column to 6. All other column widths were unaltered. You can gives as many arguments to ".width" as necessary to specify the widths of as many columns as are in your query results.

If you specify a column a width of 0, then the column width is automatically adjusted to be the maximum of three numbers: 10, the width of the header, and the width of the first row of data. This makes the column width self-adjusting. The default width setting for every column is this auto-adjusting 0 value.

The column labels that appear on the first two lines of output can be turned on and off using the ".header" dot command. In the examples above, the column labels are on. To turn them off you could do this:

sqlite> .header off
sqlite> select * from tbl1;
hello         10    
goodbye       20    
sqlite>

Another useful output mode is "insert". In insert mode, the output is formatted to look like SQL INSERT statements. You can use insert mode to generate text that can later be used to input data into a different database.

When specifying insert mode, you have to give an extra argument which is the name of the table to be inserted into. For example:

sqlite> .mode insert new_table
sqlite> select * from tbl1;
INSERT INTO 'new_table' VALUES('hello',10);
INSERT INTO 'new_table' VALUES('goodbye',20);
sqlite>

The last output mode is "html". In this mode, sqlite3 writes the results of the query as an XHTML table. The beginning <TABLE> and the ending </TABLE> are not written, but all of the intervening <TR>s, <TH>s, and <TD>s are. The html output mode is envisioned as being useful for CGI.

Writing results to a file

By default, sqlite3 sends query results to standard output. You can change this using the ".output" command. Just put the name of an output file as an argument to the .output command and all subsequent query results will be written to that file. Use ".output stdout" to begin writing to standard output again. For example:

sqlite> .mode list
sqlite> .separator |
sqlite> .output test_file_1.txt
sqlite> select * from tbl1;
sqlite> .exit
$ cat test_file_1.txt
hello|10
goodbye|20
$

Querying the database schema

The sqlite3 program provides several convenience commands that are useful for looking at the schema of the database. There is nothing that these commands do that cannot be done by some other means. These commands are provided purely as a shortcut.

For example, to see a list of the tables in the database, you can enter ".tables".

sqlite> .tables
tbl1
tbl2
sqlite>

The ".tables" command is similar to setting list mode then executing the following query:

SELECT name FROM sqlite_master 
WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'
UNION ALL 
SELECT name FROM sqlite_temp_master 
WHERE type IN ('table','view') 
ORDER BY 1

In fact, if you look at the source code to the sqlite3 program (found in the source tree in the file src/shell.c) you'll find exactly the above query.

The ".indices" command works in a similar way to list all of the indices for a particular table. The ".indices" command takes a single argument which is the name of the table for which the indices are desired. Last, but not least, is the ".schema" command. With no arguments, the ".schema" command shows the original CREATE TABLE and CREATE INDEX statements that were used to build the current database. If you give the name of a table to ".schema", it shows the original CREATE statement used to make that table and all if its indices. We have:

sqlite> .schema
create table tbl1(one varchar(10), two smallint)
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
)
sqlite> .schema tbl2
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
)
sqlite>

The ".schema" command accomplishes the same thing as setting list mode, then entering the following query:

SELECT sql FROM 
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type!='meta'
ORDER BY tbl_name, type DESC, name

Or, if you give an argument to ".schema" because you only want the schema for a single table, the query looks like this:

SELECT sql FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'
ORDER BY substr(type,2,1), name

You can supply an argument to the .schema command. If you do, the query looks like this:

SELECT sql FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE tbl_name LIKE '%s'
  AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'
ORDER BY substr(type,2,1), name

The "%s" in the query is replace by your argument. This allows you to view the schema for some subset of the database.

sqlite> .schema %abc%

Along these same lines, the ".table" command also accepts a pattern as its first argument. If you give an argument to the .table command, a "%" is both appended and prepended and a LIKE clause is added to the query. This allows you to list only those tables that match a particular pattern.

The ".databases" command shows a list of all databases open in the current connection. There will always be at least 2. The first one is "main", the original database opened. The second is "temp", the database used for temporary tables. There may be additional databases listed for databases attached using the ATTACH statement. The first output column is the name the database is attached with, and the second column is the filename of the external file.

sqlite> .databases

Converting An Entire Database To An ASCII Text File

Use the ".dump" command to convert the entire contents of a database into a single ASCII text file. This file can be converted back into a database by piping it back into sqlite3.

A good way to make an archival copy of a database is this:

$ echo '.dump' | sqlite3 ex1 | gzip -c >ex1.dump.gz

This generates a file named ex1.dump.gz that contains everything you need to reconstruct the database at a later time, or on another machine. To reconstruct the database, just type:

$ zcat ex1.dump.gz | sqlite3 ex2

The text format is pure SQL so you can also use the .dump command to export an SQLite database into other popular SQL database engines. Like this:

$ createdb ex2
$ sqlite3 ex1 .dump | psql ex2

Other Dot Commands

The ".explain" dot command can be used to set the output mode to "column" and to set the column widths to values that are reasonable for looking at the output of an EXPLAIN command. The EXPLAIN command is an SQLite-specific SQL extension that is useful for debugging. If any regular SQL is prefaced by EXPLAIN, then the SQL command is parsed and analyzed but is not executed. Instead, the sequence of virtual machine instructions that would have been used to execute the SQL command are returned like a query result. For example:

sqlite> .explain
sqlite> explain delete from tbl1 where two<20;
addr  opcode        p1     p2     p3          
----  ------------  -----  -----  -------------------------------------   
0     ListOpen      0      0                  
1     Open          0      1      tbl1        
2     Next          0      9                  
3     Field         0      1                  
4     Integer       20     0                  
5     Ge            0      2                  
6     Key           0      0                  
7     ListWrite     0      0                  
8     Goto          0      2                  
9     Noop          0      0                  
10    ListRewind    0      0                  
11    ListRead      0      14                 
12    Delete        0      0                  
13    Goto          0      11                 
14    ListClose     0      0

The ".timeout" command sets the amount of time that the sqlite3 program will wait for locks to clear on files it is trying to access before returning an error. The default value of the timeout is zero so that an error is returned immediately if any needed database table or index is locked.

And finally, we mention the ".exit" command which causes the sqlite3 program to exit.

Using sqlite3 in a shell script

One way to use sqlite3 in a shell script is to use "echo" or "cat" to generate a sequence of commands in a file, then invoke sqlite3 while redirecting input from the generated command file. This works fine and is appropriate in many circumstances. But as an added convenience, sqlite3 allows a single SQL command to be entered on the command line as a second argument after the database name. When the sqlite3 program is launched with two arguments, the second argument is passed to the SQLite library for processing, the query results are printed on standard output in list mode, and the program exits. This mechanism is designed to make sqlite3 easy to use in conjunction with programs like "awk". For example:

$ sqlite3 ex1 'select * from tbl1' |
>  awk '{printf "<tr><td>%s<td>%s\n",$1,$2 }'
<tr><td>hello<td>10
<tr><td>goodbye<td>20
$

Ending shell commands

SQLite commands are normally terminated by a semicolon. In the shell you can also use the word "GO" (case-insensitive) or a slash character "/" on a line by itself to end a command. These are used by SQL Server and Oracle, respectively. These won't work insqlite3_exec(), because the shell translates these into a semicolon before passing them to that function.

Compiling the sqlite3 program from sources

The source code to the sqlite3 command line interface is in a single file named "shell.c" which you can download from the SQLite website. Compile this file (together with the sqlite3 library source code to generate the executable. For example:

gcc -o sqlite3 shell.c sqlite3.c -ldl -lpthread

Posted by 삼스
Android/정리2010. 4. 10. 08:09

Avoiding Memory Leaks

Android app들은 적어도 T-Mobile G1에서 16MB heap size제약이 있다. 이것은 phone을 위해서는 많은 양이면서 개발자에게는 아주 작은양이다. 대부분의 메모리를 사용할 생각이 아니더라도 다른 app들을 죽이지 않을 정도로 가능한 아주 작은 양의 메모리를 사용해야 한다. 더 많은 app들이 메모리에 유지되고 그들의 app들간에 전환이 일어날것이다. 내작업의 일부로써 메모리누수이슈가 속출할것이며 대부분의 시간을 이런 실수(하나의 Context에 오랬동안 레퍼런스를 유지하는것)때문에 보내게 될것이다.

Android에서 Context는 resource를 load하고 access하는것을 제외한 많은 작업에 이용된다. 이것은 모든 widget
들이 생성자에서 Context 파라메터를 인자로 받는 이유이기도 하다. 일반적인 Android app에서 Activity와
Application이라는 2개의 Context를 가진다. 이것은 보통 class와 method에 전달하는 첫번째 파라메터이다.

@Override
protected void onCreate(Bundle state) {
 
super.onCreate(state);
 
 
TextView label= new TextView(this);
  label
.setText("Leaks are bad");
 
  setContentView
(label);
}

위코드는 view가 전체액티비티에 하나의 레퍼런스를 가지고 있고 액티비티의 모든게 그안에 유지된다는것을 의미한다(모든 뷰구조와 그 리소스들), 그러므로 만일 Context가 누수(누수는 레퍼런스를 하나 유지하여 GC를 방지하는것을 의미한다)가 발생하면 당신은 많은 양의 메모리를 잃게된다. 전체 액티비티를 읽는것은 당신이 주의하지 않으면 아주 쉽게 일어날수 있다.

디폴트로 화면이 전환되면 현재 액티비티는 제거되고 그 상태가 저장된 상태로 새로운 액티비티가 다시 생성된다. 이런 방식으로 안드로이드는 리소스들을 다시 로드하여 UI를 다시 구성한다. 당신이 로테이션시마다 다시 로드되지 않기를 원하는 아주 큰 비트맵을 사용하는 어플리케이션을 작성한다고 상상해보라.  아주 쉬운 방법은 static field를 사용하는 것이다.

private static Drawable sBackground;
 
@Override
protected void onCreate(Bundle state) {
 
super.onCreate(state);
 
 
TextView label= new TextView(this);
  label
.setText("Leaks are bad");
 
 
if (sBackground== null) {
    sBackground
= getDrawable(R.drawable.large_bitmap);
 
}
  label
.setBackgroundDrawable(sBackground);
 
  setContentView
(label);
}

이 코드는 아주 빠르지만 또한 아주 잘못된 코드이다. 처음 액티비티가 생성되어 처음 로테이션될때 leak이 발생된다. Drawable이 뷰에 첨부될때 view는 drawable에 callback으로 설정된다. 위 코드상에서 drawable은 TextView의 참조를 가지고 있다. TextView는 액티비티의 참조를 가지고 있다.

이 예제는 Context의 누수의 아주 단순한 케이스중 하나이며 Home screen소스상에서(unbindDrawables()메소드를 찾아보라) 저장된 drawable의 callback에서 액티비티가 제거될때 null로 초기화하는 것을 볼수 있다.  충분히 흥미진진하고 누수된 context의 연결고리를 생성할수 있는 여러 군데가 있으며 그것은 좋지 않은 방법이다. 그것들은 당신을 오히려 더 빠르게 메모리부족을 야기시킨다.

2가지의 아주 쉬운 context와 연관된 메모리누수를 피하는 방법이 있다. 가장 명백한 방법의 하나는 그 Context자신의 영역의 외부로 빠져나가는것을 완전히 피하는것이다. 위 코드는 static을 사용하는 경우를 보여주었다. 하지만 내부 class나 그것의 내부참조를 외부의 클래스에 참조하도록 하는것은 똑같이 아주 위험하다.
또한가지 방법은 Application context를 사용하는것이다. 이는 액티비티 생명주기와 관계없이 당신의 application이 살아있는동안 항상 유지된다. 만일 아주 오랬동안 유지되어야 하는 객체를 사용해야 한다면 applicaiton객체를 기억하라. Application context는 Context.getApplicationContext()나 Activity.getApplication()을 통해 아주 쉽게 얻을수 있다.

Context연관 메모리누수를 피하는 방법을 정리하겠다. 아래 사항을 기억하라.

  • 오랬동안 유지되어야 하는 레퍼런스는 Activity context에 유지하지 말아라(그것들은 액티비티와 동일한 생명주기를 갖게 된다.) - Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  • Application context를 사용할것을 시도하라 - Try using the context-application instead of a context-activity
  • 액티비티의 생명주기를 관리하지 않는다면 액티비티내에 non-static inner class를 사용하는것을 피하라. static inner class를 사용해야 하며 액티비티내에서 weak reference를 사용하라.  Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  • GC는 메모리 누수에 대해 아무런 보장을 하지 않는다. - A garbage collector is not an insurance against memory leaks

Posted by 삼스
Android/App개발2010. 3. 18. 12:07
http://android-developers.blogspot.com/2010/02/live-wallpapers.html

Live wallpapers

Android 2.1에서 소개된 libe wallpaper로 사용자는 이제 더 풍부하고, 애니매이션가능하고 더 인터랙티브한 그들만의 홈스크린을 즐길수 있게 되었다. live wallpaper는 일반 Android application과 아주 유사하고 플랫폼의 모든 자산에 접근이 가능하다: SGL(2D drawing), OpenGL(3D drawing), GPS, accelerometers, network access, .... Nexus One에 들어가 있는 live wallpaper는 이런 API들을 이용하여 더 재미있고 흥미있는 UX의 예를 보여준다. 예를 들어 Grass wallpaper는 폰의 위치를 가지고 해가뜰때와 질때는 구분하여 하늘 이미지를 적절히 표시한다.


자신만의 live wallpaper를 만드는것은 쉽고, SurfaceView와 Canvas를 다루어보았다면 특히 더 쉽다. 작성방법을 배우려면 Android 2.1SDK에서 제공하는 CubeLiveWallpaper예제를 받아야 한다(android-2.1/samples/CubeLiveWallpaper에 있다)

Live wallpaper는 일반적인 Android service와 유사하다. 한가지 다른점은 onCreateEngine()이라는 메서드가 추가된것이다. 이 메서드는 WallpaperService.Engine을 생성하기 위해서 있다. 이 엔진은 wallpaper의 lifecycle을 관리하고 그리는것에 대한 처리를 담당한다. 시스템은 그릴수 있는 surface를 제공한다. wallpaper그리기는 아주 비용이 비싸기 때문에 가능한 CPU자원을 많이 사용하지 않도록 피해서 코드를 최적화해야 한다. 이는 wallpaper의 lifecycle관리가 중요한 이유이기도 한다. wallpaper가 화면에서 보여지지 않을때 wallpaper는 관련된 모든 activity를 stop해야 한다.

엔진은 또한 사용자나 Home app와 상호작용하기 위해 몇가지 메서드를 구현할 수 있다. 사용자가 다른 home screen으로 이동하기 위해 scroll하기를 원한다면 onOffsetChanged()를 사용할 수 있다. touch event를 처리하고자 한다면 onTouchEvent(MotionEvent)를 구현할 수 있다. 마지막으로 app들이 live wallpaper에 명령을 보낼수 있다. 현재는 표준 home app만이 live wallpaper의 onCommand()로 명령을 보낼수 있다 :

  • android.wallpaper.tap : 사용자가 워크스페이스상의 비어있는 곳을 tap할 때 사용됨. Water live wallpaper에서 사용자가 터치한 부분에서 새로운 물줄기가 생성되도록 구현할때 사용되었다.
  • android.home.drop : 사용자가 워크스페이스상에 ICON이나 Widget을 drop할때 사용됨.

Live wallpaper는 Android 2.1의 기능이다. 당신이 만든 live wallpaper를 다운로드하여 잘 동작할것을 보장하기 위해서는 manifest에 아래와 같이 기술해야 한다는 것을 기억하라 :

  • <uses-sdk android:minSdkVersion="7" />, Android 2.1에서 동작하도록 설정.
  • <uses-feature android:name="android.software.live_wallpaper" />, live wallpaper임을 설정

많은 live wallpaper들이 미리 마켓에 많으니 사용해보삼.

Posted by 삼스