1 : /*
2 : ** 2003 April 6
3 : **
4 : ** The author disclaims copyright to this source code. In place of
5 : ** a legal notice, here is a blessing:
6 : **
7 : ** May you do good and not evil.
8 : ** May you find forgiveness for yourself and forgive others.
9 : ** May you share freely, never taking more than you give.
10 : **
11 : *************************************************************************
12 : ** This file contains code used to implement the COPY command.
13 : **
14 : ** $Id: copy.c 195361 2005-09-07 15:11:33Z iliaa $
15 : */
16 : #include "sqliteInt.h"
17 :
18 : /*
19 : ** The COPY command is for compatibility with PostgreSQL and specificially
20 : ** for the ability to read the output of pg_dump. The format is as
21 : ** follows:
22 : **
23 : ** COPY table FROM file [USING DELIMITERS string]
24 : **
25 : ** "table" is an existing table name. We will read lines of code from
26 : ** file to fill this table with data. File might be "stdin". The optional
27 : ** delimiter string identifies the field separators. The default is a tab.
28 : */
29 : void sqliteCopy(
30 : Parse *pParse, /* The parser context */
31 : SrcList *pTableName, /* The name of the table into which we will insert */
32 : Token *pFilename, /* The file from which to obtain information */
33 : Token *pDelimiter, /* Use this as the field delimiter */
34 : int onError /* What to do if a constraint fails */
35 0 : ){
36 : Table *pTab;
37 : int i;
38 : Vdbe *v;
39 : int addr, end;
40 0 : char *zFile = 0;
41 : const char *zDb;
42 0 : sqlite *db = pParse->db;
43 :
44 :
45 0 : if( sqlite_malloc_failed ) goto copy_cleanup;
46 : assert( pTableName->nSrc==1 );
47 0 : pTab = sqliteSrcListLookup(pParse, pTableName);
48 0 : if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
49 0 : zFile = sqliteStrNDup(pFilename->z, pFilename->n);
50 0 : sqliteDequote(zFile);
51 : assert( pTab->iDb<db->nDb );
52 0 : zDb = db->aDb[pTab->iDb].zName;
53 0 : if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
54 : || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
55 : goto copy_cleanup;
56 : }
57 0 : v = sqliteGetVdbe(pParse);
58 0 : if( v ){
59 0 : sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
60 0 : addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
61 0 : sqliteVdbeDequoteP3(v, addr);
62 0 : sqliteOpenTableAndIndices(pParse, pTab, 0);
63 0 : if( db->flags & SQLITE_CountRows ){
64 0 : sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */
65 : }
66 0 : end = sqliteVdbeMakeLabel(v);
67 0 : addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
68 0 : if( pDelimiter ){
69 0 : sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
70 0 : sqliteVdbeDequoteP3(v, addr);
71 : }else{
72 0 : sqliteVdbeChangeP3(v, addr, "\t", 1);
73 : }
74 0 : if( pTab->iPKey>=0 ){
75 0 : sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
76 0 : sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
77 : }else{
78 0 : sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
79 : }
80 0 : for(i=0; i<pTab->nCol; i++){
81 0 : if( i==pTab->iPKey ){
82 : /* The integer primary key column is filled with NULL since its
83 : ** value is always pulled from the record number */
84 0 : sqliteVdbeAddOp(v, OP_String, 0, 0);
85 : }else{
86 0 : sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
87 : }
88 : }
89 0 : sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
90 : 0, onError, addr);
91 0 : sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
92 0 : if( (db->flags & SQLITE_CountRows)!=0 ){
93 0 : sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */
94 : }
95 0 : sqliteVdbeAddOp(v, OP_Goto, 0, addr);
96 0 : sqliteVdbeResolveLabel(v, end);
97 0 : sqliteVdbeAddOp(v, OP_Noop, 0, 0);
98 0 : sqliteEndWriteOperation(pParse);
99 0 : if( db->flags & SQLITE_CountRows ){
100 0 : sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
101 0 : sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
102 0 : sqliteVdbeAddOp(v, OP_Callback, 1, 0);
103 : }
104 : }
105 :
106 0 : copy_cleanup:
107 0 : sqliteSrcListDelete(pTableName);
108 0 : sqliteFree(zFile);
109 : return;
110 : }
|