Skip to content

Support for joins partially done #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions debug-db/src/main/assets/custom.css
Original file line number Diff line number Diff line change
@@ -55,4 +55,10 @@
@-webkit-keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}

textarea.form-control#query {
resize: vertical;
min-height: 100px;
font-family: monospace;
}
2 changes: 1 addition & 1 deletion debug-db/src/main/assets/index.html
Original file line number Diff line number Diff line change
@@ -116,7 +116,7 @@
<div class="col-sm-12">
<div class="form-group">
<label for="query">Query</label>
<input class="form-control" id="query">
<textarea class="form-control" id="query"></textarea>
</div>
<button id="selected-db-info" type="button" onclick="downloadDb()" class="btn btn-info">
Welcome
Original file line number Diff line number Diff line change
@@ -230,7 +230,7 @@ private String getAllDataFromTheTableResponse(String route) {

if (isDbOpened) {
String sql = "SELECT * FROM " + tableName;
response = DatabaseHelper.getTableData(sqLiteDB, sql, tableName);
response = DatabaseHelper.getTableData(sqLiteDB, sql, new String[]{tableName});
} else {
response = PrefHelper.getAllPrefData(mContext, tableName);
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.util.Log;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only an (unused) import statement was added in this file. It would be good to remove it again before the merge ;)


import net.sqlcipher.database.SQLiteDatabase;

239 changes: 132 additions & 107 deletions debug-db/src/main/java/com/amitshekhar/utils/DatabaseHelper.java
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import com.amitshekhar.model.Response;
import com.amitshekhar.model.RowDataRequest;
@@ -30,6 +31,8 @@
import com.amitshekhar.sqlite.SQLiteDB;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

@@ -62,109 +65,115 @@ public static Response getAllTableName(SQLiteDB database) {
return response;
}

public static TableDataResponse getTableData(SQLiteDB db, String selectQuery, String tableName) {
public static TableDataResponse getTableData(SQLiteDB db, String selectQuery, String[] tableNames) {

TableDataResponse tableData = new TableDataResponse();
tableData.isSelectQuery = true;
if (tableName == null) {
tableName = getTableName(selectQuery);
if (tableNames == null) {
tableNames = getTableNames(selectQuery);
}

final String quotedTableName = getQuotedTableName(tableName);

if (tableName != null) {
final String pragmaQuery = "PRAGMA table_info(" + quotedTableName + ")";
tableData.tableInfos = getTableInfo(db, pragmaQuery);
}
Cursor cursor = null;
boolean isView = false;
try {
cursor = db.rawQuery("SELECT type FROM sqlite_master WHERE name=?",
new String[]{quotedTableName});
if (cursor.moveToFirst()) {
isView = "view".equalsIgnoreCase(cursor.getString(0));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
tableData.isEditable = tableName != null && tableData.tableInfos != null && !isView;


if (!TextUtils.isEmpty(tableName)) {
selectQuery = selectQuery.replace(tableName, quotedTableName);
}

try {
cursor = db.rawQuery(selectQuery, null);
} catch (Exception e) {
e.printStackTrace();
tableData.isSuccessful = false;
tableData.errorMessage = e.getMessage();
return tableData;
}

if (cursor != null) {
cursor.moveToFirst();

// setting tableInfo when tableName is not known and making
// it non-editable also by making isPrimary true for all
if (tableData.tableInfos == null) {
tableData.tableInfos = new ArrayList<>();
for (int i = 0; i < cursor.getColumnCount(); i++) {
TableDataResponse.TableInfo tableInfo = new TableDataResponse.TableInfo();
tableInfo.title = cursor.getColumnName(i);
tableInfo.isPrimary = true;
tableData.tableInfos.add(tableInfo);
}
}

tableData.isSuccessful = true;
tableData.rows = new ArrayList<>();
if (cursor.getCount() > 0) {

do {
List<TableDataResponse.ColumnData> row = new ArrayList<>();
for (int i = 0; i < cursor.getColumnCount(); i++) {
TableDataResponse.ColumnData columnData = new TableDataResponse.ColumnData();
switch (cursor.getType(i)) {
case Cursor.FIELD_TYPE_BLOB:
columnData.dataType = DataType.TEXT;
columnData.value = ConverterUtils.blobToString(cursor.getBlob(i));
break;
case Cursor.FIELD_TYPE_FLOAT:
columnData.dataType = DataType.REAL;
columnData.value = cursor.getDouble(i);
break;
case Cursor.FIELD_TYPE_INTEGER:
columnData.dataType = DataType.INTEGER;
columnData.value = cursor.getLong(i);
break;
case Cursor.FIELD_TYPE_STRING:
columnData.dataType = DataType.TEXT;
columnData.value = cursor.getString(i);
break;
default:
columnData.dataType = DataType.TEXT;
columnData.value = cursor.getString(i);
}
row.add(columnData);
}
tableData.rows.add(row);

} while (cursor.moveToNext());
}
cursor.close();
return tableData;
} else {
tableData.isSuccessful = false;
tableData.errorMessage = "Cursor is null";
return tableData;
}


String tableName = null;
if( tableNames != null && tableNames.length == 1 )
{
tableName = tableNames[0];
}

final String quotedTableName = getQuotedTableName(tableName);

if (tableName != null) {
final String pragmaQuery = "PRAGMA table_info(" + quotedTableName + ")";
tableData.tableInfos = getTableInfo(db, pragmaQuery);
}
Cursor cursor = null;
boolean isView = false;
try {
cursor = db.rawQuery("SELECT type FROM sqlite_master WHERE name=?",
new String[]{quotedTableName});
if (cursor.moveToFirst()) {
isView = "view".equalsIgnoreCase(cursor.getString(0));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
tableData.isEditable = tableName != null && tableData.tableInfos != null && !isView;


if (!TextUtils.isEmpty(tableName)) {
selectQuery = selectQuery.replace(tableName, quotedTableName);
}

try {
Log.v( "DATABASE", selectQuery );
cursor = db.rawQuery(selectQuery, null);
} catch (Exception e) {
e.printStackTrace();
tableData.isSuccessful = false;
tableData.errorMessage = e.getMessage();
return tableData;
}

if (cursor != null) {
cursor.moveToFirst();

// setting tableInfo when tableName is not known and making
// it non-editable also by making isPrimary true for all
if (tableData.tableInfos == null) {
tableData.tableInfos = new ArrayList<>();
for (int i = 0; i < cursor.getColumnCount(); i++) {
TableDataResponse.TableInfo tableInfo = new TableDataResponse.TableInfo();
tableInfo.title = cursor.getColumnName(i);
tableInfo.isPrimary = true;
tableData.tableInfos.add(tableInfo);
}
}

tableData.isSuccessful = true;
tableData.rows = new ArrayList<>();
if (cursor.getCount() > 0) {

do {
List<TableDataResponse.ColumnData> row = new ArrayList<>();
for (int i = 0; i < cursor.getColumnCount(); i++) {
TableDataResponse.ColumnData columnData = new TableDataResponse.ColumnData();
switch (cursor.getType(i)) {
case Cursor.FIELD_TYPE_BLOB:
columnData.dataType = DataType.TEXT;
columnData.value = ConverterUtils.blobToString(cursor.getBlob(i));
break;
case Cursor.FIELD_TYPE_FLOAT:
columnData.dataType = DataType.REAL;
columnData.value = cursor.getDouble(i);
break;
case Cursor.FIELD_TYPE_INTEGER:
columnData.dataType = DataType.INTEGER;
columnData.value = cursor.getLong(i);
break;
case Cursor.FIELD_TYPE_STRING:
columnData.dataType = DataType.TEXT;
columnData.value = cursor.getString(i);
break;
default:
columnData.dataType = DataType.TEXT;
columnData.value = cursor.getString(i);
}
row.add(columnData);
}
tableData.rows.add(row);

} while (cursor.moveToNext());
}
cursor.close();
return tableData;
} else {
tableData.isSuccessful = false;
tableData.errorMessage = "Cursor is null";
return tableData;
}
}


@@ -183,7 +192,6 @@ private static List<TableDataResponse.TableInfo> getTableInfo(SQLiteDB db, Strin
}

if (cursor != null) {

List<TableDataResponse.TableInfo> tableInfoList = new ArrayList<>();

cursor.moveToFirst();
@@ -367,11 +375,14 @@ public static TableDataResponse exec(SQLiteDB database, String sql) {
tableDataResponse.isSelectQuery = false;
try {

String tableName = getTableName(sql);
String[] tableNames = getTableNames(sql);

if (!TextUtils.isEmpty(tableName)) {
String quotedTableName = getQuotedTableName(tableName);
sql = sql.replace(tableName, quotedTableName);
if (tableNames == null) {
for( int i = 0; i < tableNames.length; i++ )
{
String quotedTableName = getQuotedTableName( tableNames[i] );
sql = sql.replace( tableNames[i], quotedTableName );
}
}

database.execSQL(sql);
@@ -385,18 +396,32 @@ public static TableDataResponse exec(SQLiteDB database, String sql) {
return tableDataResponse;
}

private static String getTableName(String selectQuery) {
private static String[] getTableNames( String selectQuery) {
// TODO: Handle JOIN Query
TableNameParser tableNameParser = new TableNameParser(selectQuery);
HashSet<String> tableNames = (HashSet<String>) tableNameParser.tables();

ArrayList<String> list = new ArrayList<>();
for (String tableName : tableNames) {
if (!TextUtils.isEmpty(tableName)) {
return tableName;
list.add( tableName );
}
}

return null;
if( list.size() > 0 )
{
Collections.sort( list, new java.util.Comparator<String>() {
@Override
public int compare(String s1, String s2) {
// TODO: Argument validation (nullity, length)
return s2.length() - s1.length();// comparision
}
} );

return list.toArray( new String[list.size()] );
}
else
return null;
}

}
25 changes: 25 additions & 0 deletions debug-db/src/main/java/com/amitshekhar/utils/TableNameParser.java
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@
*/
package com.amitshekhar.utils;

import android.util.Log;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -74,6 +76,7 @@ public TableNameParser(final String sql) {
String normalized = normalized(nocomments);
String cleansed = clean(normalized);
String[] tokens = cleansed.split(REGEX_SPACE);

int index = 0;

String firstToken = tokens[index];
@@ -87,6 +90,8 @@ public TableNameParser(final String sql) {

if (isFromToken(currentToken)) {
processFromToken(tokens, index);
} else if (isJoinToken(currentToken)) {
processJoinToken( tokens, index );
} else if (shouldProcess(currentToken)) {
String nextToken = tokens[index++];
considerInclusion(nextToken);
@@ -192,6 +197,10 @@ private boolean shouldProcess(final String currentToken) {
private boolean isFromToken(final String currentToken) {
return KEYWORD_FROM.equals(currentToken.toLowerCase());
}

private boolean isJoinToken(final String currentToken) {
return KEYWORD_JOIN.equals(currentToken.toLowerCase());
}

private void processFromToken(final String[] tokens, int index) {
String currentToken = tokens[index++];
@@ -208,6 +217,22 @@ private void processFromToken(final String[] tokens, int index) {
processAliasedMultiTables(tokens, index, currentToken);
}
}

private void processJoinToken(final String[] tokens, int index) {
String currentToken = tokens[index++];
considerInclusion(currentToken);

String nextToken = null;
if (moreTokens(tokens, index)) {
nextToken = tokens[index++];
}

if (shouldProcessMultipleTables(nextToken)) {
processNonAliasedMultiTables(tokens, index, nextToken);
} else {
processAliasedMultiTables(tokens, index, currentToken);
}
}

private void processNonAliasedMultiTables(final String[] tokens, int index, String nextToken) {
while (nextToken.equals(TOKEN_COMMA)) {