System.Data.SQLite
Check-in [6eac31ab88]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:6eac31ab88f55b09f9ce52889973ddd8e8c25e63
Date: 2012-03-24 10:05:13
User: mistachkin
Comment:Start of work on ticket [c71846ed57], supporting the SQLite online backup API.
Tags And Properties
Changes
hide diffs side-by-side diffs patch

Changes to System.Data.SQLite/SQLite3.cs

1365 1365 internal override int SetLogCallback(SQLiteLogCallback func) 1366 1366 { 1367 1367 int rc = UnsafeNativeMethods.sqlite3_config( 1368 1368 (int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0); 1369 1369 1370 1370 return rc; 1371 1371 } 1372 + 1373 + /////////////////////////////////////////////////////////////////////////////////////////////// 1374 + 1375 + /// <summary> 1376 + /// Creates a new SQLite backup object based on the provided destination 1377 + /// database connection. The source database connection is the one 1378 + /// associated with this object. The source and destination database 1379 + /// connections cannot be the same. 1380 + /// </summary> 1381 + /// <param name="destCnn">The destination database connection handle.</param> 1382 + /// <param name="destName">The destination database name.</param> 1383 + /// <param name="sourceName">The source database name.</param> 1384 + /// <returns>The newly created backup object.</returns> 1385 + internal override SQLiteBackup InitializeBackup( 1386 + SQLiteConnectionHandle destCnn, 1387 + string destName, 1388 + string sourceName 1389 + ) 1390 + { 1391 + if (destCnn == null) 1392 + throw new ArgumentNullException("destCnn"); 1393 + 1394 + if (destName == null) 1395 + throw new ArgumentNullException("destName"); 1396 + 1397 + if (sourceName == null) 1398 + throw new ArgumentNullException("sourceName"); 1399 + 1400 + byte[] zDestName = ToUTF8(destName); 1401 + byte[] zSourceName = ToUTF8(sourceName); 1402 + 1403 + IntPtr backup = UnsafeNativeMethods.sqlite3_backup_init( 1404 + destCnn, zDestName, _sql, zSourceName); 1405 + 1406 + if (backup == IntPtr.Zero) 1407 + throw new SQLiteException(ResultCode(), SQLiteLastError()); 1408 + 1409 + return new SQLiteBackup(this, backup, destCnn, zDestName, _sql, 1410 + zSourceName); 1411 + } 1412 + 1413 + /// <summary> 1414 + /// Copies up to N pages from the source database to the destination 1415 + /// database associated with the specified backup object. 1416 + /// </summary> 1417 + /// <param name="backup">The backup object to use.</param> 1418 + /// <param name="nPage"> 1419 + /// The number of pages to copy, negative to copy all remaining pages. 1420 + /// </param> 1421 + /// <returns> 1422 + /// True if there are more pages to be copied, false otherwise. 1423 + /// </returns> 1424 + internal override bool StepBackup( 1425 + SQLiteBackup backup, 1426 + int nPage 1427 + ) 1428 + { 1429 + if (backup == null) 1430 + throw new ArgumentNullException("backup"); 1431 + 1432 + SQLiteBackupHandle handle = backup._sqlite_backup; 1433 + 1434 + if (handle == null) 1435 + throw new InvalidOperationException( 1436 + "Backup object has an invalid handle."); 1437 + 1438 + int n = UnsafeNativeMethods.sqlite3_backup_step(handle, nPage); 1439 + backup._stepResult = n; /* NOTE: Save for use by FinishBackup. */ 1440 + 1441 + if (n == (int)SQLiteErrorCode.Ok) 1442 + return true; 1443 + else if (n == (int)SQLiteErrorCode.Done) 1444 + return false; 1445 + else 1446 + throw new SQLiteException(n, SQLiteLastError()); 1447 + } 1448 + 1449 + /// <summary> 1450 + /// Returns the number of pages remaining to be copied from the source 1451 + /// database to the destination database associated with the specified 1452 + /// backup object. 1453 + /// </summary> 1454 + /// <param name="backup">The backup object to check.</param> 1455 + /// <returns>The number of pages remaining to be copied.</returns> 1456 + internal override int RemainingBackup( 1457 + SQLiteBackup backup 1458 + ) 1459 + { 1460 + if (backup == null) 1461 + throw new ArgumentNullException("backup"); 1462 + 1463 + SQLiteBackupHandle handle = backup._sqlite_backup; 1464 + 1465 + if (handle == null) 1466 + throw new InvalidOperationException( 1467 + "Backup object has an invalid handle."); 1468 + 1469 + return UnsafeNativeMethods.sqlite3_backup_remaining(handle); 1470 + } 1471 + 1472 + /// <summary> 1473 + /// Returns the total number of pages in the source database associated 1474 + /// with the specified backup object. 1475 + /// </summary> 1476 + /// <param name="backup">The backup object to check.</param> 1477 + /// <returns>The total number of pages in the source database.</returns> 1478 + internal override int PageCountBackup( 1479 + SQLiteBackup backup 1480 + ) 1481 + { 1482 + if (backup == null) 1483 + throw new ArgumentNullException("backup"); 1484 + 1485 + SQLiteBackupHandle handle = backup._sqlite_backup; 1486 + 1487 + if (handle == null) 1488 + throw new InvalidOperationException( 1489 + "Backup object has an invalid handle."); 1490 + 1491 + return UnsafeNativeMethods.sqlite3_backup_pagecount(handle); 1492 + } 1493 + 1494 + /// <summary> 1495 + /// Destroys the backup object, rolling back any backup that may be in 1496 + /// progess. 1497 + /// </summary> 1498 + /// <param name="backup">The backup object to destroy.</param> 1499 + internal override void FinishBackup( 1500 + SQLiteBackup backup 1501 + ) 1502 + { 1503 + if (backup == null) 1504 + throw new ArgumentNullException("backup"); 1505 + 1506 + SQLiteBackupHandle handle = backup._sqlite_backup; 1507 + 1508 + if (handle == null) 1509 + throw new InvalidOperationException( 1510 + "Backup object has an invalid handle."); 1511 + 1512 + int n = UnsafeNativeMethods.sqlite3_backup_finish(handle); 1513 + 1514 + if (n > 0 && n != backup._stepResult) 1515 + throw new SQLiteException(n, SQLiteLastError()); 1516 + } 1517 + 1518 + /////////////////////////////////////////////////////////////////////////////////////////////// 1372 1519 1373 1520 /// <summary> 1374 1521 /// Determines if the SQLite core library has been initialized for the 1375 1522 /// current process. 1376 1523 /// </summary> 1377 1524 /// <returns> 1378 1525 /// A boolean indicating whether or not the SQLite core library has been

Added System.Data.SQLite/SQLiteBackup.cs

1 +/******************************************************** 2 + * ADO.NET 2.0 Data Provider for SQLite Version 3.X 3 + * Written by Robert Simpson (robert@blackcastlesoft.com) 4 + * 5 + * Released to the public domain, use at your own risk! 6 + ********************************************************/ 7 + 8 +namespace System.Data.SQLite 9 +{ 10 + using System; 11 + 12 + /// <summary> 13 + /// Represents a single SQL backup in SQLite. 14 + /// </summary> 15 + internal sealed class SQLiteBackup : IDisposable 16 + { 17 + /// <summary> 18 + /// The underlying SQLite object this backup is bound to. 19 + /// </summary> 20 + internal SQLiteBase _sql; 21 + 22 + /// <summary> 23 + /// The actual backup handle. 24 + /// </summary> 25 + internal SQLiteBackupHandle _sqlite_backup; 26 + 27 + /// <summary> 28 + /// The destination database for the backup. 29 + /// </summary> 30 + internal IntPtr _destDb; 31 + 32 + /// <summary> 33 + /// The destination database name for the backup. 34 + /// </summary> 35 + internal byte[] _zDestName; 36 + 37 + /// <summary> 38 + /// The source database for the backup. 39 + /// </summary> 40 + internal IntPtr _sourceDb; 41 + 42 + /// <summary> 43 + /// The source database name for the backup. 44 + /// </summary> 45 + internal byte[] _zSourceName; 46 + 47 + /// <summary> 48 + /// The last result from the StepBackup method of the SQLite3 class. 49 + /// This is used to determine if the call to the FinishBackup method of 50 + /// the SQLite3 class should throw an exception when it receives a non-Ok 51 + /// return code from the core SQLite library. 52 + /// </summary> 53 + internal int _stepResult; 54 + 55 + /// <summary> 56 + /// Initializes the backup. 57 + /// </summary> 58 + /// <param name="sqlbase">The base SQLite object.</param> 59 + /// <param name="backup">The backup handle.</param> 60 + /// <param name="destDb">The destination database for the backup.</param> 61 + /// <param name="zDestName">The destination database name for the backup.</param> 62 + /// <param name="sourceDb">The source database for the backup.</param> 63 + /// <param name="zSourceName">The source database name for the backup.</param> 64 + internal SQLiteBackup( 65 + SQLiteBase sqlbase, 66 + SQLiteBackupHandle backup, 67 + IntPtr destDb, 68 + byte[] zDestName, 69 + IntPtr sourceDb, 70 + byte[] zSourceName 71 + ) 72 + { 73 + _sql = sqlbase; 74 + _sqlite_backup = backup; 75 + _destDb = destDb; 76 + _zDestName = zDestName; 77 + _sourceDb = sourceDb; 78 + _zSourceName = zSourceName; 79 + } 80 + 81 + /////////////////////////////////////////////////////////////////////////////////////////////// 82 + 83 + #region IDisposable Members 84 + /// <summary> 85 + /// Disposes and finalizes the backup. 86 + /// </summary> 87 + public void Dispose() 88 + { 89 + Dispose(true); 90 + GC.SuppressFinalize(this); 91 + } 92 + #endregion 93 + 94 + /////////////////////////////////////////////////////////////////////////////////////////////// 95 + 96 + #region IDisposable "Pattern" Members 97 + private bool disposed; 98 + private void CheckDisposed() /* throw */ 99 + { 100 +#if THROW_ON_DISPOSED 101 + if (disposed) 102 + throw new ObjectDisposedException(typeof(SQLiteBackup).Name); 103 +#endif 104 + } 105 + 106 + /////////////////////////////////////////////////////////////////////////////////////////////// 107 + 108 + private void Dispose(bool disposing) 109 + { 110 + if (!disposed) 111 + { 112 + if (disposing) 113 + { 114 + //////////////////////////////////// 115 + // dispose managed resources here... 116 + //////////////////////////////////// 117 + 118 + if (_sqlite_backup != null) 119 + { 120 + _sqlite_backup.Dispose(); 121 + _sqlite_backup = null; 122 + } 123 + 124 + _zSourceName = null; 125 + _sourceDb = IntPtr.Zero; 126 + _zDestName = null; 127 + _destDb = IntPtr.Zero; 128 + _sql = null; 129 + } 130 + 131 + ////////////////////////////////////// 132 + // release unmanaged resources here... 133 + ////////////////////////////////////// 134 + 135 + disposed = true; 136 + } 137 + } 138 + #endregion 139 + 140 + /////////////////////////////////////////////////////////////////////////////////////////////// 141 + 142 + #region Destructor 143 + ~SQLiteBackup() 144 + { 145 + Dispose(false); 146 + } 147 + #endregion 148 + } 149 +}

Changes to System.Data.SQLite/SQLiteBase.cs

219 219 internal abstract bool AutoCommit 220 220 { 221 221 get; 222 222 } 223 223 224 224 internal abstract int FileControl(string zDbName, int op, IntPtr pArg); 225 225 226 + /// <summary> 227 + /// Creates a new SQLite backup object based on the provided destination 228 + /// database connection. The source database connection is the one 229 + /// associated with this object. The source and destination database 230 + /// connections cannot be the same. 231 + /// </summary> 232 + /// <param name="destCnn">The destination database connection handle.</param> 233 + /// <param name="destName">The destination database name.</param> 234 + /// <param name="sourceName">The source database name.</param> 235 + /// <returns>The newly created backup object.</returns> 236 + internal abstract SQLiteBackup InitializeBackup( 237 + SQLiteConnectionHandle destCnn, string destName, 238 + string sourceName); 239 + 240 + /// <summary> 241 + /// Copies up to N pages from the source database to the destination 242 + /// database associated with the specified backup object. 243 + /// </summary> 244 + /// <param name="backup">The backup object to use.</param> 245 + /// <param name="nPage"> 246 + /// The number of pages to copy, negative to copy all remaining pages. 247 + /// </param> 248 + /// <returns> 249 + /// True if there are more pages to be copied, false otherwise. 250 + /// </returns> 251 + internal abstract bool StepBackup(SQLiteBackup backup, int nPage); 252 + 253 + /// <summary> 254 + /// Returns the number of pages remaining to be copied from the source 255 + /// database to the destination database associated with the specified 256 + /// backup object. 257 + /// </summary> 258 + /// <param name="backup">The backup object to check.</param> 259 + /// <returns>The number of pages remaining to be copied.</returns> 260 + internal abstract int RemainingBackup(SQLiteBackup backup); 261 + 262 + /// <summary> 263 + /// Returns the total number of pages in the source database associated 264 + /// with the specified backup object. 265 + /// </summary> 266 + /// <param name="backup">The backup object to check.</param> 267 + /// <returns>The total number of pages in the source database.</returns> 268 + internal abstract int PageCountBackup(SQLiteBackup backup); 269 + 270 + /// <summary> 271 + /// Destroys the backup object, rolling back any backup that may be in 272 + /// progess. 273 + /// </summary> 274 + /// <param name="backup">The backup object to destroy.</param> 275 + internal abstract void FinishBackup(SQLiteBackup backup); 276 + 226 277 /////////////////////////////////////////////////////////////////////////////////////////////// 227 278 228 279 #region IDisposable Members 229 280 public void Dispose() 230 281 { 231 282 Dispose(true); 232 283 GC.SuppressFinalize(this); ................................................................................ 288 339 #if !SQLITE_STANDARD 289 340 int len; 290 341 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len), len); 291 342 #else 292 343 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1); 293 344 #endif 294 345 } 346 + 347 + internal static void FinishBackup(SQLiteBackupHandle backup) 348 + { 349 + lock (_lock) 350 + { 351 + int n = UnsafeNativeMethods.sqlite3_backup_finish(backup); 352 + if (n > 0) throw new SQLiteException(n, null); 353 + } 354 + } 295 355 296 356 internal static void FinalizeStatement(SQLiteStatementHandle stmt) 297 357 { 298 358 lock (_lock) 299 359 { 300 360 #if !SQLITE_STANDARD 301 361 int n = UnsafeNativeMethods.sqlite3_finalize_interop(stmt);

Changes to System.Data.SQLite/System.Data.SQLite.Files.targets

13 13 ****************************************************************************** 14 14 --> 15 15 16 16 <ItemGroup> 17 17 <Compile Include="AssemblyInfo.cs" /> 18 18 <Compile Include="SQLite3.cs" /> 19 19 <Compile Include="SQLite3_UTF16.cs" /> 20 + <Compile Include="SQLiteBackup.cs" /> 20 21 <Compile Include="SQLiteBase.cs" /> 21 22 <Compile Include="SQLiteCommand.cs"> 22 23 <SubType>Component</SubType> 23 24 </Compile> 24 25 <Compile Include="SQLiteCommandBuilder.cs"> 25 26 <SubType>Component</SubType> 26 27 </Compile>

Changes to System.Data.SQLite/UnsafeNativeMethods.cs

1231 1231 #if !PLATFORM_COMPACTFRAMEWORK 1232 1232 [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1233 1233 #else 1234 1234 [DllImport(SQLITE_DLL)] 1235 1235 #endif 1236 1236 internal static extern int sqlite3_file_control(IntPtr db, byte[] zDbName, int op, IntPtr pArg); 1237 1237 1238 +#if !PLATFORM_COMPACTFRAMEWORK 1239 + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1240 +#else 1241 + [DllImport(SQLITE_DLL)] 1242 +#endif 1243 + internal static extern IntPtr sqlite3_backup_init(IntPtr destDb, byte[] zDestName, IntPtr sourceDb, byte[] zSourceName); 1244 + 1245 +#if !PLATFORM_COMPACTFRAMEWORK 1246 + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1247 +#else 1248 + [DllImport(SQLITE_DLL)] 1249 +#endif 1250 + internal static extern int sqlite3_backup_step(IntPtr backup, int nPage); 1251 + 1252 +#if !PLATFORM_COMPACTFRAMEWORK 1253 + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1254 +#else 1255 + [DllImport(SQLITE_DLL)] 1256 +#endif 1257 + internal static extern int sqlite3_backup_finish(IntPtr backup); 1258 + 1259 +#if !PLATFORM_COMPACTFRAMEWORK 1260 + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1261 +#else 1262 + [DllImport(SQLITE_DLL)] 1263 +#endif 1264 + internal static extern int sqlite3_backup_remaining(IntPtr backup); 1265 + 1266 +#if !PLATFORM_COMPACTFRAMEWORK 1267 + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1268 +#else 1269 + [DllImport(SQLITE_DLL)] 1270 +#endif 1271 + internal static extern int sqlite3_backup_pagecount(IntPtr backup); 1238 1272 #endregion 1239 1273 } 1240 1274 1241 1275 #if PLATFORM_COMPACTFRAMEWORK 1242 1276 internal abstract class CriticalHandle : IDisposable 1243 1277 { 1244 1278 private bool _isClosed; ................................................................................ 1457 1491 } 1458 1492 1459 1493 public override bool IsInvalid 1460 1494 { 1461 1495 get { return (handle == IntPtr.Zero); } 1462 1496 } 1463 1497 } 1498 + 1499 + // Provides finalization support for unmanaged SQLite backup objects. 1500 + internal class SQLiteBackupHandle : CriticalHandle 1501 + { 1502 + public static implicit operator IntPtr(SQLiteBackupHandle backup) 1503 + { 1504 + return (backup != null) ? backup.handle : IntPtr.Zero; 1505 + } 1506 + 1507 + public static implicit operator SQLiteBackupHandle(IntPtr backup) 1508 + { 1509 + return new SQLiteBackupHandle(backup); 1510 + } 1511 + 1512 + private SQLiteBackupHandle(IntPtr backup) 1513 + : this() 1514 + { 1515 + SetHandle(backup); 1516 + } 1517 + 1518 + internal SQLiteBackupHandle() 1519 + : base(IntPtr.Zero) 1520 + { 1521 + } 1522 + 1523 + protected override bool ReleaseHandle() 1524 + { 1525 + try 1526 + { 1527 + SQLiteBase.FinishBackup(this); 1528 + 1529 +#if DEBUG && !NET_COMPACT_20 1530 + try 1531 + { 1532 + Trace.WriteLine(String.Format( 1533 + "FinishBackup: {0}", handle)); 1534 + } 1535 + catch 1536 + { 1537 + } 1538 +#endif 1539 + 1540 +#if DEBUG 1541 + return true; 1542 +#endif 1543 + } 1544 +#if DEBUG && !NET_COMPACT_20 1545 + catch (SQLiteException e) 1546 +#else 1547 + catch (SQLiteException) 1548 +#endif 1549 + { 1550 +#if DEBUG && !NET_COMPACT_20 1551 + try 1552 + { 1553 + Trace.WriteLine(String.Format( 1554 + "FinishBackup: {0}, exception: {1}", 1555 + handle, e)); 1556 + } 1557 + catch 1558 + { 1559 + } 1560 +#endif 1561 + } 1562 +#if DEBUG 1563 + return false; 1564 +#else 1565 + return true; 1566 +#endif 1567 + } 1568 + 1569 + public override bool IsInvalid 1570 + { 1571 + get { return (handle == IntPtr.Zero); } 1572 + } 1573 + } 1464 1574 }