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
- branch=backupApi propagates to descendants
- sym-backupApi propagates to descendants
- sym-trunk cancelled
Changes
Changes to System.Data.SQLite/SQLite3.cs
1365 internal override int SetLogCallback(SQLiteLogCallback func) 1365 internal override int SetLogCallback(SQLiteLogCallback func) 1366 { 1366 { 1367 int rc = UnsafeNativeMethods.sqlite3_config( 1367 int rc = UnsafeNativeMethods.sqlite3_config( 1368 (int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0); 1368 (int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0); 1369 1369 1370 return rc; 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 /// <summary> 1520 /// <summary> 1374 /// Determines if the SQLite core library has been initialized for the 1521 /// Determines if the SQLite core library has been initialized for the 1375 /// current process. 1522 /// current process. 1376 /// </summary> 1523 /// </summary> 1377 /// <returns> 1524 /// <returns> 1378 /// A boolean indicating whether or not the SQLite core library has been 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-O > 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 > 62 /// <param name="sourceDb">The source database for the backup.</param> > 63 /// <param name="zSourceName">The source database name for the backup.</ > 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 internal abstract bool AutoCommit 219 internal abstract bool AutoCommit 220 { 220 { 221 get; 221 get; 222 } 222 } 223 223 224 internal abstract int FileControl(string zDbName, int op, IntPtr pArg); 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 #region IDisposable Members 279 #region IDisposable Members 229 public void Dispose() 280 public void Dispose() 230 { 281 { 231 Dispose(true); 282 Dispose(true); 232 GC.SuppressFinalize(this); 283 GC.SuppressFinalize(this); ................................................................................................................................................................................ 288 #if !SQLITE_STANDARD 339 #if !SQLITE_STANDARD 289 int len; 340 int len; 290 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len 341 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len 291 #else 342 #else 292 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1); 343 return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1); 293 #endif 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 internal static void FinalizeStatement(SQLiteStatementHandle stmt) 356 internal static void FinalizeStatement(SQLiteStatementHandle stmt) 297 { 357 { 298 lock (_lock) 358 lock (_lock) 299 { 359 { 300 #if !SQLITE_STANDARD 360 #if !SQLITE_STANDARD 301 int n = UnsafeNativeMethods.sqlite3_finalize_interop(stmt); 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 <ItemGroup> 16 <ItemGroup> 17 <Compile Include="AssemblyInfo.cs" /> 17 <Compile Include="AssemblyInfo.cs" /> 18 <Compile Include="SQLite3.cs" /> 18 <Compile Include="SQLite3.cs" /> 19 <Compile Include="SQLite3_UTF16.cs" /> 19 <Compile Include="SQLite3_UTF16.cs" /> > 20 <Compile Include="SQLiteBackup.cs" /> 20 <Compile Include="SQLiteBase.cs" /> 21 <Compile Include="SQLiteBase.cs" /> 21 <Compile Include="SQLiteCommand.cs"> 22 <Compile Include="SQLiteCommand.cs"> 22 <SubType>Component</SubType> 23 <SubType>Component</SubType> 23 </Compile> 24 </Compile> 24 <Compile Include="SQLiteCommandBuilder.cs"> 25 <Compile Include="SQLiteCommandBuilder.cs"> 25 <SubType>Component</SubType> 26 <SubType>Component</SubType> 26 </Compile> 27 </Compile>
Changes to System.Data.SQLite/UnsafeNativeMethods.cs
1231 #if !PLATFORM_COMPACTFRAMEWORK 1231 #if !PLATFORM_COMPACTFRAMEWORK 1232 [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1232 [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] 1233 #else 1233 #else 1234 [DllImport(SQLITE_DLL)] 1234 [DllImport(SQLITE_DLL)] 1235 #endif 1235 #endif 1236 internal static extern int sqlite3_file_control(IntPtr db, byte[] zDbName, i 1236 internal static extern int sqlite3_file_control(IntPtr db, byte[] zDbName, i 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[] zDes > 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 #endregion 1272 #endregion 1239 } 1273 } 1240 1274 1241 #if PLATFORM_COMPACTFRAMEWORK 1275 #if PLATFORM_COMPACTFRAMEWORK 1242 internal abstract class CriticalHandle : IDisposable 1276 internal abstract class CriticalHandle : IDisposable 1243 { 1277 { 1244 private bool _isClosed; 1278 private bool _isClosed; ................................................................................................................................................................................ 1457 } 1491 } 1458 1492 1459 public override bool IsInvalid 1493 public override bool IsInvalid 1460 { 1494 { 1461 get { return (handle == IntPtr.Zero); } 1495 get { return (handle == IntPtr.Zero); } 1462 } 1496 } 1463 } 1497 } 1464 } | 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 } > 1574 }