select rows between two dates in sqlite using java - sqlite

select rows between two dates in sqlite using java.
When i try to retrieve rows between to two dates from sqlite database in javafx program i always get one row from the whole rows even if there is multiple rows it select the first row and discard the remaining or not included in the result set at all, how can solve this problem and again the database has some records but the query always return the first one
#FXML
private void report(ActionEvent event)
{
if(searchfromDate.getValue() != null && searchToDate.getValue() != null)
{
try
{
DBconnector.connect();
LocalDate startDate = searchfromDate.getValue();
LocalDate endDate = searchToDate.getValue();
String query = "select * from selled where date between '" + startDate
+ "' and '" + endDate + "'";
ResultSet rs = DBconnector.query(query);
Alert alert = new Alert(AlertType.INFORMATION);
JSONObject file = new JSONObject();
if(rs.next())
{
int id = rs.getInt("id");
String customer = rs.getString("costomer");
String name = rs.getString("name");
String barcode = rs.getString("barcode");
int amount = rs.getInt("amount");
LocalDate date = LocalDate.parse(rs.getString("date"));
double price = rs.getDouble("price");
String garentee = rs.getString("garentee");
file.put("id", id);
file.put("customer", customer);
file.put("name", name);
file.put("barcode", barcode);
file.put("amount", amount);
file.put("date", date);
file.put("price", price);
file.put("garentee", garentee);
}
FileWriter writer = new FileWriter("تقرير المبيعات.json");
writer.write(file.toString());
writer.flush();
writer.close();
alert.setTitle("رسالة تاكيد");
alert.setHeaderText(null);
alert.setContentText("تم استخراج الملف بنجاح");
alert.showAndWait();
Desktop desktop = Desktop.getDesktop();
desktop.browse(new URI("https://arabsefr.com/save-report?fbclid=IwAR2ON1Tl8ETQ--3QEAVFJLMjTuWUhpLCZrD3PXhg8TZpdlUH4umKBfl78OM"));
}
catch (Exception ex)
{
System.out.println(ex);
}
}
else
{
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("رسالة تاكيد");
alert.setHeaderText(null);
alert.setContentText("لم يتم تحديد التاريخ");
alert.showAndWait();
}
}

When you are using SQLite, use of strftime() method is always recommended while manipulating with dates this makes sure that future troubles are avoided.
WHERE strftime('%s', date) between strftime('%s', startDate) and strftime('%s', endDate)

Related

JavaFX delete datarow in tableview and sqlite

