Unable to use SQLite in React Native - database

I'm trying to use SQLite in my react-native project.
This is my sample code. I can open my database, but can't bring data from db.
Some people said SQLite does not work for SDK version 30. Maybe this is the problem
result
My code:
SQLite.DEBUG(true);
SQLite.enablePromise(true);
let db;
openDB = ()=>{SQLite.openDatabase(
{
name: 'recipe.db',
createFromLocation: 1,
},
(DB) => {
console.log('success opening recipe.db')
db = DB;
db.transaction((tx) => {
tx.executeSql(`SELECT * FROM recipe;`, [], (tx, results) => {
const rows = results.rows;
for (let i=0; i<rows.length; i++) {
console.log(rows.item(i));
}
})
})
},
error => {
console.error(error);
}
);
}

Related

Storing base64 image within expo-sqlite results in 'null' reading database entries

Within my Android/iOS React Native (Expo managed) app I want a database to store my images which I encode to base64. Because I am using Expo, I use expo-sqlite within my React Native app. I initialize my database within my classes (extends Component) constructor the following
constructor(props){
super(props);
this.state = {
db: null,
...
}
}
and within my ComponentDidMount I initialize the database with
async setupDB() {
const db = SQLite.openDatabase('database.db');
this.setState({db});
db.transaction( tx=> {
tx.executeSql(
'CREATE TABLE IF NOT EXISTS mytable (id INTEGER PRIMARY KEY AUTOINCREMENT, image BLOB)',
[],
(_, result) => {
console.log('success');
}, (_, error) => {
console.error(error);
},
);
});
}
I stuff my image into the DB using the following code
async toDB(image) {
const { db } = this.state;
try {
await db.transaction( tx=> {
tx.executeSql(
'INSERT INTO mytable (image) values (?)',
[image],
(_, result) => {
console.log('success');
}, (_, error) => {
console.error(error);
},
);
});
} catch (error) { console.error(error); }
}
And afterwards I print the data using the following function
async printDB() {
const { db } = this.state;
try {
await db.transaction( tx=> {
tx.executeSql(
'SELECT * FROM mytable',
[image],
(_, result) => {
const rows = result.rows;
for(let i = 0; i < rows.length; i++) {
console.log(rows.item(i).image); // this only prints null using the full length base64 image
}
console.log('success');
}, (_, error) => {
console.error(error);
},
);
});
} catch (error) { console.error(error); }
}
But when I reduce the length of my base64 image to e.g. 1/4 of its original length, it seems to be stored correctly. Printing out the length of my base64 console.log(image.length); results in 9188676 which should fit a row within the SQLite database as far as I know. I can also reproduce this using a String consisting only 0, so it is not related to the base64 encoding.
So here is my question, am I doing anything wrong here or do I have to use another database/technique to store my base64 images into the database?
EDIT1:
I am using a workaround as I saw that quartering the base64 image works within the database table. Therefore I store every quarter with an identical name, so I have to read all four identical "name" entries and concatenate the strings together afterwards.

How can i get the name of images and use the images

In product page, I want to get all images path that are in a specific folder and send those to client side, so I can use them in client side by passing the paths to Image component of next js. I tried this when I was developing my app via running npm run dev and it was successful. Then I pushed the changes to my GitHub repository and vercel built my app again. Now, when I go to the product page, I get an error from the server. I tried some ways to fix this problem, but I couldn't fix that. For example, I tried changing my entered path in readdir, but the problem didn't fix. Here are my codes:
const getPagePhotosAndReview = async (productName) => {
const root = process.cwd();
let notFound = false;
const allDatas = await fs
.readdir(root + `/public/about-${productName}`, { encoding: "utf8" })
.then((files) => {
const allDatas = { pageImages: [], review: null };
files.forEach((value) => {
const image = value.split(".")[0];
const imageInfos = {
src: `/about-${productName}/${value}`,
alt: productName,
};
if (Number(image)) {
allDatas.pageImages.push(imageInfos);
}
});
return allDatas;
})
.catch((reason) => (notFound = true));
if (notFound) return 404;
await fs
.readFile(root + `/public/about-${productName}/review.txt`, {
encoding: "utf-8",
})
.then((value) => {
allDatas.review = value;
})
.catch((reason) => {
allDatas.review = null;
});
return allDatas;
};
export async function getServerSideProps(context) {
if (context.params.product.length > 3) {
return { notFound: true };
}
if (context.params.product.length < 3) {
const filters = {
kinds: originKinds[context.params.product[0]] || " ",
};
if (context.params.product[1]) filters.brands = context.params.product[1];
const products = getFilteredProducts(filters, true);
if (products.datas.length === 0) {
return {
notFound: true,
};
}
return {
props: {
products: { ...products },
},
};
}
if (context.params.product.length === 3) {
const filters = {
path: context.resolvedUrl,
};
const product = getFilteredProducts(filters, false);
if (product.length === 0) {
return {
notFound: true,
};
}
const splitedPath = product[0].path.split("/");
const pagePhotosAndReview = await getPagePhotosAndReview(
splitedPath[splitedPath.length - 1]
);
if (pagePhotosAndReview === 404) return { notFound: true };
product[0] = {
...product[0],
...pagePhotosAndReview,
};
product[0].addressArray = [
textOfPaths[context.params.product[0]],
textOfPaths[context.params.product[1]],
];
return {
props: {
product: product[0],
},
};
}
}
This is the base code and I tried some ways but couldn't fix the problem. So to fix this problem, I want to ask: how can I get the name of all images in a specific directory and then use those images in client side? And errors that I get: if I go to a page directly and without going to the home of the website, I get internal server error with code of 500 and when I go to a page of my website, and then I go to my product page, I get
Application error: a client-side exception has occurred (see the browser console for more information).
And I should say that I know I should remove public from paths when I want to load an image from public folder. I did it but I still get error.

