Saturday, March 18, 2017

SELECT LIKE FROM LIKE WHERE LIKE LIKE LIKE

SQLite documentation clearly says about not using keywords as the names of named objects.  For example, using a keyword as a table name

CREATE TABLE UNIQUE (
    a TEXT
);

leads to the following syntax error:

Error while executing SQL query on database 'provider': near "UNIQUE": syntax error

But this is not true for all keywords.  Let's try LIKE as a table name:

CREATE TABLE LIKE (
    a TEXT
);

No error, the table is created.  Let's try LIKE as a column name:

CREATE TABLE LIKE (
    LIKE TEXT
);

No problem.

INSERT INTO LIKE (LIKE) VALUES('LIKE');

Also works.  And now is the best example:

SELECT LIKE FROM LIKE WHERE LIKE LIKE LIKE;

Compiles, runs and returns correct results.  You don't even need to put quotes around the last LIKE.


Friday, March 17, 2017

Making Antlr4 fail on a syntax error

When Antlr4 encounter a syntax error, it emits an error message and then attempts to recover and continue parsing.  This default strategy is good for normal use but does not work for unit testing where we want the parser to throw an exception on syntax error so that the unit test actually fails.

To make Antlr4 fail on syntax error, we need to extend BaseErrorListener as follows:

class FailingErrorListener extends BaseErrorListener {
    @Override
    public void syntaxError(Recognizer<?, ?> recognizer,
            Object offendingSymbol, int line,
            int charPositionInLine, String msg,
            RecognitionException e)
            throws ParseCancellationException {
        throw new ParseCancellationException("line " + line + 
            ":" + charPositionInLine + " " + msg);
    }
}

Then, we need to add this error listener to both a lexer and a parser:

final ANTLRInputStream input = new ANTLRInputStream(stream);
final FailingErrorListener errorListener = new FailingErrorListener();

final MyLexer lexer = new MyLexer(input);
lexer.removeErrorListeners();
lexer.addErrorListener(errorListener);

final CommonTokenStream tokens = new CommonTokenStream(lexer);

final MyParser parser = new MyParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(errorListener);

After these changes the parser starts failing on as soon as it encounters a syntax error.

Wednesday, March 15, 2017

One of the 'BEST' markdown preview extensions for Atom

By default Atom editor comes with markdown-preview package which, unfortunately, does not handle relative references: you cannot click on a relative reference inside Atom editor to verify that it works.
 
Luckily, there is markdown-preview-enhanced package that deals with relative references without problems.  The package description says "One of the 'BEST' markdown preview extensions for Atom editor!", and this is not an exaggeration.

Sunday, March 12, 2017

Forwarding GoDaddy domain to Google app engine

If you purchased your domain through GoDaddy and want to forward its traffic to an application hosted on Google App Engine, don't start at GoDaddy domains settings, it'll just complicate the process.

Start at Google cloud console. Here is a link to the only instructions you need. The process is simple: Click Add Custom Domain under  {my app} -> App Engine -> Settings -> Custom Domains and follow the prompts.  Google will verify that you own the domain and then allow you to configure domain forwarding.  After configuration is saved, it'll take up to 24 hours for the changes to take effect, but it's usually faster than that.

At this point sub-domain forwarding should work.  To forward your naked domain, you need to login to GoDaddy, go to My Account -> Domains -> {domain name} -> DNS Zone File and add all A and AAAA records listed on Google cloud console.  Use @ as a host name when adding the records. Give it some time before testing.  In my case it took about 5 minutes for the changes to take effect, but it may take longer.

Saturday, March 11, 2017

Deploying a Polymer app to Google App Engine

The steps that are required to deploy a Polymer app to Google App Engine are documented and there is no need to repeat them here.  However, some changes are required to make everything work end to end.

First, polymer build command creates an unbundled output and places it to build/default folder. GAE seems to serve resources via HTTP/2 with server push just fine, so there is no need to create create a bundled output.

Second, since all output files by default are in build/default folder, you need to change static_files in app.yaml file  from build/bundled/... to build/default/....  Another option is to simply rename build/default folder to build/bundled folder.

Third, appcfg.py -A {project name} update app.yaml will more likely fail.  I had to add --oauth2 option for deployment to succeed:  appcfg.py --oauth2 -A {project name} update app.yaml

Wednesday, March 8, 2017

Tips to reduce mobile data usage

After switching to Project Fi, I started tracking my mobile data usage.  Below is the summary of what I've done so far to reduce my bills.

Google Play Music

Turn on Stream only on Wi-Fi in Settings
If you want to stream over mobile network, set Quality on mobile network to Low.

YouTube

Turn on Limit mobile data usage in Settings -> General.  This will only stream HD videos on Wi-Fi.

Google Photos

Turn off Cellular data back up in Settings -> Back up & sync

Google Play

In Settings (General) set Auto-update apps to Auto-update apps over Wi-Fi only. 

Google Plus

Turn on Conserve data usage in Settings (General)

Google Maps

Turn on Wi-Fi only in Settings.  Click on your offline areas link and save the area around your home.  Google Maps can save areas larger than a half of the state of Washington in size.

I'll update this post when I learn about other apps that consume a lot of data.  Project Fi app reports data usage per app, so it's easy to track apps that abuse mobile data.

Friday, March 3, 2017

Using CKEditor in WebView on Android

CKEditor is a powerful rich text editor for web applications.  This post shows how to integrate the editor into an Android application and load a sample page into a WebView.

  1. Download CKEditor.
  2. Unpack Zip file and move ckeditor folder to $project.projectDir/src/main/assets folder.
  3. Create a WebView in your layout file.
  4. After inflating the layout file, find WebView and enable JavaScript: webView.getSettings().setJavaScriptEnabled(true);
  5. Load sample app into the WebView: webView.loadUrl("file:///android_asset/ckeditor/samples/index.html");
When the application is launched, it'll look something like this:




Thursday, March 2, 2017

Loading WebView from a resource file on Android

This pattern worked for me:

final Uri uri = Uri.parse("file:///android_res/raw/maptest");
webView.loadUrl(uri.toString());

where maptest.html is a file in res/raw folder.  Replacing maptest with maptest.html also works.

The following works to load a file from assets directory:

final Uri uri = Uri.parse("file:///android_asset/maptest.html");
webView.loadUrl(uri.toString());

Note the use of .html extension when loading from assets directory.  When the extension is removed from the URI, the file won't load.