Fossil SCM
Improve error handling in "fossil sqlite" command ".tables". Cherry-pick from SQLite trunk.
Commit
5c9aecae2149c164727d2b904d91facd2419b940
Parent
e757cd3d2345cc6…
1 file changed
+45
-10
+45
-10
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -2610,10 +2610,26 @@ | ||
| 2610 | 2610 | } |
| 2611 | 2611 | sqlite3_free(zSchemaTab); |
| 2612 | 2612 | return 0; |
| 2613 | 2613 | } |
| 2614 | 2614 | |
| 2615 | +/* | |
| 2616 | +** Print the current sqlite3_errmsg() value to stderr and return 1. | |
| 2617 | +*/ | |
| 2618 | +static int shellDatabaseError(sqlite3 *db){ | |
| 2619 | + const char *zErr = sqlite3_errmsg(db); | |
| 2620 | + fprintf(stderr, "Error: %s\n", zErr); | |
| 2621 | + return 1; | |
| 2622 | +} | |
| 2623 | + | |
| 2624 | +/* | |
| 2625 | +** Print an out-of-memory message to stderr and return 1. | |
| 2626 | +*/ | |
| 2627 | +static int shellNomemError(void){ | |
| 2628 | + fprintf(stderr, "Error: out of memory\n"); | |
| 2629 | + return 1; | |
| 2630 | +} | |
| 2615 | 2631 | |
| 2616 | 2632 | /* |
| 2617 | 2633 | ** If an input line begins with "." then invoke this routine to |
| 2618 | 2634 | ** process that line. |
| 2619 | 2635 | ** |
| @@ -3711,17 +3727,21 @@ | ||
| 3711 | 3727 | int nRow, nAlloc; |
| 3712 | 3728 | char *zSql = 0; |
| 3713 | 3729 | int ii; |
| 3714 | 3730 | open_db(p, 0); |
| 3715 | 3731 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 3716 | - if( rc ) return rc; | |
| 3732 | + if( rc ) return shellDatabaseError(p->db); | |
| 3733 | + | |
| 3734 | + /* Create an SQL statement to query for the list of tables in the | |
| 3735 | + ** main and all attached databases where the table name matches the | |
| 3736 | + ** LIKE pattern bound to variable "?1". */ | |
| 3717 | 3737 | zSql = sqlite3_mprintf( |
| 3718 | 3738 | "SELECT name FROM sqlite_master" |
| 3719 | 3739 | " WHERE type IN ('table','view')" |
| 3720 | 3740 | " AND name NOT LIKE 'sqlite_%%'" |
| 3721 | 3741 | " AND name LIKE ?1"); |
| 3722 | - while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 3742 | + while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 3723 | 3743 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 3724 | 3744 | if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; |
| 3725 | 3745 | if( strcmp(zDbName,"temp")==0 ){ |
| 3726 | 3746 | zSql = sqlite3_mprintf( |
| 3727 | 3747 | "%z UNION ALL " |
| @@ -3736,15 +3756,21 @@ | ||
| 3736 | 3756 | " WHERE type IN ('table','view')" |
| 3737 | 3757 | " AND name NOT LIKE 'sqlite_%%'" |
| 3738 | 3758 | " AND name LIKE ?1", zSql, zDbName, zDbName); |
| 3739 | 3759 | } |
| 3740 | 3760 | } |
| 3741 | - sqlite3_finalize(pStmt); | |
| 3742 | - zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); | |
| 3743 | - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 3761 | + rc = sqlite3_finalize(pStmt); | |
| 3762 | + if( zSql && rc==SQLITE_OK ){ | |
| 3763 | + zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); | |
| 3764 | + if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 3765 | + } | |
| 3744 | 3766 | sqlite3_free(zSql); |
| 3745 | - if( rc ) return rc; | |
| 3767 | + if( !zSql ) return shellNomemError(); | |
| 3768 | + if( rc ) return shellDatabaseError(p->db); | |
| 3769 | + | |
| 3770 | + /* Run the SQL statement prepared by the above block. Store the results | |
| 3771 | + ** as an array of nul-terminated strings in azResult[]. */ | |
| 3746 | 3772 | nRow = nAlloc = 0; |
| 3747 | 3773 | azResult = 0; |
| 3748 | 3774 | if( nArg>1 ){ |
| 3749 | 3775 | sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); |
| 3750 | 3776 | }else{ |
| @@ -3754,21 +3780,29 @@ | ||
| 3754 | 3780 | if( nRow>=nAlloc ){ |
| 3755 | 3781 | char **azNew; |
| 3756 | 3782 | int n2 = nAlloc*2 + 10; |
| 3757 | 3783 | azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); |
| 3758 | 3784 | if( azNew==0 ){ |
| 3759 | - fprintf(stderr, "Error: out of memory\n"); | |
| 3785 | + rc = shellNomemError(); | |
| 3760 | 3786 | break; |
| 3761 | 3787 | } |
| 3762 | 3788 | nAlloc = n2; |
| 3763 | 3789 | azResult = azNew; |
| 3764 | 3790 | } |
| 3765 | 3791 | azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); |
| 3766 | - if( azResult[nRow] ) nRow++; | |
| 3792 | + if( 0==azResult[nRow] ){ | |
| 3793 | + rc = shellNomemError(); | |
| 3794 | + break; | |
| 3795 | + } | |
| 3796 | + nRow++; | |
| 3797 | + } | |
| 3798 | + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ | |
| 3799 | + rc = shellDatabaseError(p->db); | |
| 3767 | 3800 | } |
| 3768 | - sqlite3_finalize(pStmt); | |
| 3769 | - if( nRow>0 ){ | |
| 3801 | + | |
| 3802 | + /* Pretty-print the contents of array azResult[] to the output */ | |
| 3803 | + if( rc==0 && nRow>0 ){ | |
| 3770 | 3804 | int len, maxlen = 0; |
| 3771 | 3805 | int i, j; |
| 3772 | 3806 | int nPrintCol, nPrintRow; |
| 3773 | 3807 | for(i=0; i<nRow; i++){ |
| 3774 | 3808 | len = strlen30(azResult[i]); |
| @@ -3783,10 +3817,11 @@ | ||
| 3783 | 3817 | fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); |
| 3784 | 3818 | } |
| 3785 | 3819 | fprintf(p->out, "\n"); |
| 3786 | 3820 | } |
| 3787 | 3821 | } |
| 3822 | + | |
| 3788 | 3823 | for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); |
| 3789 | 3824 | sqlite3_free(azResult); |
| 3790 | 3825 | }else |
| 3791 | 3826 | |
| 3792 | 3827 | if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ |
| 3793 | 3828 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -2610,10 +2610,26 @@ | |
| 2610 | } |
| 2611 | sqlite3_free(zSchemaTab); |
| 2612 | return 0; |
| 2613 | } |
| 2614 | |
| 2615 | |
| 2616 | /* |
| 2617 | ** If an input line begins with "." then invoke this routine to |
| 2618 | ** process that line. |
| 2619 | ** |
| @@ -3711,17 +3727,21 @@ | |
| 3711 | int nRow, nAlloc; |
| 3712 | char *zSql = 0; |
| 3713 | int ii; |
| 3714 | open_db(p, 0); |
| 3715 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 3716 | if( rc ) return rc; |
| 3717 | zSql = sqlite3_mprintf( |
| 3718 | "SELECT name FROM sqlite_master" |
| 3719 | " WHERE type IN ('table','view')" |
| 3720 | " AND name NOT LIKE 'sqlite_%%'" |
| 3721 | " AND name LIKE ?1"); |
| 3722 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 3723 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 3724 | if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; |
| 3725 | if( strcmp(zDbName,"temp")==0 ){ |
| 3726 | zSql = sqlite3_mprintf( |
| 3727 | "%z UNION ALL " |
| @@ -3736,15 +3756,21 @@ | |
| 3736 | " WHERE type IN ('table','view')" |
| 3737 | " AND name NOT LIKE 'sqlite_%%'" |
| 3738 | " AND name LIKE ?1", zSql, zDbName, zDbName); |
| 3739 | } |
| 3740 | } |
| 3741 | sqlite3_finalize(pStmt); |
| 3742 | zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); |
| 3743 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 3744 | sqlite3_free(zSql); |
| 3745 | if( rc ) return rc; |
| 3746 | nRow = nAlloc = 0; |
| 3747 | azResult = 0; |
| 3748 | if( nArg>1 ){ |
| 3749 | sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); |
| 3750 | }else{ |
| @@ -3754,21 +3780,29 @@ | |
| 3754 | if( nRow>=nAlloc ){ |
| 3755 | char **azNew; |
| 3756 | int n2 = nAlloc*2 + 10; |
| 3757 | azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); |
| 3758 | if( azNew==0 ){ |
| 3759 | fprintf(stderr, "Error: out of memory\n"); |
| 3760 | break; |
| 3761 | } |
| 3762 | nAlloc = n2; |
| 3763 | azResult = azNew; |
| 3764 | } |
| 3765 | azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); |
| 3766 | if( azResult[nRow] ) nRow++; |
| 3767 | } |
| 3768 | sqlite3_finalize(pStmt); |
| 3769 | if( nRow>0 ){ |
| 3770 | int len, maxlen = 0; |
| 3771 | int i, j; |
| 3772 | int nPrintCol, nPrintRow; |
| 3773 | for(i=0; i<nRow; i++){ |
| 3774 | len = strlen30(azResult[i]); |
| @@ -3783,10 +3817,11 @@ | |
| 3783 | fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); |
| 3784 | } |
| 3785 | fprintf(p->out, "\n"); |
| 3786 | } |
| 3787 | } |
| 3788 | for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); |
| 3789 | sqlite3_free(azResult); |
| 3790 | }else |
| 3791 | |
| 3792 | if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ |
| 3793 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -2610,10 +2610,26 @@ | |
| 2610 | } |
| 2611 | sqlite3_free(zSchemaTab); |
| 2612 | return 0; |
| 2613 | } |
| 2614 | |
| 2615 | /* |
| 2616 | ** Print the current sqlite3_errmsg() value to stderr and return 1. |
| 2617 | */ |
| 2618 | static int shellDatabaseError(sqlite3 *db){ |
| 2619 | const char *zErr = sqlite3_errmsg(db); |
| 2620 | fprintf(stderr, "Error: %s\n", zErr); |
| 2621 | return 1; |
| 2622 | } |
| 2623 | |
| 2624 | /* |
| 2625 | ** Print an out-of-memory message to stderr and return 1. |
| 2626 | */ |
| 2627 | static int shellNomemError(void){ |
| 2628 | fprintf(stderr, "Error: out of memory\n"); |
| 2629 | return 1; |
| 2630 | } |
| 2631 | |
| 2632 | /* |
| 2633 | ** If an input line begins with "." then invoke this routine to |
| 2634 | ** process that line. |
| 2635 | ** |
| @@ -3711,17 +3727,21 @@ | |
| 3727 | int nRow, nAlloc; |
| 3728 | char *zSql = 0; |
| 3729 | int ii; |
| 3730 | open_db(p, 0); |
| 3731 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 3732 | if( rc ) return shellDatabaseError(p->db); |
| 3733 | |
| 3734 | /* Create an SQL statement to query for the list of tables in the |
| 3735 | ** main and all attached databases where the table name matches the |
| 3736 | ** LIKE pattern bound to variable "?1". */ |
| 3737 | zSql = sqlite3_mprintf( |
| 3738 | "SELECT name FROM sqlite_master" |
| 3739 | " WHERE type IN ('table','view')" |
| 3740 | " AND name NOT LIKE 'sqlite_%%'" |
| 3741 | " AND name LIKE ?1"); |
| 3742 | while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 3743 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 3744 | if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; |
| 3745 | if( strcmp(zDbName,"temp")==0 ){ |
| 3746 | zSql = sqlite3_mprintf( |
| 3747 | "%z UNION ALL " |
| @@ -3736,15 +3756,21 @@ | |
| 3756 | " WHERE type IN ('table','view')" |
| 3757 | " AND name NOT LIKE 'sqlite_%%'" |
| 3758 | " AND name LIKE ?1", zSql, zDbName, zDbName); |
| 3759 | } |
| 3760 | } |
| 3761 | rc = sqlite3_finalize(pStmt); |
| 3762 | if( zSql && rc==SQLITE_OK ){ |
| 3763 | zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); |
| 3764 | if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 3765 | } |
| 3766 | sqlite3_free(zSql); |
| 3767 | if( !zSql ) return shellNomemError(); |
| 3768 | if( rc ) return shellDatabaseError(p->db); |
| 3769 | |
| 3770 | /* Run the SQL statement prepared by the above block. Store the results |
| 3771 | ** as an array of nul-terminated strings in azResult[]. */ |
| 3772 | nRow = nAlloc = 0; |
| 3773 | azResult = 0; |
| 3774 | if( nArg>1 ){ |
| 3775 | sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); |
| 3776 | }else{ |
| @@ -3754,21 +3780,29 @@ | |
| 3780 | if( nRow>=nAlloc ){ |
| 3781 | char **azNew; |
| 3782 | int n2 = nAlloc*2 + 10; |
| 3783 | azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); |
| 3784 | if( azNew==0 ){ |
| 3785 | rc = shellNomemError(); |
| 3786 | break; |
| 3787 | } |
| 3788 | nAlloc = n2; |
| 3789 | azResult = azNew; |
| 3790 | } |
| 3791 | azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); |
| 3792 | if( 0==azResult[nRow] ){ |
| 3793 | rc = shellNomemError(); |
| 3794 | break; |
| 3795 | } |
| 3796 | nRow++; |
| 3797 | } |
| 3798 | if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ |
| 3799 | rc = shellDatabaseError(p->db); |
| 3800 | } |
| 3801 | |
| 3802 | /* Pretty-print the contents of array azResult[] to the output */ |
| 3803 | if( rc==0 && nRow>0 ){ |
| 3804 | int len, maxlen = 0; |
| 3805 | int i, j; |
| 3806 | int nPrintCol, nPrintRow; |
| 3807 | for(i=0; i<nRow; i++){ |
| 3808 | len = strlen30(azResult[i]); |
| @@ -3783,10 +3817,11 @@ | |
| 3817 | fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); |
| 3818 | } |
| 3819 | fprintf(p->out, "\n"); |
| 3820 | } |
| 3821 | } |
| 3822 | |
| 3823 | for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); |
| 3824 | sqlite3_free(azResult); |
| 3825 | }else |
| 3826 | |
| 3827 | if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ |
| 3828 |