I would like to delete a row in tableview but also in the
underlying SQLite Database which populate the tableview
Here I get the selectedRow
public void deleteDBRow() {
if (tableV.getSelectionModel().getSelectedItem() != null) {
Bew selBew = tableV.getSelectionModel().getSelectedItem();
System.out.println(selBew.getName());
}
}
and can delete it with casual code
DELETE FROM Table WHERE name = ""+selBew.getName()");
But I would like to delete the entry in the sqlite database also
From time to time I have rows with the same text in every column - so this way
was critical - can I use rowID to delete the selected row in sqlite?
Here one try from me to get rowid in tableview
ObservableList bewList = FXCollections.observableArrayList();
try {
String sql = "SELECT rowID, Name, Date, Action, Info FROM tab1";
Connection conn = DriverManager.getConnection("jdbc:sqlite:TestB1.db");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
bewList.add(new Bew(rs.getInt("rowID"), rs.getString("name"), rs.getString("date"),
rs.getString("action"), rs.getString("Info")));
System.out.println("rs.next : " + rs.getInt("rowID") +" - " + rs.getString("date") +" " +
rs.getString("action") +" " + rs.getString("Info"));
}
}catch (Exception e) {
System.out.println("SQLiteDB.getData ---> Error RS");
System.err.println("*E"+e.getClass().getName() + ": " + e.getMessage());
}
return bewList;
String sql = "CREATE TABLE IF NOT EXISTS tab1" +
"(rowID INT PRIMARY KEY," +
"NAME CHAR(50) NOT NULL ,"+
"DATE CHAR(15) ,"+
"ACTION CHAR(50) ,"+
"INFO CHAR(3));";
conn.createStatement().executeUpdate(sql);
rowID ist always 0 - don't know why ???
edit:
Controller
ObservableList bewList = DB.getData();
tableV.setItems(bewList);
Edit:
Maybe error in here - add data
i add 4 values - rowid missing??
public void add(String Name, String Date, String Action, String Info) {
try {
Connection conn = DriverManager.getConnection("jdbc:sqlite:TestB2.db");
stmt = conn.createStatement();
String ValStr = "\'"+Name+"\' ,\'"+Date+"\',\'"+Action+"\' ,\'"+Info+"\'";
String sql = "INSERT INTO tab1 (rowID, NAME,DATE,ACTION, INFO) VALUES ("+ValStr+")";
// System.out.println("Button Click add"+conn.createStatement().toString());
stmt.executeUpdate(sql); //geändert
ObservableList<Bew> list = getData();
conn.close();
System.out.println("DB ROW add");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}

SQLite test if record exists

I am struggling with testing if there is specific data in my SQLite database.
The method accepts a subject code, person id, and a table name. I am 100% sure those 3 things are correct.
What this should do is try to select a record. If the record can be selected return -1, otherwise return 0.
My problem is the datareader does not seem to be reading any records, when there is records in my database.
public int TestIfExists(string subID, string personID, string table)
{
_sqlConnection = new SQLiteConnection(_conStr);
bool dataRead = false;
int rc = 0;
try
{
string selectQuery = "SELECT * FROM " + table + " WHERE PersonID = '" +
personID + "' AND SubjectCode = '" + subID + "'";
_sqlConnection.Open();
SQLiteCommand sqlCommand = new SQLiteCommand(selectQuery, _sqlConnection);
IDataReader idr = sqlCommand.ExecuteReader();
dataRead = idr.Read();
if (dataRead == true)
{
rc = -1;
}//end if
else
{
rc = 0;
}//end else
idr.Close(); // Closed IDataReader
}//end try
catch (SQLiteException sqlEx) // Catch SQLiteException
{
MessageBox.Show(sqlEx.ToString());
throw new DataStoreError(sqlEx.Message);
}//end catch
catch (Exception ex)
{
throw ex;
}//end catch
finally
{
_sqlConnection.Close();
}//end finally
return rc; //Single return
}
When you are trying to see if it exists or no, you can do a
SELECT Count(*) FROM Table WHERE (...)
and this way 0 would means doesn't exists, other wise yes.

Secure website from SQL Injection ' using ASP.net and an Access database

I currently have a website with a normal registration and login, coded with ASP.net.
I am using an Access database, while using a C# class my friend wrote for handling most of the database actions (executeQuery, executeRead, isExits...).
Now that I've almost finished building my website, I want to start adding security - mostly to my database. I have searched for a while now for a tutorial on the subject, but I could not find anything good exept an old microsoft msdn article which I couldn't realy get its code to work.
The furthest I've got now is just no allowing any dangerous characters in the username and password, (such as ',--,;), but it kind of feels as if it is the worse solution that i can use (why shouldn't my users use this characters?).
I think that the best solution I've found is somehow insertion the variables into the query string after declaring it (something to do with "WHERE username=#user" or something like that), but i couldn't get it to work with Access and with my oleDBManager.
here is my current registration code. handle() is removing all ' from the string, and Validate() checks for dangerous parts in the string.
string username = user.Text;
string password = pass.Text;
bool isThingy = false;
if (handle(ref password)) isThingy = true;
if (handle(ref username)) isThingy = true;
if (username != "" && username != null)
{
if (password != "" && password != null)
{
if (Validate(username, password))
{
if ((db.IsExist("SELECT * FROM Table1 WHERE username='" + username + "'") == false))
{
int a = db.ExecuteQuery("INSERT INTO `Table1`(`username`, `password`, `logins`, `email`, `fname`, `lname`, `country`, `city`, `birthday`, `userid`) VALUES ('" + username + "', '" + password + "', '0', '', '', '', '', '', '', '" + Convert.ToString(Convert.ToInt32(db.ExecuteCellRead("SELECT MAX(userid) FROM Table1")) + 1) + "');");
if (!isThingy) errorLabel.Text = "Your user has been successfully registered";
else errorLabel.Text = "The ' token is invalid. your user was registered absence the '.";
}
else
errorLabel.Text = "This username is already taken";
}
else errorLabel.Text = "Invalid name format";
}
else errorLabel.Text = "Please enter a password";
}
else errorLabel.Text = "Please enter a user name";
as for the oleDBManager (named db in my code):
private OleDbConnection link; // The link instance
private OleDbCommand command; // The command object
private OleDbDataReader dataReader; // The data reader object
private OleDbDataAdapter dataAdapter; // the data adapter object
private DataTable dataTable; // the data table object
private string dbName; // the Database filename
private int version; // the usersTableG office version
private string connectionString; // the connection string for the database connection
private string provider; // the matching driver string for the connection string
private string path; // the path to the database file
...
public int ExecuteQuery(string query)
{
this.link.Open();
int rowsAffected;
// ---
this.command = new OleDbCommand(query, this.link);
try
{
rowsAffected = this.command.ExecuteNonQuery();
}
catch (InvalidOperationException e)
{
if (e.Data == null)
throw;
else
rowsAffected = -1;
}
finally
{
this.command.Dispose();
this.link.Close();
}
// ---
return rowsAffected;
}
public bool IsExist(string query)
{
this.link.Open();
// ---
this.command = new OleDbCommand(query, this.link);
this.dataReader = this.command.ExecuteReader();
bool a = this.dataReader.Read();
// ---
this.command.Dispose();
this.link.Close();
// ---
return a;
}
public string ExecuteCellRead(string query)
{
string output = "";
this.dataTable = this.ExcecuteRead(query);
foreach (DataRow row in this.dataTable.Rows)
{
foreach (object obj in row.ItemArray)
{
output += obj.ToString();
}
}
return output;
}
So, as you might see, the main problem is that the user now can not use characters as '.
It suppose the best solution would be using the # variables in the SQL queries, but I have no idea how.
[thanks for your help]
PS. i HAVE changed my tables' name ;)
edit: most of you are telling me to use these parameterized queries, but it would be great if you could give me an example of how to use them, since i've never done that
So, thanks to #Remou, my FINAL code is:
db.DoWeirdStackOverFlowStuff(
"INSERT INTO `Table1`(`username`, `password`, `logins`) VALUES (#username, #password, '0');"
, new string[] { "#username", "#password" }
, new string[] { username, password });
and
public int DoWeirdStackOverFlowStuff(string query, string[] vars, string[] reps)
{
this.link.Open();
int rowsAffected;
// ---
this.command = new OleDbCommand();
this.command.CommandText = query;
this.command.CommandType = System.Data.CommandType.Text;
this.command.Connection = this.link;
//Parameters in the order in which they appear in the query
for (int i = 0; i < vars.Length; i++)
this.command.Parameters.AddWithValue(vars[i], reps[i]);
try
{
rowsAffected = this.command.ExecuteNonQuery();
}
catch (InvalidOperationException e)
{
if (e.Data == null)
throw;
else
rowsAffected = -1;
}
finally
{
this.command.Dispose();
this.link.Close();
}
// ---
return rowsAffected;
}
for whoever needs this =]
Some notes
In MS Access, I have a saved query called UpdateUser, it looks like this:
UPDATE INTERNETSETTINGS
SET url = [#url],
databasename = [#databasename],
port = [#port],
username = [#username],
[password] = [#password]
I can refer to this query by name in my code, using a command object:
OleDbCommand Command = new OleDbCommand();
Command.CommandText = "UpdateUser"; //saved query
Command.CommandType = System.Data.CommandType.StoredProcedure;
Command.Connection = cn; //a connection to the database
//Parameters in the order in which they appear in the query
Command.Parameters.AddWithValue("#url", "a"); //a,b,c etc for my test run
Command.Parameters.AddWithValue("#databasename", "b");
Command.Parameters.AddWithValue("#port","c");
Command.Parameters.AddWithValue("#username", "d");
Command.Parameters.AddWithValue("#password", "e");
Command.ExecuteNonQuery();
I don't remember whether Access does the same thing as SQL Server here, but in SQL Server you can escape the single quote mark by doubling it:
username = username.Replace("'", "''");
So you can include single-quote marks in the string, you can store them in the database, and they can't be used as malicious string terminators.

Incorrect and duplicated results from a sqlite fts3 unionQuery

I'm getting results from my rawQuery that duplicate and follow an OR logic as opposed to an AND logic i.e. I will get all the entries that contain "tuxedo" as well as all the entries that contain "hotel" when I only want the ones that contain both.
This is my method:
public ArrayList<Integer> getAdvancedResultIDList(String[] search)
{
ArrayList<String> queryList = new ArrayList<String>();
ArrayList<Integer> resultsList = new ArrayList<Integer>();
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
this.mDB = GamesList.mDBHelper.getDatabase();
Cursor searchCursor = null;
try
{
//TODO:
// for each string in the search array search the whole of searchable table. Check that the results are only of the values that
// contain all the search strings, and add the id of that row to the results ArrayList
for(int i = 0; i < search.length; i++)
{
String query;
String s = '"' + search[i] + '"';
query = "SELECT " + KEY_ID + " FROM "+ SEARCHABLE_TABLE + " WHERE " + SEARCHABLE_TABLE + " MATCH " + s;
queryList.add(query);
}
String[] queryArray = queryList.toArray(new String[queryList.size()]);
String unionQuery = builder.buildUnionQuery(queryArray, KEY_ID + " ASC", null);
searchCursor = this.mDB.rawQuery(unionQuery, null);
int colId = searchCursor.getColumnIndex(KEY_ID);
String resultID;
for(searchCursor.moveToFirst(); !searchCursor.isAfterLast();searchCursor.moveToNext())
{
resultID = searchCursor.getString(colId);
Integer Id = Integer.parseInt(searchCursor.getString(colId));
resultsList.add(Id);
}
searchCursor.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
this.mDB.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
return resultsList;
}
Thanks in advance and Happy New Year!
The documentation explains how to use multiple search terms:
SELECT id FROM searchTable WHERE searchTable MATCH 'tuxedo hotel'

Session variable accessibility

I have a class which creates a session the following way:
Session["UserId"] = UserId; // UserId = 1
In one of the pages on Page_Load, I retrieve the session variable value this way which works fine:
if (Session["UserId"] != null){
var userid = Session["UserId"];
Welcome.Text = "Hello, " + userid;
}
Now I need to use the value of the session variable in my classes as well. I used the following method to get the session value int useridsession = Convert.ToInt32(HttpContext.Current.Session["UserId"]); but it always returns null whereas the session is correctly read using Session["UserId"]; in my code behind file.
The mentioned class:
public static DataTable ManageBookingsDataTable()
{
int useridsession = Convert.ToInt32(HttpContext.Current.Session["UserId"]);
SqlConnection con = new SqlConnection(Database.ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("select bookings.id,user_id, start_date, end_date, pets.name AS 'Pet name' from bookings AS bookings left join users AS usr ON bookings.user_id=usr.id AND bookings.user_id=1 left join pets AS pets ON pets.id=bookings.pet_id WHERE bookings.user_id=#userid_session", con);
cmd.Parameters.AddWithValue("#userid_session", useridsession);
SqlDataAdapter sqlDa = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
string id = string.Empty;
string name = string.Empty;
string startdate = string.Empty;
string enddate = string.Empty;
string full_string = string.Empty;
sqlDa.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
id = dt.Rows[i]["id"].ToString();
var sdate = dt.Rows[i]["start_date"];
name = dt.Rows[i]["Pet name"].ToString();
startdate = dt.Rows[i]["start_date"].ToString();
enddate = dt.Rows[i]["end_date"].ToString();
full_string = startdate + " to " + enddate + " (" + name + ")";
//CurrentBookings.Items.Add(new ListItem(full_string, id));
}
}
return dt;
}
I diagnosed the problem by adding HttpContext.Current.Session["UserId"] = 1; which proves that when I set the session in the same class, the method works.
My question is how do I access the previously created session from any class?
Session should be available for the session regardless of the class. Why don't you set and get
your session values using the same class? All your session stuff in a one place so it is more neat and tidy as well.
Local.MySession.UserId = UserId; //Set here
int myUserId = Local.MySession.UserId; //Get here
//Something like this??
namespace Local
{
//You can add all session variables to this class
public class MySession
{
public static int UserId
{
get
{
return Convert.ToInt32(HttpContext.Current.Session["userId"] ?? "0");
}
set { HttpContext.Current.Session["userId"] = value.ToString(); }
}
public static string UserEmail //For Example another session variable
{
get { return HttpContext.Current.Session["email"] ?? ""; }
set { HttpContext.Current.Session["email"] = value; }
}
}
}

Resources