Android SQLite not returning data for given search term - android-sqlite

I am trying to build a search interface but the SQLite database returns nothing here is the code for search function
public List<DiaryModel> searchData(String srchTerm){
List<DiaryModel> data2=new ArrayList<>();
SQLiteDatabase db1 = this.getWritableDatabase();
String sql="SELECT * FROM "+DB_TABLE+" WHERE "+KEY_HEADING+" LIKE '"+srchTerm+"%'";
Cursor cursor2 =db1.rawQuery(sql,null);
cursor2.moveToFirst();
StringBuilder stringBuffer2;
stringBuffer2 = new StringBuilder();
DiaryModel diaryModel2;
while (cursor2.moveToNext()){
diaryModel2 = new DiaryModel();
String heading = cursor2.getString(cursor2.getColumnIndexOrThrow("heading"));
String desc = cursor2.getString(cursor2.getColumnIndexOrThrow("desc_"));
diaryModel2.setHeading(heading);
diaryModel2.setDesc(desc);
stringBuffer2.append(diaryModel2);
data2.add(diaryModel2);
}
return data2;
}
but when I print everything the Database returns data, here is the code for get Data used for printing data present in Database
public List<DiaryModel> getdata(){
List<DiaryModel> data=new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor =db.rawQuery("SELECT * FROM diary_db", null);
cursor.moveToFirst();
StringBuilder stringBuffer = new StringBuilder();
DiaryModel diaryModel;
while (cursor.moveToNext()){
diaryModel = new DiaryModel();
String heading = cursor.getString(cursor.getColumnIndexOrThrow(KEY_HEADING));
String desc = cursor.getString(cursor.getColumnIndexOrThrow(KEY_DESC));
diaryModel.setHeading(heading);
diaryModel.setDesc(desc);
stringBuffer.append(diaryModel);
data.add(diaryModel);
}
return data
}
The thing is only this SQL statement is working
SELECT * FROM diary_db
and if any condition is put nothing returns.

There is something that you are doing wrong in both methods:
cursor.moveToFirst();
and then:
while (cursor.moveToNext()){
.................
}
This way you miss the 1st row of the results, because after you move the cursor to the 1st row, you move once again to the next row.
So delete this:
cursor.moveToFirst();
from both methods.

Related

cursor count is 1 whereas the table has 3 rows

I m trying to populate sql table and then retrieve data from it. Following is my code.
public void addQuestion(Question quest)
{
int id = 1;
ContentValues values = new ContentValues();
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUEST1);
onCreate(db);
values.put(KEY_QUES, quest.getQuestion());
values.put(KEY_ANSWER, quest.getAnswer());
values.put(KEY_OPTA, quest.getOptA());
values.put(KEY_OPTB, quest.getOptB());
values.put(KEY_OPTC, quest.getOptC());
db.insert(TABLE_QUEST1, null, values);
System.out.println("Added in database: " + quest.getQuestion());
}
public ArrayList<Question> getAllQuestions() {
System.out.println("getting rows 1");
ArrayList<Question> quesList = new ArrayList<Question>();
System.out.println("getting rows 2");
Cursor cursor = null;
SQLiteDatabase db = getReadableDatabase();
System.out.println("getting rows ");
cursor = db.rawQuery("SELECT * FROM " + TABLE_QUEST1, null);
if (!cursor.moveToFirst()) {
System.out.println("No data in the database ");
} else {
System.out.println("theres data in the database ");
quesList = new ArrayList<Question>();
do {
System.out.print("total rows " + cursor.getCount());
Question quest = new Question();
quest.setID(cursor.getInt(0));
quest.setQuestion(cursor.getString(1));
quest.setAnswer(cursor.getString(2));
quest.setOptA(cursor.getString(3));
quest.setOptB(cursor.getString(4));
quest.setOptC(cursor.getString(5));
quesList.add(quest);
} while (cursor.moveToNext());
cursor.close();
}
}
I have 4 rows of data in my table and I can see that with the print statement "added in database"
but when i actually read it the cursor just reads row 1 and moves out of the while loop. what could potentially be wrong.
tia
Your code was absolutely fine except placing drop command in the loop. As mentioned in the earlier comments, please make sure to avoid calling drop query each time and you'll find the result.
As Santosh has pointed out DROPPING the table (as per db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUEST1);) and then re-creating it (as per onCreate(db);) will delete the table and then re-create the table removing any rows/data that had previously been added to the table.
As such it's simply a matter of removing those two lines of code, Also there appears to be no need for the line int id = 1;, so perhaps remove this, as per :-
public void addQuestion(Question quest)
{
ContentValues values = new ContentValues();
SQLiteDatabase db = this.getWritableDatabase();
values.put(KEY_QUES, quest.getQuestion());
values.put(KEY_ANSWER, quest.getAnswer());
values.put(KEY_OPTA, quest.getOptA());
values.put(KEY_OPTB, quest.getOptB());
values.put(KEY_OPTC, quest.getOptC());
db.insert(TABLE_QUEST1, null, values);
System.out.println("Added in database: " + quest.getQuestion());
}
P.S. you may consider not using hard coded column offsets but instead obtain offsets according to column names by utilising the getColumnIndex(column_name) Cursor method. e.g. :-
Question quest = new Question();
quest.setID(cursor.getInt(cursor.getColumnIndex("name_of_your_id_columm")));
quest.setQuestion(cursor.getString(cursor.getColumnIndex(KEY_QUES)));
quest.setAnswer(cursor.getString(cursor.getColumnIndex(KEY_ANSWER)));
quest.setOptA(cursor.getString(cursor.getColumnIndex(KEY_OPTA)));
quest.setOptB(cursor.getString(cursor.getColumnIndex(KEY_OPTB)));
quest.setOptC(cursor.getString(cursor.getColumnIndex(KEY_OPTC)));
quesList.add(quest);
Noting that instead of "name_of_your_id_columm", you may have something like KEY_ID defined, if so use that, thus you have a single definition so it reduces the chance of inadvertently mispelling column names or miscalculating the offsets.

