sha,message,author_date,committer_date,raw_author,raw_committer,repo,author,committer b2dee11fcd989d9e2a7bf4de1e23dbc320c05013,"Databases now get distinct colours A left border based on their content hash. Closes #31",2017-11-09T14:12:42Z,2017-11-09T14:14:40Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 abb591d83264bbf11a5eb9daf03011d051e8f833,"Added --reload argument to 'immutabase serve' command Uses hupper to restart the server when the code changes. Useful for development. Depends on https://pypi.python.org/pypi/hupper",2017-11-09T13:46:16Z,2017-11-09T14:14:26Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 8af7bc100c681975894f49f4ffd6d26a06e93f60,"Added a MANIFEST.in Now python setup.py bdist_wheel creates a .whl that includes the CSS.",2017-11-09T02:39:42Z,2017-11-09T02:39:42Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 7e0cedae3d920797f6f9411aea90a2b1d86ac9c7,"Now using bootstrap 4 beta Refs #16",2017-11-06T02:49:07Z,2017-11-06T02:49:07Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 9e9e9613907b6a2a8a051fdda93c0d26344ee110,Fixed error in RowView,2017-11-06T02:38:06Z,2017-11-06T02:38:06Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 25c241fa5a0f8868e3c1bc5be4f5888caa47d864,Renamed project to immutabase,2017-11-06T02:32:13Z,2017-11-06T02:32:13Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 a0bb9da17fb95ac5e3bcd3c8d800d33c25a71bbc,"Now requires DB files to be passed as arguments Refs #40",2017-11-06T02:24:43Z,2017-11-06T02:24:43Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 186c513a61a091b9f83d788e25b08f41a84ed9a3,"Support parameterized SQL and block potentially harmful queries You can now call arbitrary SQL like this: /flights?sql=select%20*%20from%20airports%20where%20country%20like%20:c&c=iceland Unescaped, those querystring params look like this: sql = select * from airports where country like :c c = iceland So SQL can be constructed with named parameters embedded in it, which will then be read from the querystring and correctly escaped. This means we can aggressively filter the SQL parameter for potentially dangerous syntax. For the moment we enforce that it starts with a SELECT statement and we ban the sequence ""pragma"" from it entirely. If you need to use pragma in a query, you can use the new named parameter mechanism. Fixes #39",2017-11-05T02:49:18Z,2017-11-05T02:49:18Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 31b21f5c5e15fc3acab7fabb170c1da71dc3c98c,"Moved all SQLite queries to threads SQLite operations are blocking, but we're running everything in Sanic, an asyncio web framework, so blocking operations are bad - a long-running DB operation could hold up the entire server. Instead, I've moved all SQLite operations into threads. These are managed by a concurrent.futures ThreadPoolExecutor. This means I can run up to X queries in parallel, and I can continue to queue up additional incoming HTTP traffic while the threadpool is busy. Each thread is responsible for managing its own SQLite connections - one per database. These are cached in a threadlocal. Since we are working with immutable, read-only SQLite databases it should be safe to share SQLite objects across threads. On this assumption I'm using the check_same_thread=False option. Opening a database connection looks like this: conn = sqlite3.connect( 'file:filename.db?immutable=1', uri=True, check_same_thread=False, ) The following articles were helpful in figuring this out: * https://pymotw.com/3/asyncio/executors.html * https://marlinux.wordpress.com/2017/05/19/python-3-6-asyncio-sqlalchemy/ Closes #45. Refs #38.",2017-11-05T02:21:44Z,2017-11-05T02:21:44Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 1fc75809a6aa17860944b4cc3a4d7175cd53b1f4,"Refactored everything into a factory function I now call a factory function to construct the Sanic app: app = app_factory(files) This allows me to pass additional arguments to it, e.g. the files to serve. Also refactored my class-based views to accept jinja as an argument, e.g: app.add_route( TableView.as_view(jinja), '//' )",2017-11-05T02:13:44Z,2017-11-05T02:13:44Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 0ac8bbce2e73c0759ec48661a7b740d2c368b2a2,"Default subcommand is now serve Using click-default-group: https://github.com/click-contrib/click-default-group Also removed requirements.txt in favour of setup.py",2017-11-04T23:53:50Z,2017-11-04T23:53:50Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 edaa10587e60946e0c1935333f6b79553db33798,Configured Travis CI,2017-11-04T23:47:46Z,2017-11-04T23:47:46Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 be768f26d09fa060b1ca71785ff546dd572f3fbc,python setup.py test now runs the tests,2017-11-04T23:40:27Z,2017-11-04T23:40:27Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 2c625e31ed018f929223918240603bf2a80e665c,"Fixed bug on Row page with tables containing spaces We were attempting to run this SQL: select * from ""Order%20Details"" where ... On this page: http://0.0.0.0:8877/northwind-40d049b/Order%20Details/10250,41",2017-10-27T07:16:18Z,2017-10-27T07:16:18Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 1592fd0419f374de201926d3ba67fbf1522eed13,"Started work on cli, which also meant adding setup.py I'm using click, and click recommends using a setup.py - so I've added one of those. I also refactored code into a new datasite package. It's not quite deploying to now properly at the moment though - I seem to have messed up the path handling a bit. Also snuck in a new template for the ""Row"" view. Refs #40",2017-10-27T07:08:24Z,2017-10-27T07:08:24Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 2a9799bae651558a23ae5074edad7cc13ff0fbdc,"Implemented database summary on index page Closes #41",2017-10-27T04:05:13Z,2017-10-27T04:05:17Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 3cce63b59851495b6d9d38936356e21ea8fbad3a,"URL to allow direct database download It's just the database URL with .db on the end, e.g. /flights.db Closes #19",2017-10-25T15:19:32Z,2017-10-25T15:19:32Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 f1b0521810bbc467721e4dcc5a2ff1bf2a1ddbb8,Preserve .json through redirects,2017-10-25T15:01:22Z,2017-10-25T15:01:22Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 d94d4465d7e72e668122f81206397f4f20cf555b,"Double quote around column names This means filters still work even with column names that contain spaces",2017-10-25T14:47:20Z,2017-10-25T14:47:20Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 e55bc3b2fa6e1e8be7b7c1f5b6cb3764713b6faa,th align left for all tables,2017-10-25T14:46:38Z,2017-10-25T14:46:38Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 1c5977961f596dae5aaa18c8b2d7a10e9f42a543,Added glob and like lookups - refs #23,2017-10-25T01:53:01Z,2017-10-25T01:53:01Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 630b40038ef31b351abc2e39c3a0c7b3648814f8,"Added support for gt, gte, lt, lte lookups Refs #23",2017-10-25T01:46:49Z,2017-10-25T01:46:55Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 6823b094066c5cb1dcd3581da2ed877ed72298b7,"Set time limit of 1000ms on SQL queries Using the (undocumented in the Python docs) fact that if you return 1 from a set_progress_handler callback, SQLite will cancel the current query. Closes #35",2017-10-25T01:34:54Z,2017-10-25T01:34:54Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 2fe94641b0b2dc291d1fce3dad0fbf96294b3a32,"Don't try to show row counts for views Also handle tables/views with spaces in their name in the URL.",2017-10-25T01:33:12Z,2017-10-25T01:33:12Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 bd5f3b2ba1a627383d512d613b77d15501dfccc4,Show time taken at bottom of table page,2017-10-25T01:31:54Z,2017-10-25T01:31:54Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 3eb79e1a5fa4c164a224ae0adbe0ea16fde35758,Show total row count at top of table page,2017-10-25T01:31:43Z,2017-10-25T01:31:43Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 eef213ab4d57622dfc60c8655c0c7a18afcc844f,Show total number of rows in table,2017-10-25T00:11:36Z,2017-10-25T00:11:36Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 1ae8ea0f03cfb9f25b1e25f3194c456c3649789c,"Started implementing ?name__contains=X filters So far we support __contains=, __startswith=, __endswith= and __exact= Refs #23",2017-10-25T00:06:23Z,2017-10-25T00:06:23Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 4c7379a898df426af0c31159e5cb06d672189301,"Don't crash on weird character encodings Expecting SQLite columns to all be valid utf8 doesn't work, because we are deailing with all kinds of databases. Instead, we now use the 'replace' encoding mode to replace any non-UTF8 characters with a [X] character.",2017-10-25T00:01:34Z,2017-10-25T00:01:34Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 c371f06fdea413cfb00aa8f81b7a5535a7ecdbc4,Include took_ms in JSON output,2017-10-24T23:55:53Z,2017-10-24T23:55:53Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 2a09d3708777116daedc548078a662086552523f,Allow views to be browsed as well as tables,2017-10-24T23:55:08Z,2017-10-24T23:55:08Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 02b1814fcfdc61b1b69b5955f2b60252ff10cde9,"Redirects now preserve query string Fixes #28",2017-10-24T23:54:26Z,2017-10-24T23:54:26Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 5f806880c9766daf09fc9535171637ebb8224cab,Correctly JSON serialize sqlite3.Cursor,2017-10-24T23:53:21Z,2017-10-24T23:53:21Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 bc9379aabcedce7fbc661ac15008d8801199a045,"Added .jsono extension Returns JSON key/value objects for each row instead of lists of values. Closes #6",2017-10-24T15:07:52Z,2017-10-24T15:07:52Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 f643f7aee1b3d29df82b93a6560887a35b7a2f13,"base64 encode bytestrings from DB in JSON Fixes #29",2017-10-24T14:58:41Z,2017-10-24T14:58:41Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 b46e370ee6126aa2fa85cf789a31da38aed98496,"Link to pages-per-row Closes #1",2017-10-24T14:10:58Z,2017-10-24T14:10:58Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 6a9fdcc0718aea2cbc01ae4d60b9a1fba3601a66,"Added addressable page per row Refs #1 - only exists for tables with introspectable primary keys. Still need to link to this page. Also added first unit tests - refs #9",2017-10-24T05:54:58Z,2017-10-24T05:54:58Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 606ff9e35e007ae58a491d417f47779034bacabc,"python app.py --build to generate build-metadata.json This is now run by the Dockerfile to build this at compile time.",2017-10-24T05:53:13Z,2017-10-24T05:53:13Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 b20d7119e4f6506cdb9d5d11322e28130823adfd,Implemented template inheritance and brought back errors,2017-10-24T02:56:27Z,2017-10-24T02:56:27Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 0fa177269767e5e55c863382333fde627d2b7074,"Allow ?sql= argument against database e.g. /database-234324?sql=select * from table limit 1",2017-10-24T02:48:56Z,2017-10-24T02:48:56Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 255e2611e5c3cfdda76c9da7abdbe5af976044ac,"CORS headers for JSON responses Access-Control-Allow-Origin: *",2017-10-24T02:48:06Z,2017-10-24T02:48:06Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 12f7e1dc5624d14f644abead18bd90b420b6d97e,"Hashed URLs now have far-future cache expiry Since the URL now includes a hash of the database, we can return a Cache- Control: max-age=31536000 header for every response. The exception is our 302 redirects. These we now serve with a Link: header that tells any HTTP/2 server-push aware fronting proxies (such as Cloudfront) to push the target of the redirect. Closes #4",2017-10-24T02:36:44Z,2017-10-24T02:36:44Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 9d219140694551453bfa528e0624919eb065f9d6,"Refactored to use class based views Closes #22",2017-10-24T02:25:48Z,2017-10-24T02:25:48Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 b2372605d63248f422b6e67cb5c392236a3aa612,"Implemented multi-db support plus initial URL structure Refs #24 Fixes #15",2017-10-24T02:00:37Z,2017-10-24T02:00:37Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 6a0c5de6154893eb4269dc7b1f160726ec6395f2,"ensure_build_metadata() function for metadata This will be run at compile time - the goal is to generate a build- metadata.json file with a bunch of useful facts about the databases that could be expensive to generate at run-time. Example metadata: { ""flights"": { ""file"": ""flights.db"", ""tables"": { ""airlines"": 6048, ""airports"": 8107, ""routes"": 67663 }, ""hash"": ""07d1283e07786b1235bb7041ea445ae103d1571565580a29eab0203c555725fd"" } So far we have a sha256 hash of the database file itself, plus a row count for each table. Fixes #11",2017-10-23T16:02:40Z,2017-10-23T16:02:40Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 f571b19d8a5fd3a19fdf679421fd55a8edbf5295,"sqlerrors() decorator catching and returning useful errors Closes #8",2017-10-23T15:28:00Z,2017-10-23T15:28:00Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599 de04d7a854d71003ffcf98028eab976a936c2dba,Initial working proof of concept,2017-10-23T00:41:19Z,2017-10-23T00:41:19Z,2946d096d0cdefdc017559e6b57e87658736e843,2946d096d0cdefdc017559e6b57e87658736e843,107914493,9599,9599