xref: /illumos-gate/usr/src/lib/libsqlite/src/copy.c (revision 1da57d55)
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,v 1.9 2004/02/25 13:47:31 drh Exp $
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 */
sqliteCopy(Parse * pParse,SrcList * pTableName,Token * pFilename,Token * pDelimiter,int onError)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 ){
36   Table *pTab;
37   int i;
38   Vdbe *v;
39   int addr, end;
40   char *zFile = 0;
41   const char *zDb;
42   sqlite *db = pParse->db;
43 
44 
45   if( sqlite_malloc_failed  ) goto copy_cleanup;
46   assert( pTableName->nSrc==1 );
47   pTab = sqliteSrcListLookup(pParse, pTableName);
48   if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
49   zFile = sqliteStrNDup(pFilename->z, pFilename->n);
50   sqliteDequote(zFile);
51   assert( pTab->iDb<db->nDb );
52   zDb = db->aDb[pTab->iDb].zName;
53   if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
54       || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
55     goto copy_cleanup;
56   }
57   v = sqliteGetVdbe(pParse);
58   if( v ){
59     sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
60     addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
61     sqliteVdbeDequoteP3(v, addr);
62     sqliteOpenTableAndIndices(pParse, pTab, 0);
63     if( db->flags & SQLITE_CountRows ){
64       sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
65     }
66     end = sqliteVdbeMakeLabel(v);
67     addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
68     if( pDelimiter ){
69       sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
70       sqliteVdbeDequoteP3(v, addr);
71     }else{
72       sqliteVdbeChangeP3(v, addr, "\t", 1);
73     }
74     if( pTab->iPKey>=0 ){
75       sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
76       sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
77     }else{
78       sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
79     }
80     for(i=0; i<pTab->nCol; i++){
81       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         sqliteVdbeAddOp(v, OP_String, 0, 0);
85       }else{
86         sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
87       }
88     }
89     sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
90                                    0, onError, addr);
91     sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
92     if( (db->flags & SQLITE_CountRows)!=0 ){
93       sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
94     }
95     sqliteVdbeAddOp(v, OP_Goto, 0, addr);
96     sqliteVdbeResolveLabel(v, end);
97     sqliteVdbeAddOp(v, OP_Noop, 0, 0);
98     sqliteEndWriteOperation(pParse);
99     if( db->flags & SQLITE_CountRows ){
100       sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
101       sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
102       sqliteVdbeAddOp(v, OP_Callback, 1, 0);
103     }
104   }
105 
106 copy_cleanup:
107   sqliteSrcListDelete(pTableName);
108   sqliteFree(zFile);
109   return;
110 }
111