Linq query in stored procedure result set Ado.Net

I have a stored procedure with multiple joins, pulling all the data into a resultset I.e in dataset, now I want to write a linq query over it. How can I do that?
I am expecting:
IEnumerable<SomeType> result;
[where I need to know how the Properties of SomeType are defined.]
This is what I have tried but it does not look efficient.
SqlCommand cmd = new SqlCommand("Select top 10 * from trade");
cmd.Connection = con;
if (con.State != ConnectionState.Open)
{
con.Open();
}
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
var result = dt.AsEnumerable();
string valresukir = string.Empty;
var sortResult = result.OrderBy(x => Convert.ToInt32(x["trade_num"]) > 12);
string valuedata = string.Empty;
foreach (var i in sortResult)
{
valuedata += i["trade_num"].ToString();
}
to can write linq query on data table like
var data= from dataRow in dt.AsEnumerable()
where dataRow.Field<int>("trade_num") > 12
select dataRow
if trade_num is integer . Take it as a example and add your conditions accordingly.
Hope it will help you.

Postgres Insert query not working?

This the code. I have mentioned where the query stops. There is no error in the console too. What could be the problem. I am using postgres database. getting data from jsp servlet and passing to dao through servlet as string. But as my db has different format i want to convert the variables to their respective types. But i first want to check whether insert query works with dummy data. It seems that every thing is working fine but code flow stops where mentioned and there is no data inserted in my db also.
public void doInsert(Connection conn, String i, String nam,String indate, String amont, String tx, String tot,String closd, String shipvia, String not) throws Exception {
ResultSet rs = null;
ResultSet rs1 = null;
Statement st=null;
Statement st1=null;
// TODO Auto-generated method stub
try{
/* String in=indate;
String reverse = new StringBuffer(in).reverse().toString();
System.out.println(reverse);
System.out.println(reverse);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-dd");
String dateInString = indate;
Date date = sdf.parse(dateInString);
System.out.println(date);*/
/*String it=i;
String n=nam;
String in=indate;
String a=amont;
String t=tx;
String tota=tot;
String closed=closd;
String ship_via=shipvia;
String note=not;
to_date("+date+",'YYYY-MM-DD')*/
System.out.println("came above sql");
/*to_date("+date+",'YYYY-MM-DD')*/
String sql="insert into invheader(id,invdate,client_id,amount,tax,total,closed,ship_via,note) values(100001,to_date('1963-09-01', 'YYYY-MM-DD'),100001,100.00,20.00,120.00,TRUE,'tnt','note 1')";
//"insert into invheader(id,invdate,client_id,amount,tax,total,closed,ship_via,note) values('',to_date('1963-09-01', 'YYYY-MM-DD'),"+i+","+amont+","+tx+","+tot+","+closd+","+shipvia+","+not+")";
System.out.println("after 1st query");
String sql1="insert into clients(client_id,name) values("+i+","+nam+")";
System.out.println("after 2nd query");
st =conn.createStatement();
st1 =conn.createStatement();
//Statement stmt1 = conn.createStatement();//connection to statement
System.out.println("above execute"); //<======= code stops here
rs=st.executeQuery(sql);
System.out.println("above execute1");
rs1=st1.executeQuery(sql1);
System.out.println("inserted dao");
}catch(Exception e){
e.printStackTrace();
throw e;
}
// TODO Auto-generated method stub
}
Please help me. what could be the reason?