react-native SQLite-storage INSERT statement

I use react-native react-native-sqlite-storage in my project and I am struggling to insert data
I managed to successfully read the pre populated table I created in
./android/app/src/main/assets/Mydb.db
but the INSERT statement somehow does not work.
simplified sample code:
import React, { Component } from 'react';
import SQLite from 'react-native-sqlite-storage';
let db;
class App extends Component {
constructor(props) {
// SQLite connection / config settings
db = SQLite.openDatabase({ name: 'testTable', //Name of my table
createFromLocation: "~MyDB.db", // Name of my DB
});
}
selectExample = () => { // working
db.transaction((tx) => {
tx.executeSql('SELECT * FROM testTable', [], (tx, results) => {
console.log("Query completed");
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
console.log(`My AWG: ${row.AWG}, My Metric: ${row.metric}`);
}
});
});
}
updateDatabase = () => { // not working
db.transaction((tx) => {
tx.executeSql('Insert into testTable (AWG, metric) VALUES (?,?)',
[28,0.5],
(tx,results) => {
console.log("Results", results.rowsAffected);
},(err) => {
console.error(err);
}
)
})
}
onPress = () => {
this.selectExample(); // working
this.updateDatabase(); // issue
}
render() {
return (
<View>
<TouchableOpacity style = {styles.button} onPress={() => this.onPress() } />
</View>
);
}
in the console I get Results 1 as feedback, so the query seems fine but when I open MyDB.db with the mac app: DB Browser for SQLite, no changes happened no new rows..
Am I missing something here?

Sample Database Connection to SQLite Database in Cypress

I ran into an issue when connecting to a SQLite Database before. Now that I figured it out, I'd like to share the solution with everyone. Thanks.
In plugins/index.js
const sqlite3 = require('sqlite3').verbose();
module.exports = (on, _config) => {
on('task', {
queryDb: queryTestDb,
//wait: timeout,
});
};
Also in plugins/index.js
const path='C:/Users/Mamga/TestDB/chinook.db'
function queryTestDb(sql) {
let db = new sqlite3.Database(path);
return new Promise((resolve, reject) => {
db.all(sql, [], (err, rows) => {
if(err)
reject(err);
else {
db.close();
console.log(rows)
return resolve(rows);
}//End else
});//End db.run
});
}
Actual Test in TaskCommandDBConnectionTest.js ///
/// <reference types="Cypress" />
describe('Task Command', () => {
it('Should send execute something on node', () => {
const query='select * from Persons';
cy.task('queryDb', query).then((rows) => {
//expect(rows).to.have.lengthOf(4);
for(var i=0; i<rows.length; i++)
{
cy.log(rows[i].FirstName + " "+ rows[i].LastName + " " + rows[i].Age)
}
});
})
})
Might be related to a bugfix in cypress 5.3.0:
"Fixed an issue where a cy.task with no arguments passed would receive null as the first argument instead of undefined"
https://docs.cypress.io/guides/references/changelog.html#5-3-0

Cannot read property 'transaction' of undefined . React Native

I am new to React-Native and I was following the steps on the react-native-sqlite-storage on GitHub but I am unfortunately stuck on the transaction and I've tried enablePromises but it still doesn't work. I am kind of at loss on how to proceed.
import React from 'react';
import SQLite from 'react-native-sqlite-storage';
import { StyleSheet, Text, View, ListItem } from 'react-native';
export default function App() {
let db = SQLite.openDatabase(
{
name: 'users',
createFromLocation: 1,
},
successToOpenDB(),
failToOpenDB()
);
function successToOpenDB() {
db.transaction((tx) => {
tx.executeSql('SELECT * FROM USERS', [], (tx, results) => {
let dataLength = results.row.length;
alert(dataLength);
});
});
}
function failToOpenDB(err) {
console.log(err);
}
return (
<>
<View style={styles.header}>
<Text style={styles.headerText}>Title</Text>
</View>
</>
);
};
Thanks!
You are passing the success callback successToOpenDB function while making a connection to db and using "db" which is undedined and u are getting error "cannot read property transaction of undefined.So do not pass successToOpenDB funtion as a success callback.
errorCB(err) {
console.log("SQL Error: " + err);
},
successCB() {
console.log("SQL executed fine");
},
openCB() {
console.log("Database OPENED");
},
var db = SQLite.openDatabase({
name: 'users',
createFromLocation: 1,
}, openCB, errorCB);
db.transaction((tx) => {
tx.executeSql('SELECT * FROM Employees a, Departments b WHERE a.department = b.department_id', [], (tx, results) => {
console.log("Query completed");
// Get rows with Web SQL Database spec compliance.
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`);
}
// Alternatively, you can use the non-standard raw method.
/*
let rows = results.rows.raw(); // shallow copy of rows Array
rows.map(row => console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`));
*/
});
});

Resources