Returning a DataTable using Entity Framework ExecuteStoreQuery

I am working with a system that has many stored procedures that need to be displayed. Creating entities for each of my objects is not practical.
Is it possible and how would I return a DataTable using ExecuteStoreQuery ?
public ObjectResult<DataTable> MethodName(string fileSetName) {
using (var dataContext = new DataContext(_connectionString))
{
var returnDataTable = ((IObjectContextAdapter)dataContext).ObjectContext.ExecuteStoreQuery<DataTable>("SP_NAME","SP_PARAM");
return returnDataTable;
}
Yes it's possible, but it should be used for just dynamic result-set or raw SQL.
public DataTable ExecuteStoreQuery(string commandText, params Object[] parameters)
{
DataTable retVal = new DataTable();
retVal = context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
return retVal;
}
Edit: It's better to use classical ADO.NET to get the data model rather than using Entity Framework because most probably you cannot use DataTable even if you can run the method: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
ADO.NET Example:
public DataSet GetResultReport(int questionId)
{
DataSet retVal = new DataSet();
EntityConnection entityConn = (EntityConnection)context.Connection;
SqlConnection sqlConn = (SqlConnection)entityConn.StoreConnection;
SqlCommand cmdReport = new SqlCommand([YourSpName], sqlConn);
SqlDataAdapter daReport = new SqlDataAdapter(cmdReport);
using (cmdReport)
{
SqlParameter questionIdPrm = new SqlParameter("QuestionId", questionId);
cmdReport.CommandType = CommandType.StoredProcedure;
cmdReport.Parameters.Add(questionIdPrm);
daReport.Fill(retVal);
}
return retVal;
}
No, I don't think that'll work - Entity Framework is geared towards returning entities and isn't meant to return DataTable objects.
If you need DataTable objects, use straight ADO.NET instead.
This method uses the connection string from the entity framework to establish an ADO.NET connection, to a MySQL database in this example.
using MySql.Data.MySqlClient;
public DataSet GetReportSummary( int RecordID )
{
var context = new catalogEntities();
DataSet ds = new DataSet();
using ( MySqlConnection connection = new MySqlConnection( context.Database.Connection.ConnectionString ) )
{
using ( MySqlCommand cmd = new MySqlCommand( "ReportSummary", connection ) )
{
MySqlDataAdapter adapter = new MySqlDataAdapter( cmd );
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.Add( new MySqlParameter( "#ID", RecordID ) );
adapter.Fill( ds );
}
}
return ds;
}
Yes it can easily be done like this:
var table = new DataTable();
using (var ctx = new SomeContext())
{
var cmd = ctx.Database.Connection.CreateCommand();
cmd.CommandText = "Select Col1, Col2 from SomeTable";
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
}
By the rule, you shouldn't use a DataSet inside a EF application. But, if you really need to (for instance, to feed a report), that solution should work (it's EF 6 code):
DataSet GetDataSet(string sql, CommandType commandType, Dictionary<string, Object> parameters)
{
// creates resulting dataset
var result = new DataSet();
// creates a data access context (DbContext descendant)
using (var context = new MyDbContext())
{
// creates a Command
var cmd = context.Database.Connection.CreateCommand();
cmd.CommandType = commandType;
cmd.CommandText = sql;
// adds all parameters
foreach (var pr in parameters)
{
var p = cmd.CreateParameter();
p.ParameterName = pr.Key;
p.Value = pr.Value;
cmd.Parameters.Add(p);
}
try
{
// executes
context.Database.Connection.Open();
var reader = cmd.ExecuteReader();
// loop through all resultsets (considering that it's possible to have more than one)
do
{
// loads the DataTable (schema will be fetch automatically)
var tb = new DataTable();
tb.Load(reader);
result.Tables.Add(tb);
} while (!reader.IsClosed);
}
finally
{
// closes the connection
context.Database.Connection.Close();
}
}
// returns the DataSet
return result;
}
In my Entity Framework based solution I need to replace one of my Linq queries with sql - for efficiency reasons.
Also I want my results in a DataTable from one stored procedure so that I could create a table value parameter to pass into a second stored procedure. So:
I'm using sql
I don't want a DataSet
Iterating an IEnumerable probably isn't going to cut it - for efficiency reasons
Also, I am using EF6, so I would prefer DbContext.SqlQuery over ObjectContext.ExecuteStoreQuery as the original poster requested.
However, I found that this just didn't work:
_Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
This is my solution. It returns a DataTable that is fetched using an ADO.NET SqlDataReader - which I believe is faster than a SqlDataAdapter on read-only data. It doesn't strictly answer the question because it uses ADO.Net, but it shows how to do that after getting a hold of the connection from the DbContext
protected DataTable GetDataTable(string sql, params object[] parameters)
{
//didn't work - table had no columns or rows
//return Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
DataTable result = new DataTable();
SqlConnection conn = Context.Database.Connection as SqlConnection;
if(conn == null)
{
throw new InvalidCastException("SqlConnection is invalid for this database");
}
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddRange(parameters);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
result.Load(reader);
}
return result;
}
}
The easiest way to return a DataTable using the EntityFramework is to do the following:
MetaTable metaTable = Global.DefaultModel.GetTable("Your EntitySetName");
For example:
MetaTable metaTable = Global.DefaultModel.GetTable("Employees");
Maybe your stored procedure could return a complex type?
http://blogs.msdn.com/b/somasegar/archive/2010/01/11/entity-framework-in-net-4.aspx

using the TSqlParser

I'm attempting to parse SQL using the TSql100Parser provided by microsoft. Right now I'm having a little trouble using it the way it seems to be intended to be used. Also, the lack of documentation doesn't help. (example: http://msdn.microsoft.com/en-us/library/microsoft.data.schema.scriptdom.sql.tsql100parser.aspx )
When I run a simple SELECT statement through the parser it returns a collection of TSqlStatements which contains a SELECT statement.
Trouble is, the TSqlSelect statement doesn't contain attributes such as a WHERE clause, even though the clause is implemented as a class. http://msdn.microsoft.com/en-us/library/microsoft.data.schema.scriptdom.sql.whereclause.aspx
The parser does recognise the WHERE clause as such, looking at the token stream.
So, my question is, am I using the parser correctly? Right now the token stream seems to be the most useful feature of the parser...
My Test project:
public static void Main(string[] args)
{
var parser = new TSql100Parser(false);
IList<ParseError> Errors;
IScriptFragment result = parser.Parse(
new StringReader("Select col from T1 where 1 = 1 group by 1;" +
"select col2 from T2;" +
"select col1 from tbl1 where id in (select id from tbl);"),
out Errors);
var Script = result as TSqlScript;
foreach (var ts in Script.Batches)
{
Console.WriteLine("new batch");
foreach (var st in ts.Statements)
{
IterateStatement(st);
}
}
}
static void IterateStatement(TSqlStatement statement)
{
Console.WriteLine("New Statement");
if (statement is SelectStatement)
{
PrintStatement(sstmnt);
}
}
Yes, you are using the parser correctly.
As Damien_The_Unbeliever points out, within the SelectStatement there is a QueryExpression property which will be a QuerySpecification object for your third select statement (with the WHERE clause).
This represents the 'real' SELECT bit of the query (whereas the outer SelectStatement object you are looking at has just got the 'WITH' clause (for CTEs), 'FOR' clause (for XML), 'ORDER BY' and other bits)
The QuerySpecification object is the object with the FromClauses, WhereClause, GroupByClause etc.
So you can get to your WHERE Clause by using:
((QuerySpecification)((SelectStatement)statement).QueryExpression).WhereClause
which has a SearchCondition property etc. etc.
Quick glance around would indicate that it contains a QueryExpression, which could be a QuerySpecification, which does have the Where clause attached to it.
if someone lands here and wants to know how to get the whole elements of a select statement the following code explain that:
QuerySpecification spec = (QuerySpecification)(((SelectStatement)st).QueryExpression);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Select Elements");
foreach (var elm in spec.SelectElements)
sb.Append(((Identifier)((Column)((SelectColumn)elm).Expression).Identifiers[0]).Value);
sb.AppendLine();
sb.AppendLine("From Elements");
foreach (var elm in spec.FromClauses)
sb.Append(((SchemaObjectTableSource)elm).SchemaObject.BaseIdentifier.Value);
sb.AppendLine();
sb.AppendLine("Where Elements");
BinaryExpression binaryexp = (BinaryExpression)spec.WhereClause.SearchCondition;
sb.Append("operator is " + binaryexp.BinaryExpressionType);
if (binaryexp.FirstExpression is Column)
sb.Append(" First exp is " + ((Identifier)((Column)binaryexp.FirstExpression).Identifiers[0]).Value);
if (binaryexp.SecondExpression is Literal)
sb.Append(" Second exp is " + ((Literal)binaryexp.SecondExpression).Value);
I had to split a SELECT statement into pieces. My goal was to COUNT how many record a query will return. My first solution was to build a sub query such as
SELECT COUNT(*) FROM (select id, name from T where cat='A' order by id) as QUERY
The problem was that in this case the order clause raises the error "The ORDER BY clause is not valid in views, inline functions, derived tables, sub-queries, and common table expressions, unless TOP or FOR XML is also specified"
So I built a parser that split a SELECT statment into fragments using the TSql100Parser class.
using Microsoft.Data.Schema.ScriptDom.Sql;
using Microsoft.Data.Schema.ScriptDom;
using System.IO;
...
public class SelectParser
{
public string Parse(string sqlSelect, out string fields, out string from, out string groupby, out string where, out string having, out string orderby)
{
TSql100Parser parser = new TSql100Parser(false);
TextReader rd = new StringReader(sqlSelect);
IList<ParseError> errors;
var fragments = parser.Parse(rd, out errors);
fields = string.Empty;
from = string.Empty;
groupby = string.Empty;
where = string.Empty;
orderby = string.Empty;
having = string.Empty;
if (errors.Count > 0)
{
var retMessage = string.Empty;
foreach (var error in errors)
{
retMessage += error.Identifier + " - " + error.Message + " - position: " + error.Offset + "; ";
}
return retMessage;
}
try
{
// Extract the query assuming it is a SelectStatement
var query = ((fragments as TSqlScript).Batches[0].Statements[0] as SelectStatement).QueryExpression;
// Constructs the From clause with the optional joins
from = (query as QuerySpecification).FromClauses[0].GetString();
// Extract the where clause
where = (query as QuerySpecification).WhereClause.GetString();
// Get the field list
var fieldList = new List<string>();
foreach (var f in (query as QuerySpecification).SelectElements)
fieldList.Add((f as SelectColumn).GetString());
fields = string.Join(", ", fieldList.ToArray());
// Get The group by clause
groupby = (query as QuerySpecification).GroupByClause.GetString();
// Get the having clause of the query
having = (query as QuerySpecification).HavingClause.GetString();
// Get the order by clause
orderby = ((fragments as TSqlScript).Batches[0].Statements[0] as SelectStatement).OrderByClause.GetString();
}
catch (Exception ex)
{
return ex.ToString();
}
return string.Empty;
}
}
public static class Extension
{
/// <summary>
/// Get a string representing the SQL source fragment
/// </summary>
/// <param name="statement">The SQL Statement to get the string from, can be any derived class</param>
/// <returns>The SQL that represents the object</returns>
public static string GetString(this TSqlFragment statement)
{
string s = string.Empty;
if (statement == null) return string.Empty;
for (int i = statement.FirstTokenIndex; i <= statement.LastTokenIndex; i++)
{
s += statement.ScriptTokenStream[i].Text;
}
return s;
}
}
And to use this class simply:
string fields, from, groupby, where, having, orderby;
SelectParser selectParser = new SelectParser();
var retMessage = selectParser.Parse("SELECT * FROM T where cat='A' Order by Id desc",
out fields, out from, out groupby, out where, out having, out orderby);